SpringBoot快速入门

虽然我的工作中更多的是与数据库打交道,但是作为一个 Coder,我觉得掌握前后端的 Web技术来说是非常有必要的。

不仅可以帮助我们在工作中更好的理解其他岗位与你对接的人他的工作痛点,也能在公司需要人手的时候成为一个有力的应急帮手,比如之前公司的数据中台我就参与架构和部分开发任务,更重要的是我私下里可以运用一些快速框架来搭建一些有意思的网站,比如我的个人主页个人博客都是我自学 javajs所做出来的作品。

MVC

使用xml还是注解

@Component 组件没有明确规定其角色,作用在类级别上声明当前类为一个业务组件,被 Spring IOC 容器维护
@Service 在业务逻辑层(Service)类级别进行声明
@Registory 在数据访问层(Dao)类级别进行声明
@Controller 在展现层(MVC)使用,标注当前类为一个控制器

@Autowired 它可以对类成员变量、方法及构造函数进行标注,完成自动装配的工作,通过 @Autowired的使用来消除set、get方法
@Inject 作用同上,是 JSR-330 标准
@Resource 作用同上,是 JSR-250 标准
以上三种注解在Set方法或属性上声明,一般情况下更习惯声明在属性上,代码简洁清晰

@Configuration 将当前类声明为一个配置类,相当于一个xml配置文件
@ComponentScan 自动扫描包下标注有@Repository @Service @Controller
@Component 注解的类并有 Spring IOC 容器进行实例化和维护
@Bean 作用于方法上,声明当前方法的返回值是一个 Bean&#x5BF9;&#x8C61;,相当于 xml&#x6587;&#x4EF6;<bean></bean>声明当前方法返回一个 bean&#x5BF9;&#x8C61;
@Value 获取 properties&#x6587;&#x4EF6;指定的 key/value

作用是添加坐标相关配置,主要是各种依赖jar包

所谓元注解其实就是可以注解到别的注解上的注解,被注解的注解称之为组合注解,组合注解具备元注解的功能,主要的作用是消除重复注解

习惯大于配置目标

Spring Boot 的目标是快速运行,快速创建web应用,并独立机型部署(jar包方式,war包方式),相比于Spring框架是全新重写的框架

核心配置

主要是通过修改 /src/main/resources目录下的 banner.txt文件,如果没有则默认使用SpringBoot初始Banner
可以个性化制作Banner的网站制定相应的txt文件

默认是 application.properties或者 application.yml
坐标依赖都配置在 pom.xml中,如果添加了依赖以后标红可以使用 Maven -> Reload project即可

@SpringBootConfiguration 本身是一个配置类,启动类启动的时候会加载
@EnableAutoConfiguration 组合了 @AutoConfigurationPackage& @Import(AutoConfigurationImportSelector.class)
@AutoConfigurationPackage 底层是一个@Import(AutoConfigurationPackage.Registrar.class),其会把启动类的包下组合都扫描到Spring容器中
@AutoConfigurationImportSelector 读取大量的自动配置类,完成自动配置,其读取的是classpath下的 META-INF/spring.factories下的配置文件

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(
    excludeFilters = {@Filter(
    type = FilterType.CUSTOM,
    classes = {TypeExcludeFilter.class}
), @Filter(
    type = FilterType.CUSTOM,
    classes = {AutoConfigurationExcludeFilter.class}
)}
)

通过在 application.yml中设置 spring.profiles.active=test/dev/prod来动态切换不同环境,例如:

&#x5F00;&#x53D1;&#x73AF;&#x5883;&#x914D;&#x7F6E;&#x6587;&#x4EF6;
application-dev.yml
server:
  prot: 8098

&#x6D4B;&#x8BD5;&#x73AF;&#x5883;&#x914D;&#x7F6E;&#x6587;&#x4EF6;
application-test.yml
server:
  prot: 8097

&#x751F;&#x4EA7;&#x73AF;&#x5883;&#x914D;&#x7F6E;&#x6587;&#x4EF6;
application-prod.yml
server:
  prot: 8099

&#x4E3B;&#x914D;&#x7F6E;&#x6587;&#x4EF6;
application.yml
spring:
  profiles:
    active: dev

SpringBoot默认使用 LogBack日志系统,一般主流的日志都是用 log4j日志系统

事务控制

全局异常

可以参考文章————Springboot系列-@ControllerAdvice使用 详细学习,这里后期会补上说明
此注解其实是一个增强的 Controller,使用这个 Controller,可实现三个方面的功能,因为这是SpringMVC提供的功能,所以可以在springboot中直接使用

package com.fx67ll.springboot.exceptions;

import com.fx67ll.springboot.po.vo.ResultInfo;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

@ControllerAdvice
public class TestGlobalExceptionHandler {
    @ExceptionHandler(value = Exception.class)
    @ResponseBody
    public ResultInfo exceptionHandler(Exception exception) {
        ResultInfo resultInfo = new ResultInfo();
        resultInfo.setCode(978);
        resultInfo.setMsg("&#x5168;&#x5C40;&#x5F02;&#x5E38;&#x62E6;&#x622A;&#xFF0C;&#x64CD;&#x4F5C;&#x5931;&#x8D25;&#xFF01;");
//        if (exception instanceof ParamsException) {
//            ParamsException paramsException = (ParamsException) exception;
//            resultInfo.setMsg(paramsException.getMsg());
//            resultInfo.setCode(paramsException.getCode());
//        }
        return resultInfo;
    }
}

数据校验

数据的校验是交互式网站一个不可或缺的功能,前端的 js&#x6821;&#x9A8C;可以涵盖大部分的校验职责,如用户名唯一性,生日格式,邮箱格式校验等等常用的校验。
但是一般前端传来的数据是不可信的,前端校验过了,后端也应该重新校验,因为不排除用户绕过浏览器直接通过 Http&#x5DE5;&#x5177;向后端请求的情况。
所以服务端的数据校验也是必要的,可以防止脏数据落到数据库中,如果数据库中出现一个非法的邮箱格式,也会让运维人员头疼不已。

@Null:被注释的元素必须为 null
@NotNull:被注释的元素不能为 null,可以为空字符串
@AssertTrue:被注释的元素必须为 true
@AssertFalse:被注释的元素必须为 false
@Min(value):被注释的元素必须是一个数字,其值必须大于等于指定的最小值
@Max(value):被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@DecimalMin(value):被注释的元素必须是一个数字,其值必须大于等于指定的最小值
@DecimalMax(value):被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@Size(max,min):被注释的元素的大小必须在指定的范围内
@Digits(integer,fraction):被注释的元素必须是一个数字,其值必须在可接受的范围内
@Past:被注释的元素必须是一个过去的日期
@Future:被注释的元素必须是一个将来的日期
@Pattern(value):被注释的元素必须符合指定的正则表达式
@Email:被注释的元素必须是电子邮件地址
@Length:被注释的字符串的大小必须在指定的范围内
@Range:被注释的元素必须在合适的范围内
@URL:被注解的元素必须是一个 URL
@NotEmpty:用在集合类上,不能为 null,并且长度必须大于0
@NotBlank:只能作用在 String上,不能为 null,而且调用 trim()后,长度必须大于0

静态资源

默认配置下,我们可以在 resources资源目录下存放web应用静态资源文件
自定义静态资源路径,可以通过在 spring.resources.static-locations后面追加一个配置 classpath:/&#x4F60;&#x81EA;&#x5B9A;&#x4E49;&#x7684;&#x914D;&#x7F6E;&#x76EE;&#x5F55;/,例如:

application.yml
spring:
  resources:
    # &#x591A;&#x4E2A;&#x76EE;&#x5F55;&#x4F7F;&#x7528;&#x9017;&#x53F7;&#x9694;&#x5F00;
    static-loaction: classpath:/public/,classpath:/static/,classpath:/fx67ll/

打包和部署

热部署,就是在应用正在运行的时候升级软件,却不需要重新启动应用,主要应用在开发过程中

单元测试

<!--单元测试-->
<dependency>
    <groupid>org.springframework.boot</groupid>
    <artifactid>spring-boot-starter-test</artifactid>
    <scope>test</scope>
</dependency>

需要注意的是:

&#x793A;&#x4F8B;&#x4EE3;&#x7801;
package com.fx67ll.springboot.service;

import com.fx67ll.springboot.Starter;
import com.fx67ll.springboot.po.User;
import com.fx67ll.springboot.query.UserQuery;
import com.fx67ll.springboot.srevice.UserService;
import com.github.pagehelper.PageInfo;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import javax.annotation.Resource;

/**
 * Service&#x4E1A;&#x52A1;&#x65B9;&#x6CD5;&#x6D4B;&#x8BD5;
 *
 * Junit&#x4E2D;&#x7684;RunWith&#x6CE8;&#x89E3; &#x8868;&#x793A;&#x8BE5;&#x7C7B;&#x662F;&#x5355;&#x5143;&#x6D4B;&#x8BD5;&#x7684;&#x6267;&#x884C;&#x7C7B;
 * SpringRunner &#x662F; spring-test &#x63D0;&#x4F9B;&#x7684;&#x6D4B;&#x8BD5;&#x6267;&#x884C;&#x5355;&#x5143;&#x7C7B;&#xFF08;&#x662F;Spring&#x5355;&#x5143;&#x6D4B;&#x8BD5;&#x4E2D;SpringJUnit4ClassRunner&#x7684;&#x65B0;&#x540D;&#x5B57;&#xFF09;
 * SpringBootTest&#x6CE8;&#x89E3; &#x662F;&#x6267;&#x884C;&#x6D4B;&#x8BD5;&#x7A0B;&#x5E8F;&#x7684;&#x5F15;&#x5BFC;&#x7C7B;
 */
@RunWith(SpringRunner.class)
@SpringBootTest(classes = {Starter.class})
public class TestUserService {

    // &#x65E5;&#x5FD7;&#x7684;&#x4F7F;&#x7528;
    private Logger logger = LoggerFactory.getLogger(TestUserService.class);

    @Resource
    private UserService userService;

    @Before
    public void before() {
        logger.info("&#x5355;&#x5143;&#x6D4B;&#x8BD5;&#x5F00;&#x59CB;......");
    }

    @Test
    public void testQueryUserById() {
        logger.info("&#x6D4B;&#x8BD5;&#x6839;&#x636E;&#x7528;&#x6237;id&#x67E5;&#x8BE2;......");

        User user = userService.queryUserById(1);
        logger.info("&#x7528;&#x6237;&#x8BB0;&#x5F55;: {}", user.toString());
    }

    @Test
    public void testSelectUserListByParams() {
        logger.info("&#x6D4B;&#x8BD5;&#x6839;&#x636E;&#x5206;&#x9875;&#x6761;&#x4EF6;&#x67E5;&#x8BE2;&#x7528;&#x6237;&#x5217;&#x8868;......");

        UserQuery userQuery = new UserQuery();
        PageInfo<user> pageInfo = userService.selectUserListByParams(userQuery);
        logger.info(pageInfo.toString());
    }

    @After
    public void after() {
        logger.info("&#x5355;&#x5143;&#x6D4B;&#x8BD5;&#x7ED3;&#x675F;......");
    }
}
</user>

MockMvc是由 spring-test包提供,实现了对 Http&#x8BF7;&#x6C42;的模拟,能够直接使用网络的形式,转换到 Controller的调用,使得测试速度快、不依赖网络环境。
同时提供了一套验证的工具,结果的验证十分方便

提供一个唯一的 build&#x65B9;&#x6CD5;,用来构造 MockMvc
主要有两个实现: StandaloneMockMvcBuilderDefaultMockMvcBuilder,分别对应两种测试方式,
即独立安装和集成Web环境测试(并不会集成真正的 web&#x73AF;&#x5883;,而是通过相应的 Mock API进行模拟测试,无须启动服务器)。
MockMvcBuilders提供了对应的创建方法 standaloneSetup方法和 webAppContextSetup方法,在使用时直接调用即可。

&#x793A;&#x4F8B;&#x4EE3;&#x7801;
PS&#xFF1A;&#x867D;&#x7136;&#x63D0;&#x793A;&#x6D4B;&#x8BD5;&#x901A;&#x8FC7;&#xFF0C;&#x4F46;&#x662F;&#x63A7;&#x5236;&#x53F0;&#x4E00;&#x76F4;&#x6CA1;&#x6709;&#x6253;&#x5370;&#x51FA;&#x8FD4;&#x56DE;&#x4FE1;&#x606F;&#x7684;&#x8BB0;&#x5F55;&#xFF0C;&#x540E;&#x671F;&#x6709;&#x7A7A;&#x770B;&#x770B;
package com.fx67ll.springboot.controller;

import com.fx67ll.springboot.Starter;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.ResultActions;
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;

@RunWith(SpringRunner.class)
@SpringBootTest(classes = {Starter.class})
@AutoConfigureMockMvc
public class TestUserController {

    // &#x65E5;&#x5FD7;&#x7684;&#x4F7F;&#x7528;
    private Logger logger = LoggerFactory.getLogger(TestUserController.class);

    @Autowired
    private MockMvc mockMvc;

    /**
     * &#x6A21;&#x62DF;&#x6D4B;&#x8BD5;&#x7528;&#x6237;&#x5217;&#x8868;&#x67E5;&#x8BE2;
     * &#x5176;&#x5B9E;&#x5C31;&#x5728;&#x6A21;&#x62DF;&#x771F;&#x5B9E;&#x73AF;&#x5883;&#x4E0B;&#x524D;&#x7AEF;&#x5BF9;&#x540E;&#x7AEF;&#x53D1;&#x8D77;&#x7684;&#x8BF7;&#x6C42;
     */
    @Test
    public void apiTestSelectUserListByParams() throws Exception {

        logger.info("&#x5F00;&#x59CB;&#x6A21;&#x62DF;&#x53D1;&#x9001;&#x67E5;&#x8BE2;&#x7528;&#x6237;&#x5217;&#x8868;&#x7684;&#x8BF7;&#x6C42;......");

        // &#x6784;&#x5EFA;&#x8BF7;&#x6C42;
        MockHttpServletRequestBuilder requestBuilder = MockMvcRequestBuilders.get("/user/list")
                .contentType("text/html") // &#x8BBE;&#x7F6E;&#x8BF7;&#x6C42;&#x5934;&#x4FE1;&#x606F;
                .accept(MediaType.APPLICATION_JSON); // &#x8BBE;&#x7F6E;&#x8BF7;&#x6C42;Accept&#x5934;&#x4FE1;&#x606F;

        // &#x53D1;&#x9001;&#x8BF7;&#x6C42;
        ResultActions perform = mockMvc.perform(requestBuilder);

        // &#x6821;&#x9A8C;&#x8BF7;&#x6C42;&#x7ED3;&#x679C;
        perform.andExpect(MockMvcResultMatchers.status().isOk());

        // &#x83B7;&#x53D6;&#x6267;&#x884C;&#x5B8C;&#x6210;&#x540E;&#x8FD4;&#x56DE;&#x7684;&#x7ED3;&#x679C;
        MvcResult mvcResult = perform.andReturn();

        // &#x5F97;&#x5230;&#x6267;&#x884C;&#x540E;&#x7684;&#x54CD;&#x5E94;
        MockHttpServletResponse response = mvcResult.getResponse();

        // &#x6253;&#x5370;&#x7ED3;&#x679C;
        logger.info(String.valueOf(response.getContentLength()));
        logger.info("&#x54CD;&#x5E94;&#x72B6;&#x6001;: ", response.getStatus());
        logger.info("&#x54CD;&#x5E94;&#x4FE1;&#x606F;: ", response.getContentAsString());

        logger.info("&#x7ED3;&#x675F;&#x6A21;&#x62DF;&#x53D1;&#x9001;&#x67E5;&#x8BE2;&#x7528;&#x6237;&#x5217;&#x8868;&#x7684;&#x8BF7;&#x6C42;......");
    }

    @Test
    public void apiTestQueryUserByUsername() throws Exception {

        logger.info("&#x5F00;&#x59CB;&#x6A21;&#x62DF;&#x6839;&#x636E;&#x7528;&#x6237;&#x540D;&#x67E5;&#x8BE2;&#x7528;&#x6237;&#x8BB0;&#x5F55;&#x7684;&#x8BF7;&#x6C42;......");

        // &#x6784;&#x5EFA;&#x8BF7;&#x6C42;&#x5E76;&#x53D1;&#x9001;
        MvcResult mvcResult = mockMvc.perform(MockMvcRequestBuilders.get("/user/name/admin"))
                .andExpect(MockMvcResultMatchers.status().isOk()).andReturn();

        // &#x6253;&#x5370;&#x7ED3;&#x679C;
        logger.info("&#x54CD;&#x5E94;&#x72B6;&#x6001;: ", mvcResult.getResponse().getStatus());
        logger.info("&#x54CD;&#x5E94;&#x4FE1;&#x606F;: ", mvcResult.getResponse().getContentAsString());

        logger.info("&#x7ED3;&#x675F;&#x6A21;&#x62DF;&#x6839;&#x636E;&#x7528;&#x6237;&#x540D;&#x67E5;&#x8BE2;&#x7528;&#x6237;&#x8BB0;&#x5F55;&#x7684;&#x8BF7;&#x6C42;......");
    }
}

Swagger2文档工具

pom.xml中添加以下代码

<dependency>
    <groupid>io.springfox</groupid>
    <artifactid>springfox-swagger2</artifactid>
    <version>2.9.2</version>
</dependency>
<dependency>
    <groupid>io.springfox</groupid>
    <artifactid>springfox-swagger-ui</artifactid>
    <version>2.9.2</version>
</dependency>

主要是用在请求类上,用于说明该类的作用

&#x793A;&#x4F8B;
@Api(tags = "xx&#x6A21;&#x5757;")

主要是用在请求的方法上,说明方法的作用

&#x793A;&#x4F8B;
@ApiOperation(value = "xx&#x65B9;&#x6CD5;&#x7684;&#x4F5C;&#x7528;", notes = "xx&#x65B9;&#x6CD5;&#x7684;&#x5907;&#x6CE8;&#x8BF4;&#x660E;")

主要是用在请求的方法上,说明方法的参数

&#x8BE6;&#x7EC6;&#x53C2;&#x6570;&#x8BF4;&#x660E;
@ApiImplicitParams&#xFF1A;&#x7528;&#x5728;&#x8BF7;&#x6C42;&#x7684;&#x65B9;&#x6CD5;&#x4E0A;&#xFF0C;&#x5305;&#x542B;&#x4E00;&#x7EC4;&#x53C2;&#x6570;&#x8BF4;&#x660E;
    @ApiImplicitParam&#xFF1A;&#x5BF9;&#x5355;&#x4E2A;&#x53C2;&#x6570;&#x7684;&#x8BF4;&#x660E;
        name&#xFF1A;&#x53C2;&#x6570;&#x540D;
        value&#xFF1A;&#x53C2;&#x6570;&#x7684;&#x8BF4;&#x660E;&#x3001;&#x63CF;&#x8FF0;
        required&#xFF1A;&#x53C2;&#x6570;&#x662F;&#x5426;&#x5FC5;&#x987B;&#x5FC5;&#x586B;
        paramType&#xFF1A;&#x53C2;&#x6570;&#x653E;&#x5728;&#x54EA;&#x4E2A;&#x5730;&#x65B9;
            &#xB7; query --> &#x8BF7;&#x6C42;&#x53C2;&#x6570;&#x7684;&#x83B7;&#x53D6;&#xFF1A;@RequestParam
            &#xB7; header --> &#x8BF7;&#x6C42;&#x53C2;&#x6570;&#x7684;&#x83B7;&#x53D6;&#xFF1A;@RequestHeader
            &#xB7; path&#xFF08;&#x7528;&#x4E8E;restful&#x63A5;&#x53E3;&#xFF09;--> &#x8BF7;&#x6C42;&#x53C2;&#x6570;&#x7684;&#x83B7;&#x53D6;&#xFF1A;@PathVariable
            &#xB7; body&#xFF08;&#x8BF7;&#x6C42;&#x4F53;&#xFF09;-->  @RequestBody User user
            &#xB7; form&#xFF08;&#x666E;&#x901A;&#x8868;&#x5355;&#x63D0;&#x4EA4;&#xFF09;
        dataType&#xFF1A;&#x53C2;&#x6570;&#x7C7B;&#x578B;&#xFF0C;&#x9ED8;&#x8BA4;String&#xFF0C;&#x5176;&#x5B83;&#x503C;dataType="Integer"
        defaultValue&#xFF1A;&#x53C2;&#x6570;&#x7684;&#x9ED8;&#x8BA4;&#x503C;

&#x5355;&#x4E2A;&#x53C2;&#x6570;&#x793A;&#x4F8B;
@ApiImplicitParam(name = "xxx", value = "xxx", required = true, paramType = "path", dataType = "String", defaultValue = "")

&#x591A;&#x4E2A;&#x53C2;&#x6570;&#x793A;&#x4F8B;
@ApiImplicitParams({
    @ApiImplicitParam(name = "xxxa", value = "xxxa", required = true, paramType = "body", dataType = "String", defaultValue = ""),
    @ApiImplicitParam(name = "xxxb", value = "xxxb", required = true, paramType = "body", dataType = "String", defaultValue = ""),
})

主要是用在请求的方法上,说明错误响应的信息

&#x8BE6;&#x7EC6;&#x53C2;&#x6570;&#x8BF4;&#x660E;
@ApiResponses&#xFF1A;&#x54CD;&#x5E94;&#x72B6;&#x6001;&#x7684;&#x8BF4;&#x660E;&#x3002;&#x662F;&#x4E2A;&#x6570;&#x7EC4;&#xFF0C;&#x53EF;&#x5305;&#x542B;&#x591A;&#x4E2A; @ApiResponse
    @ApiResponse&#xFF1A;&#x6BCF;&#x4E2A;&#x53C2;&#x6570;&#x7684;&#x8BF4;&#x660E;
        code&#xFF1A;&#x6570;&#x5B57;&#xFF0C;&#x4F8B;&#x5982;400
        message&#xFF1A;&#x4FE1;&#x606F;&#xFF0C;&#x4F8B;&#x5982;"&#x8BF7;&#x6C42;&#x53C2;&#x6570;&#x6CA1;&#x586B;&#x597D;"
        response&#xFF1A;&#x629B;&#x51FA;&#x5F02;&#x5E38;&#x7684;&#x7C7B;

&#x591A;&#x4E2A;&#x53C2;&#x6570;&#x793A;&#x4F8B;&#xFF0C;&#x4E00;&#x822C;&#x54CD;&#x5E94;&#x90FD;&#x662F;&#x591A;&#x4E2A;code&#xFF0C;&#x6240;&#x4EE5;&#x4E0D;&#x5199;&#x5355;&#x4E2A;&#x53C2;&#x6570;&#x7684;&#x793A;&#x4F8B;&#x4E86;
@ApiResponses({
        @ApiResponse(code = 200, message = "&#x8BF7;&#x6C42;&#x6210;&#x529F;"),
        @ApiResponse(code = 578, message = "&#x8BF7;&#x6C42;&#x53C2;&#x6570;&#x9519;&#x8BEF;"),
        @ApiResponse(code = 404, message = "&#x8BF7;&#x6C42;&#x8DEF;&#x5F84;&#x6CA1;&#x6709;&#x6216;&#x9875;&#x9762;&#x8DF3;&#x8F6C;&#x8DEF;&#x5F84;&#x4E0D;&#x5BF9;")
})

&#x793A;&#x4F8B;
@ApiModel(description = "&#x7528;&#x6237;&#x5B9E;&#x4F53;&#x7C7B;")
public class User {
    @ApiModelProperty(value = "&#x7528;&#x6237;&#x540D;", required = true, example = "0")
    private Integer id;

    @ApiModelProperty(value = "&#x7528;&#x6237;ID", required = true, example = "fx67ll")
    private String userName;

    @ApiModelProperty(value = "&#x7528;&#x6237;&#x5BC6;&#x7801;", required = true, example = "xxxxxxxx")
    private String userPwd;
}

分布式缓存工具Ehcache

EhCache是一个 &#x7EAF;Java的进程内缓存框架,具有快速、精干等特点,是 Hibernate中默认 CacheProvider
Ehcache是一种广泛使用的开源 Java&#x5206;&#x5E03;&#x5F0F;&#x7F13;&#x5B58;,主要面向通用缓存, Java EE&#x8F7B;&#x91CF;&#x7EA7;&#x5BB9;&#x5668;
它具有内存和磁盘存储,缓存加载器,缓存扩展,缓存异常处理程序,一个 gzip缓存 servlet过滤器,支持 REST APISOAP API等特点。

SpringBoot缓存实现内部使用SpringCache实现缓存控制,这里集成Ehcache实际上是对SpringCache抽象的一种实现
可以参考文章————Spring Cache 简介 详细学习,这里后期会补上说明

开启缓存功能,一般放在启动类上

当我们需要缓存的地方越来越多,你可以使用 @CacheConfig(cacheNames = {"cacheName"})注解在 Class之上来统一指定 value的值,
这时可省略 value,如果你在你的方法依旧写上了 value,那么依然以方法的 value值为准

根据方法对其返回结果进行缓存,下次请求时,如果缓存存在,则直接读取缓存数据返回;如果缓存不存在,则执行方法,并把返回的结果存入缓存中,一般用在查询方法上
注意 value 后面要使用 ehcache.xml 文件中所列的 cache.name

&#x5355;&#x4E2A;&#x53C2;&#x6570;&#x793A;&#x4F8B;&#x4EE3;&#x7801;
@Cacheable(value = "fx67llCache", key = "#xxx")

&#x591A;&#x4E2A;&#x53C2;&#x6570;&#x793A;&#x4F8B;&#xFF0C;&#x91C7;&#x7528;&#x62FC;&#x63A5;&#x7684;&#x65B9;&#x5F0F;
@Cacheable(value = "fx67llCache", key = "#xxx.xxx + '-' + #xxx.xxx + '-' + #xxx.xxx")

使用该注解标志的方法,每次都会执行,并将结果存入指定的缓存中。其他方法可以直接从响应的缓存中读取缓存数据,而不需要再去查询数据库,一般用在新增方法上

&#x793A;&#x4F8B;&#x4EE3;&#x7801;
@CachePut(value = "fx67llCache", key = "#xxx.xxx")

使用该注解标志的方法,会清空指定的缓存,一般用在更新或者删除方法上

&#x793A;&#x4F8B;&#x4EE3;&#x7801;
@CacheEvict(value = "fx67llCache", key = "#xxx")

该注解可以实现同一个方法上同时使用多种注解

定时调度工具Quartz

在日常项目运行中,我们总会有需求在某一时间段周期性的执行某个动作,比如每天在某个时间段导出报表,或者每隔多久统计一次现在在线的用户量等。
在SpringBoot中有Java自带的 java.util.Timer类,也可以在启动类添加 @EnableScheduling注解引入定时任务环境

springboot-quickstart springboot-mybatis springboot-mybatis-crud springboot-mybatis-crud-prod 快速入门 整合mybatis 整套crud操作 生产环境开发

我是 fx67ll.com,如果您发现本文有什么错误,欢迎在评论区讨论指正,感谢您的阅读!
如果您喜欢这篇文章,欢迎访问我的 本文github仓库地址,为我点一颗Star,Thanks~ 😃
转发请注明参考文章地址,非常感谢!!!

Original: https://www.cnblogs.com/fx67ll/p/springboot-quickstart.html
Author: fx67ll
Title: SpringBoot快速入门

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/599333/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球