构建微服务的利器

简单介绍

  • 减少了使用Spring的时候的复杂的配置。
  • 底层基于Spring框架。
  • Web开发使用SpringMVC。

Spring Boot也是Spring生态中一个极其重要的项目,Spring Boot是对Spring Framework的扩展,也可以说它是是一个服务于框架的框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程。服务范围是简化配置文件,它消除了设置Spring应用程序所需的XML配置,即尽可能的自动配置Spring应用,同时直接嵌入Tomcat、Jetty或Undertow(无需部署WAR文件),提供生产就绪功能,例如指标、运行状况检查和外部化配置等等,为更快和更高效的开发应用程序铺平了道路。

https://start.spring.io/ 在线直接生成基础项目代码当前 Spring Boot 3.1.3,可以使用Maven、Gradle来管理项目。

plugins {
	id 'java'
	id 'org.springframework.boot' version '3.1.3'
	id 'io.spring.dependency-management' version '1.1.3'
}
 
group = 'cn.duchaoqun'
version = '0.0.1-SNAPSHOT'
 
java {
	sourceCompatibility = '17'
}
 
repositories {
	maven { url 'https://maven.aliyun.com/repository/public/' }
	maven { url 'https://repo.spring.io/snapshot' }
	maven { url 'https://repo.spring.io/milestone' }
	mavenCentral()
}
 
dependencies {
	// Web project needs this.
	implementation 'org.springframework.boot:spring-boot-starter-web'
	testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
 
tasks.named('test') {
	useJUnitPlatform()
}
 

dependencies

// Web 相关的注解
implementation 'org.springframework.boot:spring-boot-starter-web'

Controller

package cn.duchaoqun.demo;
 
 
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
 
@RestController
public class TestController {
 
    //@RequestMapping("/hello")
    @GetMapping("/hello")
    public String Hello(){
        return "Hello";
    }
}
 

Test

package cn.duchaoqun.controller;  
  
import jakarta.annotation.Resource;  
import org.junit.jupiter.api.Test;  
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;  
import org.springframework.boot.test.context.SpringBootTest;  
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;  
  
import static org.hamcrest.Matchers.equalTo;  
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;  
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;  
  
 
@SpringBootTest  
@AutoConfigureMockMvc  
class HelloControllerTests {  
  
    @Resource  
    private MockMvc mockMvc;  
  
    @Test  
    void testHello() throws Exception{  
        mockMvc.perform(MockMvcRequestBuilders.get("/hello")  
                        .accept(MediaType.APPLICATION_JSON)  
                ).andExpect(status().isOk())  
                .andExpect(content().string(equalTo("Hello")));  
    }  
  
}

发布

生成可以执行的jar包,然后再目标环境执行 java -jar xxx.jar 的方式来运行。

./gradlew build

VO, DO, PO, DTO

  • VO(View Object):视图对象,用于展示层,它的作用是把某个指定页面(或组件)的所有数据封装起来,用来在View层和Controller层传递数据。
  • DO(Domain Object):领域对象,就是从现实世界中抽象出来的有形或无形的业务实体。
  • DTO(Data Transfer Object):数据传输对象,这个概念来源于J2EE的设计模式,原来的目的是为了EJB的分布式应用提供粗粒度的数据实体,以减少分布式调用的次数,从而提高分布式调用的性能和降低网络负载,但在这里,我泛指用于展示层与服务层之间的数据传输对象。
  • PO(Persistent Object):持久化对象,它跟持久层(通常是关系型数据库)的数据结构形成一一对应的映射关系,如果持久层是关系型数据库,那么,数据表中的每个字段(或若干个)就对应PO的一个(或若干个)属性。

service

  • 每一个DO定义一个service接口,用来被Spring依赖注入。
  • 创建接口的实现类,返回页面需要的VO,然后Controller中进行调用。
  • 创建Controller 返回对应的VO对象。

Controller

@RestController

控制器注解

@RequestMapping("/hello")

路径映射注解,标注Controller。

@GetMapping()

修饰方法,配置URL地址,和获取地址中的参数。

@GetMapping()  
public String Hello(){  
    return "根路径";  
}  
 
@GetMapping("/hello")  
public String Hello(){  
    return "Hello";  
}  
 
@GetMapping("/api/{pathParameter}")  
public String getSomething(@PathVariable("pathParameter") String param){  
    System.out.println(param);  
    return "Something";  
}

@PostMapping()

前端提交的表单是以application/x-www-form-urlencoded;charset=UTF-8 提交的,它是健值对形式的,用 @RequestParam 来接收参数

@PostMapping("/save")  
public ModelAndView save(@RequestParam Map<String,String> params, Model model) {  
    User user = new User();  
    user.setUsername(params.get("username"));  
    user.setPassword(params.get("password"));  
    user.setFullName(params.get("fullName"));  
    user.setEmail(params.get("email"));  
    user.setPhone(params.get("phone"));  
    userRepository.save(user);  
    model.addAttribute("user", user);  
    return new ModelAndView("user/show", "params", model);  
}

ModelAndVIew

 
// 跳转到其他页
return new ModelAndView("redirect:/user/index");

src/main/resources

templates

可以存放thymeleaf的模板,记得添加引用内容。

<!DOCTYPE html>  
<html lang="en"  
      xmlns:th="http://www.thymeleaf.org"  
      xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">  
<head>  
    <meta charset="UTF-8">  
    <title>Title</title>  
</head>  
<body>  
  
</body>  
</html>

static

存放静态资源 static/js static/css static/image

使用redis

key-value 的数据缓存服务

	// data redis
	implementation 'org.springframework.boot:spring-boot-starter-data-redis'

使用缓存数据

package cn.duchaoqun.demo.service;
 
 
import cn.duchaoqun.demo.vo.InfoVO;
import jakarta.annotation.Resource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;
 
import java.util.concurrent.TimeUnit;
 
@Service
public class WeatherServiceImpl implements WeatherService{
 
    private final static Logger logger = LoggerFactory.getLogger(WeatherServiceImpl.class);
    @Resource
    private StringRedisTemplate stringRedisTemplate;
 
 
    @Override
    public String getInfo() {
 
        InfoVO infoVO = new InfoVO();
        infoVO.setCode(200);
        infoVO.setMessage("TestInfo");
 
        String body = "";
 
        String key = "hello";
        ValueOperations<String, String> valueOperations = stringRedisTemplate.opsForValue();
        if (stringRedisTemplate.hasKey(key)){
            logger.info("Redis has Data!");
            body = valueOperations.get(key);
            return body;
        } else {
            logger.info("Redis not found data!");
            body = "New Data!";
            // 设置存入缓存的失效时间,正常应该30分钟左右
            valueOperations.set(key,body, 10, TimeUnit.SECONDS);
            return body;
        }
    }
}
 

注解

@Bean

method注解,Indicates that a method produces a bean to be managed by the Spring container.

Quartz

  • 先创建一个Job类,执行具体的任务。
package cn.duchaoqun.demo.quartz;  
  
import org.quartz.JobExecutionContext;  
import org.quartz.JobExecutionException;  
import org.slf4j.Logger;  
import org.slf4j.LoggerFactory;  
import org.springframework.scheduling.quartz.QuartzJobBean;  
  
public class FirstJob extends QuartzJobBean {  
  
    private static Logger logger = LoggerFactory.getLogger(FirstJob.class);  
  
    @Override  
    protected void executeInternal(JobExecutionContext context) throws JobExecutionException {  
        logger.info("Quartz Job....");  
    }  
}
  • 再创建一个配置类,加载上面创建好的Job
package cn.duchaoqun.demo.config;  
  
import cn.duchaoqun.demo.quartz.FirstJob;  
import org.quartz.*;  
import org.springframework.context.annotation.Bean;  
import org.springframework.context.annotation.Configuration;  
  
@Configuration  
public class QuartzConfiguration {  
    // Job Detail  
    @Bean  
    public JobDetail firstJob() {  
        return JobBuilder.newJob(FirstJob.class)  
                .withIdentity("First Job.")  
                .storeDurably()  
                .build();  
    }  
    // Trigger  
    @Bean  
    public Trigger firstJobTrigger(){  
  
        SimpleScheduleBuilder schedBuilder = SimpleScheduleBuilder  
                .simpleSchedule()  
                .withIntervalInSeconds(2)  
                .repeatForever();  
  
        return TriggerBuilder.newTrigger().forJob(firstJob())  
                .withIdentity("First Job Trigger")  
                .withSchedule(schedBuilder)  
                .build();  
    }  
}