springboot的各种配置

1.AOP配置

    
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-aopartifactId>
    dependency>
package com.qf.HomeWork.aop;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

/**
 * 该切面用于统计方法执行的时长
 */
@Aspect
@Component
@Slf4j
public class TimeAspect {
    //1.定义切点
    @Pointcut("execution(* com.qf.HomeWork.controller.UserController.*(..))")
    public void timepointcut(){};

    //2.定义通知
    @Around("timepointcut()")
    public Object calculateTime(ProceedingJoinPoint pjp) throws Throwable {
        long start =System.currentTimeMillis();
        Object proceed = pjp.proceed();
        //获取当前调用的目标方法
        Signature signature = pjp.getSignature();

        long end =System.currentTimeMillis();
        log.info("{}请求消耗的时长为:{}ms",signature,(end-start));
        return proceed;

    }
}

2.Filter过滤器

先写一个过滤器的类 若用原生态Filter或者servlet 必须在 主启动类上面加@ServletComponentScan注解

package com.qf.HomeWork.filter;

import com.qf.HomeWork.entity.Info;
import com.qf.HomeWork.mapper.InfoMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
@Slf4j
@Component
public class InfoFilter implements Filter {

  @Autowired
  private InfoMapper infoMapper;


    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
      log.info("============经过了InfoFilter过滤器================");
        HttpServletRequest req= (HttpServletRequest) request;
        long start = System.currentTimeMillis();
        log.info("起始时间戳:{}",start);
        String url = req.getRequestURI().toString();
        log.info("请求的url={}",url);
        String ip = req.getRemoteAddr();
        log.info("请求的ip={}",ip);
        String method = req.getMethod();
        log.info("请求的方式={}",method);
        chain.doFilter(request,response);
        long end = System.currentTimeMillis();
      Long time = end - start;
      log.info("请求所用时间为{}ms",time);
     infoMapper.add(new Info(null,url,ip,method,time.toString()));
        log.info("============离开了InfoFilter过滤器================");



    }




}

然后在配置类里,注册此过滤器,然后就能在 请求的时候经过过滤器

package com.qf.HomeWork.config;

import com.qf.HomeWork.filter.CheckPasswordFilter;
import com.qf.HomeWork.filter.CheckUserNameFilter;
import com.qf.HomeWork.filter.InfoFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class FilterConfig {

    @Autowired
  private  InfoFilter infoFilter;


    //将InfoFilter对象放入注册器中,将注册器放入IOC容器中,让springboot拿到,然后调用选取有效的过滤器的执行链,遍历执行其方法。
    @Bean
    public FilterRegistrationBean<InfoFilter> infoFilterFilterRegistrationBean(){
        FilterRegistrationBean<InfoFilter> registrationBean = new FilterRegistrationBean<>();

        //要注册的filter的对象
        registrationBean.setFilter(infoFilter);

        //处理filter的url路径
        registrationBean.addUrlPatterns("/*");
       //设置优先级 越小优先级越高
        registrationBean.setOrder(Integer.MIN_VALUE);
        //   把注册器这个类的对象注入IOC容器里供Spring自行调用
        return registrationBean;

    }








    @Bean
    public FilterRegistrationBean<CheckUserNameFilter> checkUsernameFilterFilterRegistrationBean(){
        FilterRegistrationBean<CheckUserNameFilter> registrationBean = new FilterRegistrationBean<>();

        //要注册的filter的对象
        registrationBean.setFilter(new CheckUserNameFilter());

        //处理filter的url路径
        registrationBean.addUrlPatterns("/h1","/login/dologin");

        registrationBean.setOrder(2);

        return registrationBean;



    }


    @Bean
    public FilterRegistrationBean<CheckPasswordFilter> checkPasswordFilterFilterRegistrationBean(){
        FilterRegistrationBean<CheckPasswordFilter> registrationBean = new FilterRegistrationBean<>();

        //要注册的filter的对象
        registrationBean.setFilter(new CheckPasswordFilter());

        //处理filter的url路径
        registrationBean.addUrlPatterns("/h1","/login/dologin");

        registrationBean.setOrder(3);
        return registrationBean;



    }

}

3.Interceptor拦截器

写一个拦截器的类

package com.qf.HomeWork.interceptor;

import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Component
public class MyInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        System.out.println("==========MyInterceptor preHandle==============");
        //放行该请求
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("==========MyInterceptor postHandle==============");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("==========MyInterceptor afterCompletion==============");
    }
}

注册拦截器

package com.qf.HomeWork.config;

import com.qf.HomeWork.interceptor.MyInterceptor;
import com.qf.HomeWork.interceptor.MyInterceptor2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
    @Autowired
    MyInterceptor myInterceptor;
     @Autowired
    MyInterceptor2 myInterceptor2;
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //添加拦截器
        registry.addInterceptor(myInterceptor)
            //拦截路径
                .addPathPatterns("/login/dologin")
            //优先级
                .order(10);
        registry.addInterceptor(myInterceptor2)
                .addPathPatterns("/login/dologin")
                .order(1);
    }



}

4.文件上传

spring: 
#图片上传大小 肯定存在 MultipartProperties这个类
  servlet:
    multipart:
      #单个文件最大大小
      max-file-size: 10MB
      #全部文件总大小
      max-request-size: 50MB
qf:      
  fileupload:
    path: F:\pathpng\      
package com.qf.HomeWork.controller;

import com.qf.HomeWork.util.ResultVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.validation.Valid;
import java.io.File;
import java.io.IOException;
import java.util.UUID;

@RestController
@RequestMapping("/up")
@Slf4j
public class UploadController {

    @Value("${qf.fileupload.path}")
    private String picdir;

    @RequestMapping("/pic")
    public ResultVo upload(MultipartFile photo) throws IOException {
        log.info("接收到文件为:{}",photo.getOriginalFilename());
        String extName = photo.getOriginalFilename().substring(photo.getOriginalFilename().lastIndexOf("."));

        String picPath=picdir;
        String filepath=picPath+ UUID.randomUUID().toString().replace("-","")+extName;

        log.info("上传路径为:{}",filepath);
        //存放文件
        photo.transferTo(new File(filepath));

        return ResultVo.ok(1,photo.getName());

    }



}

5.文件下载

package com.qf.HomeWork.controller;

import lombok.extern.slf4j.Slf4j;
import org.apache.tomcat.util.http.fileupload.IOUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletResponse;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

@RestController
@RequestMapping("/down")
@Slf4j
public class DownLoadController {

    @Value("${qf.fileupload.path}")
    private  String filedir;

      @RequestMapping("/pic")
      public  void  download(String picname, HttpServletResponse resp) throws IOException {

          //1.获取文件名对应文件的路径
          String filepath=filedir+picname;
          resp.addHeader("Content-Disposition","attachment;filename="+picname);
         log.info("文件路径:{}",filepath);
          //2. 将要下载的文件的字节数据拷贝到response对象的输出流中即可,不写响应头就和验证码响应浏览器原理相同
          IOUtils.copy(new FileInputStream(filepath), resp.getOutputStream());


      }

}

6.验证码

先导依赖


        <dependency>
            <groupId>com.baomidougroupId>
            <artifactId>kaptcha-spring-boot-starterartifactId>
            <version>1.1.0version>
        dependency>

yml

#验证码的配置
kaptcha:
  height: 50
  width: 200
  content:
    length: 2
    source: abcdefghjklmnopqrstuvwxyz23456789
    space: 2
  font:
    color: black
    name: Arial
    size: 40
  background-color:
    from: lightGray
    to: white
  border:
    enabled: true
    color: black
    thickness: 1
#自定义验证码超时时间
qf:
  kapchar:
    timeout: 60

测试

package com.qf.HomeWork.controller;

import com.baomidou.kaptcha.Kaptcha;
import com.baomidou.kaptcha.exception.KaptchaTimeoutException;
import com.qf.HomeWork.util.ResultVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/login")
@Slf4j
public class KapcherController {

    @Autowired
    private Kaptcha kaptcha;

    @Value("${qf.kapchar.timeout}")
    private Integer timeout;

    @GetMapping("/kapchar")
    public void kapchar(){
        kaptcha.render();
    }

    @GetMapping("/validate")
    public ResultVo validate(@RequestParam("code") String code){
        log.info("入参为:code={}",code);
        try {
            boolean flag = kaptcha.validate(code,10);
            log.info("验证码校验结果,flag={}",flag);
            return ResultVo.ok(1,flag);
        }catch (Exception e){
            e.printStackTrace();
            return ResultVo.error(-1,false);
        }
    }

    @PostMapping("/dologin")
    public ResultVo dologin(@RequestParam("username") String username,@RequestParam("password")String password,@RequestParam("captcha")String captcha) {
        log.info("入参为:username={},password={},captcha={}", username, password, captcha);
        //校验验证码
        try {
            log.info("验证码有效时间为:timeout={}",timeout);
            boolean flag = kaptcha.validate(captcha,timeout);
            log.info("验证码校验结果,flag={}", flag);
        }catch (KaptchaTimeoutException e) {
            e.printStackTrace();
            return ResultVo.error(-1, "验证码超时");
        }
        catch (Exception e) {
            e.printStackTrace();
            return ResultVo.error(-1, "验证码错误");
        }
        //判断用户名密码是否正确
        if (username.equals("luffy") && password.equals("123456")) {
            return ResultVo.ok(1, "登录成功");
        } else {
            return ResultVo.error(-1, "登陆失败");
        }

    }
}

7.基于注解的校验功能

启用方法 在springboot2.7之前,都不用导入依赖, 依赖在我的博客上。升级版本就去导。

package com.qf.HomeWork.controller;

import com.qf.HomeWork.entity.HelloVo;
import com.qf.HomeWork.entity.User;
import com.qf.HomeWork.util.ResultVo;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.Valid;
import javax.validation.constraints.*;

@RestController
@RequestMapping("/p")
@Validated //开启基于注解的校验功能
public class PramcheckController {
//@Size(min=3,max=5,message = "长度应该在3-5之间")

    /**
     *@NotNull注解要求name只是不能为null,可以为空串
     */
    @RequestMapping("/test1")
    public ResultVo test1( @NotNull String name){
        System.out.println(name);
        return ResultVo.ok(1,name);
    }

    /**
     *@NotEmpty注解要求name既不能为空串,也不能为null
     */
    @RequestMapping("/test2")
    public ResultVo test2( @NotEmpty String name){
        System.out.println(name);
        return ResultVo.ok(1,name);
    }
    /**
     *@Email 邮箱验证
     */
    @RequestMapping("/test3")
    public ResultVo test3( @Email(message = "不合法邮箱") String name){
        System.out.println(name);
        return ResultVo.ok(1,name);
    }

    /**
     *@Pattern 正则表达式验证
     */
    @RequestMapping("/test4")
    public ResultVo test4( @Pattern(message = "你的手机号输入不对",regexp = "^1(3[0-9]|4[579]|5[0-35-9]|6[2567]|7[0-8]|8[0-9]|9[89])\\d{8}$") String name){
        System.out.println(name);
        return ResultVo.ok(1,name);
    }

    /**
     *@Valid 验证对象的注解
     */
    @RequestMapping("/test5")
    public ResultVo test5(@Valid HelloVo user){
        System.out.println(user);
        return ResultVo.ok(1,user);
    }
}

在实体类里面可以,加注解校验,然后在方法上加 @Valid 就可以开启校验了

package com.qf.HomeWork.entity;

import lombok.Data;

import javax.validation.constraints.Email;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;

@Data
public class HelloVo {
    @NotNull
    private Integer id;

    //    @NotNull  // 需要该参数不能为null
    @NotEmpty   // 不可以为空串
    @Size(min = 5,max = 100)
    private String name;

    @Email
    private String email;
}

8.启动类运行后面加上方法的操作

package com.qf.HomeWork.runner;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;

@Component
public class MyRunner implements ApplicationRunner {
    @Value("${server.port}")
    private Integer port;


    @Override
    public void run(ApplicationArguments args) throws Exception {
        System.out.println("http://localhost:"+port);

    }
}

9.Swagger

导入依赖

<dependencies>
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starterartifactId>
        <version>2.2.9.RELEASEversion>
    dependency>
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-configuration-processorartifactId>
        <version>2.2.9.RELEASEversion>
        <optional>trueoptional>
    dependency>
    
    <dependency>
        <groupId>io.springfoxgroupId>
        <artifactId>springfox-swagger2artifactId>
        <version>2.9.2version>
    dependency>
    <dependency>
        <groupId>io.springfoxgroupId>
        <artifactId>springfox-swagger-uiartifactId>
        <version>2.9.2version>
    dependency>

    
    <dependency>
        <groupId>com.github.xiaoymingroupId>
        <artifactId>knife4j-spring-boot-starterartifactId>
        <version>2.0.4version>
    dependency>
dependencies>

在主启动类上面加上

@EnableSwagger2//开启swagger依赖
@EnableKnife4j//开启knife4j皮肤

然后写个配置类

package com.qianfeng.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

/**
 * Swagger基础配置类
 * 此类相当于配置文件, 项目启动就立即自动加载此类
 *
 */
@Configuration
public class SwaggerConfiguration {

    @Bean
    public Docket buildDocket() {
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(buildApiInfo())
                .select()
                // 要扫描的API(Controller)基础包
                .apis(RequestHandlerSelectors.basePackage("com.qianfeng.controller"))
                .build();
    }

    private ApiInfo buildApiInfo() {
        Contact contact = new Contact("千锋教育","http://www.baidu.com","[email protected]");
        return new ApiInfoBuilder()
                .title("千峰教育API文档")
                .description("平台管理服务api")
                .contact(contact)
                .version("1.0.0")
                .build();
    }
}

加到IOC容器,即可使用

调用官网 小刀 http://localhost:8080/doc.html

​ swagger 访问地址:http://localhost:8080/swagger-ui.html

然后我把它写成了启动器

9.1Properties类
package com.qf.swagger.spring.boot.autoconfigure.properties;

import org.springframework.boot.context.properties.ConfigurationProperties;

@ConfigurationProperties("com.qf.swagger")
public class SwaggerProperties {

    //联系人的名字
    private String contactName;

    //联系人的网址
    private String contactUrl;

    //联系人的邮箱
    private String email;

    //文档的标题
    private String title;

    //项目的描述信息
    private String description;

    //项目的版本号
    private String version;

    //swagger扫描下的包
    private String packageName;

    public String getContactName() {
        return contactName;
    }

    public void setContactName(String contactName) {
        this.contactName = contactName;
    }

    public String getContactUrl() {
        return contactUrl;
    }

    public void setContactUrl(String contactUrl) {
        this.contactUrl = contactUrl;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public String getVersion() {
        return version;
    }

    public void setVersion(String version) {
        this.version = version;
    }

    public String getPackageName() {
        return packageName;
    }

    public void setPackageName(String packageName) {
        this.packageName = packageName;
    }
}
9.2 配置类
package com.qf.swagger.spring.boot.autoconfigure;

import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j;
import com.qf.swagger.spring.boot.autoconfigure.properties.SwaggerProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

@Configuration
@EnableSwagger2//开启swagger依赖
@EnableKnife4j//开启knife4j皮肤
@EnableConfigurationProperties(SwaggerProperties.class)
public class SwaggerAutoConfigure {

    @Autowired
    private SwaggerProperties swaggerProperties;


    @Bean
    public Docket docket(){

        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(buildApiInfo())
                .select()
                // 要扫描的API(Controller)基础包
                .apis(RequestHandlerSelectors.basePackage(swaggerProperties.getPackageName()))
                .build();

    }

    private ApiInfo buildApiInfo() {
        Contact contact = new Contact(swaggerProperties.getContactName(),swaggerProperties.getContactUrl(),swaggerProperties.getEmail());
        return new ApiInfoBuilder()
                .title(swaggerProperties.getTitle())
                .description(swaggerProperties.getDescription())
                .contact(contact)
                .version(swaggerProperties.getVersion())
                .build();//最后调用build方法返回ApiInfo对象
    }




}
9.3 yml文件配置+导入依赖即可使用
com:
  qf:
    swagger:
      package-name: com.qf.HomeWork.controller
      contact-name: 蒋铭基
      contact-url: http://www.baidu.com
      email: [email protected]
      title: 蒋铭基的接口API文档
      description: 这是蒋铭基项目的接口描述文档的描述信息。很棒!
      version: 1.1.0
<dependency>
    <groupId>com.qfgroupId>
    <artifactId>swagger-spring-boot-startartifactId>
    <version>1.0-SNAPSHOTversion>
dependency>

10.druid 配置

导入依赖


<dependency>
    <groupId>com.alibabagroupId>
    <artifactId>druid-spring-boot-starterartifactId>
    <version>1.2.6version>
dependency>

  <dependency>
        <groupId>mysqlgroupId>
        <artifactId>mysql-connector-javaartifactId>
       <version>5.1.47version>
  dependency>

yml配置数据源

#配置数据源
spring:
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    username: root
    password: 2001
    url: jdbc:mysql://47.94.172.139:6789/lawer?useSSL=false&useUnicode=true&characterEncoding=utf8
    type: com.alibaba.druid.pool.DruidDataSource

即可调用数据源 ,已经在IOC容器里面了 也可也使用JDBC模板,但是必须要导入 spring-boot-starter-jdbc依赖

package com.qf;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;

@SpringBootTest
class Spring05DataApplicationTests {
    //数据源会自动装配,配置类数据源类型,会通过XXXproperties绑定的XXXAutoConfigure里的Bean加载到IOC容器里面,
    // 当包生效,就会把数据源放入到IOC容器里。
    @Autowired
    private DataSource dataSource;
    @Test
    void contextLoads() throws SQLException {
        System.out.println(dataSource.getClass());

        //获取数据源链接
        Connection connection = dataSource.getConnection();
        System.out.println(connection);
        connection.close();

    }

}

11.全局异常类

package com.qf.HomeWork.exhandler;

import com.qf.HomeWork.util.ResultVo;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

@RestControllerAdvice//全局异常处理器的注解,相当于增强通知
public class GlobalExHandler {
//底层不是AOP,就是调用了DispatcherServlet,拿到映射器处理器找到对应的Controller,应该是捕获到异常的时候,就会触发映射器找到这个方法,实现这个方法响应,一个数据给客户端
    @ExceptionHandler(Exception.class)
    public ResultVo handleEx(Exception e){
        e.printStackTrace();
        return ResultVo.error(-1,"出异常了,请与运维联系!");
    }

}

12.静态资源处理

@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        // 这种方式也会覆盖掉默认的web静态资源目录
        registry.addResourceHandler("/**").addResourceLocations("classpath:static/","classpath:templates/");
    }
}
# 注意:这样配置会覆盖掉默认的web静态资源目录
spring.web.resources.static-locations=classpath:/templates

13.日期格式配置

#日期格式json
  jackson:
    date-format: yyyy-MM-dd HH:mm:ss
    time-zone: GMT+8
package com.qf.HomeWork.entity;

import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.format.annotation.DateTimeFormat;

import java.util.Date;

@NoArgsConstructor
@AllArgsConstructor
@Data
public class Student {
    private Integer id;
    private String name;
    private String sex;
    private Integer age;
    //跟json,没关系,一般是表单提交查询字符串的时候,用这个,
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    //因为刚刚不是用springboot去接受的,用的是jackson来接收的,所以得加上这个注解,
    //请求有过滤器,响应有响应头,纯文本响应头,json响应头。
    //请求日期类型有 dateTimeFormat  json有 JsonFormat 在 springboot配置文件已经配好了,在自动装配里会把配置信息放入Jackson对象,放到IOC容器里
    //springboot这个底层也是用jackson接收,他在配置文件里写了,被注入IOC容器得jackson对象配置了注入日期格式的问题。
//    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")//会用就行,记住大概的原理,一查就知道了,不需要记得那么牢,就是格林威治时间与中国时区差8小时
    private Date birthday;
    private Integer status;
}

14.springboot整合Mybatis


<dependency>
    <groupId>mysqlgroupId>
    <artifactId>mysql-connector-javaartifactId>
dependency>


<dependency>
    <groupId>com.alibabagroupId>
    <artifactId>druid-spring-boot-starterartifactId>
    <version>1.1.10version>
dependency>


<dependency>
    <groupId>org.mybatis.spring.bootgroupId>
    <artifactId>mybatis-spring-boot-starterartifactId>
    <version>1.3.2version>
dependency>

导入依赖

#mybatis 的必要配置,配置mapperxml文件的位置 类路径包括导入所有jar包的类路径下的所有文件夹下的所有Mapper.xml为映射文件。
mybatis:
  mapper-locations: classpath*:**/*Mapper.xml
#开启mybatis的sql日志。
logging:
  level:
    com.qf.HomeWork.mapper: debug

配置文件

15.SpringBoot整合分页助手


<dependency>
    <groupId>com.github.pagehelpergroupId>
    <artifactId>pagehelper-spring-boot-starterartifactId>
    <version>1.2.5version>
dependency>
@Test
public void test(){
    SqlSession sqlSession = MyBatisUtils.getSqlSession();
    BookMapper mapper = sqlSession.getMapper(BookMapper.class);
    //分页
    PageHelper.startPage(2,5);
    List<Book> byPage = mapper.findByPage();
    //分页对象,里面有各种上一页,下一页,总页数,什么的数据
    PageInfo<Book> pageInfo = new PageInfo<>(byPage);
    for (Book book : byPage) {
        System.out.println(book);
    }

    System.out.println("---------------");
    System.out.println(pageInfo);
    System.out.println(pageInfo.getList());

}

16.springboot整合Mybatis-plus

导入依赖

     
     <dependency>
         <groupId>com.baomidougroupId>
         <artifactId>mybatis-plus-boot-starterartifactId>
         <version>3.5.2version>
     dependency>

     
     <dependency>
         <groupId>com.alibabagroupId>
         <artifactId>druid-spring-boot-starterartifactId>
         <version>1.2.6version>
     dependency>


     <dependency>
         <groupId>mysqlgroupId>
         <artifactId>mysql-connector-javaartifactId>
         <version>5.1.47version>
     dependency>
     
#开启mybatis-plus的sql日志。
logging:
  level:
    com.qf.HomeWork.mapper: debug

通过继承BaseMapper<泛型> 来继承自动SQL的生成

package com.qf.MP2302.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.qf.MP2302.entity.Category;

import java.util.List;

public interface CategoryMapper extends BaseMapper<Category> {

    List<Category> findAll(int parentID);

}

17.springboot整合事务

@Transactional(rollbackFor = Exception.class,isolation = Isolation.READ_COMMITTED)//隔离级别,调整为读已提交

在方法上加上这个就能代理这个方法,或者加到类上,就能让类里所有的方法开启事务。

18.springboot整合生成SQL原理,实体类字段配置

//定义在实体类里
  /**
     * mybatis-plus不允许下划线,他会有默认的命名策略,将驼峰命名映射到数据库的下划线的数据库名,绑定对应的值
     * 如果不用驼峰命名,下划线,虽然能查出来条数,也会生成正确的sql,但是数据回显的时候,他会将数据库查询出来的,字段
     * 映射成驼峰命名的map集合,但是在实体类里,它却是下划线,所以匹配不到属性,赋不上值,所以,传回来一个空对象,,如果有值,就创建对象,没值,就把空对象加入集合里,没有映射上去的话,就是ORM,从下划线映射成驼峰命名,这个策略,若
     * 属性不是驼峰命名,则对应不上,就会返回一个空对象,把这个空对象加入集合,最后就会存在很多空对象的集合 !!!
     * mybatis-plus加了@TableField(exist = false),这个就会,表示这个属性不存在字段在数据库当中,也不会映射,上去,不会报错
     */
@TableName("sys_user")//定义表名,加载类名上
@TableId(type = IdType.AUTO,value = "category_id")//定义主键,加载字段上
//INPUT 是自动填充NULL。然后数据库自增
//NONE是数字UUID,
//AUTO 主键自增  其他都懂
@TableField("category_name")//定义字段
@TableField(exist = false)//定义属性不在数据库字段里
@Version//乐观锁的版本号
@TableLogic//逻辑删除键  数据库表中的逻辑删除字段设置默认值为0(未删除)。

19.Mybatis-plus整合分页插件

@Configuration
// 在mybatisplus的配置类上也可以添加注解扫描,启动类和配置类二选一,添加一处即可
// @MapperScan("scan.your.mapper.package")
public class MybatisPlusConfig {

    /**
     * 新的分页插件,一缓和二缓遵循mybatis的规则,需要设置 MybatisConfiguration#useDeprecatedExecutor = false 避免缓存出现问题(该属性会在旧插件移除后一同移除)
     */
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return interceptor;
    }

}
@Test
void select() {

    Page<User> userPage = new Page<>(1,3);
//这里示范无条件查询,所以null
 userPage= userDao.selectPage(userPage,null);
    long total = userPage.getTotal();
    System.out.println("总条数:"+total);
    System.out.println("总页数:"+userPage.getPages());
    System.out.println("当前页数据:"+userPage.getRecords());
}

分页查询,用map集合接收,map集合当实体类,key就是Select后面的字段,包括别名

@Test
void selectByPage() {

    //ORM映射,这个问题解决了,就是SQL查出来的数据封装成Map集合
    Page<Map<String,Object>> userPage = new Page<>(1,3);
    userPage= userDao.selectMapsPage(userPage,null);
    long total = userPage.getTotal();
    System.out.println("总条数:"+total);
    System.out.println("总页数:"+userPage.getPages());
    System.out.println("当前页数据:"+userPage.getRecords());
}

20.乐观锁与springboot整合

在配置类:注册

@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
    MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
    interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
    return interceptor;
}

乐观锁的例子

package com.qf.MP2302.service.impl;

import com.qf.MP2302.entity.Product;
import com.qf.MP2302.mapper.ProductMapper;
import com.qf.MP2302.service.ProductService;
import lombok.AllArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;
@Service
public class ProductServiceImpl implements ProductService {

    @Autowired
    private ProductMapper productMapper;

    @Transactional(rollbackFor = Exception.class,isolation = Isolation.READ_COMMITTED)//隔离级别,调整为读已提交
    @Override
    public boolean modPrice(Long id, Integer deltaPrice) {

        //1.根据id查询商品信息
        Product product = productMapper.selectById(id);
        Integer cunrrentPrice = product.getPrice();
        Integer newPrice = cunrrentPrice - deltaPrice;
        //2.修改数据库表
        product.setPrice(newPrice);
        int i = productMapper.updateById(product);

        //3.乐观锁的补偿机制,如果出现i=0的情况,说明出现了并发冲突,重试
        while (i==0){
            Product  productAgain=productMapper.selectById(id);
            Integer againPrice = productAgain.getPrice();

            int newPriceAgain = againPrice - deltaPrice;
            productAgain.setPrice(newPriceAgain);
            i=productMapper.updateById(productAgain);
        }

        return i==1;
    }
}

21.Mybatis-plus 代码自动生成器

导入依赖

   <dependencies>
        <dependency>
            <groupId>com.baomidougroupId>
            <artifactId>mybatis-plus-boot-starterartifactId>
            <version>3.5.2version>
        dependency>


        <dependency>
            <groupId>com.baomidougroupId>
            <artifactId>mybatis-plus-generatorartifactId>
            <version>3.5.2version>
        dependency>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-freemarkerartifactId>
            <version>2.2.9.RELEASEversion>
        dependency>
        
        <dependency>
            <groupId>mysqlgroupId>
            <artifactId>mysql-connector-javaartifactId>
            <version>5.1.47version>
        dependency>
    dependencies>

通过主启动类,启动,来实现代码的自动生成

package com.qf.gen;

import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.OutputFile;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import com.baomidou.mybatisplus.generator.fill.Column;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;

public class Gen {
    public static void main(String[] args) {
        FastAutoGenerator.create("jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&useSSL=false", "root", "2001")
                // 全局配置
                .globalConfig((scanner, builder) -> builder.author(scanner.apply("请输入作者名称?")).fileOverride().outputDir("F:/MPgen"))
                // 包配置
                .packageConfig((scanner, builder) -> builder.parent(scanner.apply("请输入包名?")).moduleName(scanner.apply("请输入模块名?")).pathInfo(Collections.singletonMap(OutputFile.xml, "F:/MPgen")))
                // 策略配置
                .strategyConfig((scanner, builder) -> builder.addInclude(getTables(scanner.apply("请输入表名,多个英文逗号分隔?所有输入 all")))
                        .controllerBuilder().enableRestStyle().enableHyphenStyle()
                        .entityBuilder().enableLombok().addTableFills(
                                new Column("create_time", FieldFill.INSERT)
                        ).build())
                /*
                    模板引擎配置,默认 Velocity 可选模板引擎 Beetl 或 Freemarker
                   .templateEngine(new BeetlTemplateEngine())
                   .templateEngine(new FreemarkerTemplateEngine())
                 */
                .templateEngine(new FreemarkerTemplateEngine())
                .execute();

    }

    // 处理 all 情况
    protected static List<String> getTables(String tables) {
        return "all".equals(tables) ? Collections.emptyList() : Arrays.asList(tables.split(","));
    }
}

代码生成器使用流程

  1. 搭建springboot+mp环境
  2. 设计数据表
  3. 搭建mp代码生成器工程,使用工程生成模块代码
  4. 拷贝代码到指定目录
  5. 移植其他项目各分层代码

你可能感兴趣的:(SpringBoot,spring,boot,后端,java)