springboot的各种配置
1.AOP配置
<!-- AOP的依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId></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 {@Autowiredprivate InfoMapper infoMapper;@Overridepublic 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 {@Autowiredprivate InfoFilter infoFilter;//将InfoFilter对象放入注册器中,将注册器放入IOC容器中,让springboot拿到,然后调用选取有效的过滤器的执行链,遍历执行其方法。@Beanpublic 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;}@Beanpublic 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;}@Beanpublic 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 {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {System.out.println("==========MyInterceptor preHandle==============");//放行该请求return true;}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {System.out.println("==========MyInterceptor postHandle==============");}@Overridepublic 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 {@AutowiredMyInterceptor myInterceptor;@AutowiredMyInterceptor2 myInterceptor2;@Overridepublic 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.baomidou</groupId><artifactId>kaptcha-spring-boot-starter</artifactId><version>1.1.0</version></dependency>
yml
#验证码的配置
kaptcha:height: 50width: 200content:length: 2source: abcdefghjklmnopqrstuvwxyz23456789space: 2font:color: blackname: Arialsize: 40background-color:from: lightGrayto: whiteborder:enabled: truecolor: blackthickness: 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 {@Autowiredprivate 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 {@NotNullprivate Integer id;// @NotNull // 需要该参数不能为null@NotEmpty // 不可以为空串@Size(min = 5,max = 100)private String name;@Emailprivate 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;@Overridepublic void run(ApplicationArguments args) throws Exception {System.out.println("http://localhost:"+port);}
}
9.Swagger
导入依赖
<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId><version>2.2.9.RELEASE</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-configuration-processor</artifactId><version>2.2.9.RELEASE</version><optional>true</optional></dependency><!-- swagger依赖 ,两个 ,一个核心功能,一个UI可视化 --><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><!-- https://mvnrepository.com/artifact/com.github.xiaoymin/knife4j-spring-boot-starter 小刀启动器 --><dependency><groupId>com.github.xiaoymin</groupId><artifactId>knife4j-spring-boot-starter</artifactId><version>2.0.4</version></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 {@Beanpublic 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","dong_jl@163.com");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 {@Autowiredprivate SwaggerProperties swaggerProperties;@Beanpublic 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.controllercontact-name: 蒋铭基contact-url: http://www.baidu.comemail: 1393087444@qq.comtitle: 蒋铭基的接口API文档description: 这是蒋铭基项目的接口描述文档的描述信息。很棒!version: 1.1.0
<dependency><groupId>com.qf</groupId><artifactId>swagger-spring-boot-start</artifactId><version>1.0-SNAPSHOT</version>
</dependency>
10.druid 配置
导入依赖
<!-- 德鲁伊启动器 -->
<dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>1.2.6</version>
</dependency>
<!-- Mysql --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.47</version></dependency>
yml配置数据源
#配置数据源
spring:datasource:driver-class-name: com.mysql.jdbc.Driverusername: rootpassword: 2001url: jdbc:mysql://localhost:3306/test?useSSL=true&useUnicode=true&characterEncoding=utf8type: 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容器里。@Autowiredprivate DataSource dataSource;@Testvoid 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 {@Overridepublic void addResourceHandlers(ResourceHandlerRegistry registry) {// 这种方式也会覆盖掉默认的web静态资源目录registry.addResourceHandler("/**").addResourceLocations("classpath:static/","classpath:templates/");}
}
# 注意:这样配置会覆盖掉默认的web静态资源目录
spring.web.resources.static-locations=classpath:/templates
13.日期格式配置
#日期格式jsonjackson:date-format: yyyy-MM-dd HH:mm:sstime-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
<!-- mysql驱动-->
<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId>
</dependency><!-- druid连接-->
<dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>1.1.10</version>
</dependency><!-- mybatis-->
<dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>1.3.2</version>
</dependency>
导入依赖
#mybatis 的必要配置,配置mapperxml文件的位置 类路径包括导入所有jar包的类路径下的所有文件夹下的所有Mapper.xml为映射文件。
mybatis:mapper-locations: classpath*:**/*Mapper.xml
#开启mybatis的sql日志。
logging:level:com.qf.HomeWork.mapper: debug
配置文件
15.SpringBoot整合分页助手
<!-- pageHelper依赖-->
<dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper-spring-boot-starter</artifactId><version>1.2.5</version>
</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
导入依赖
<!-- 基于 mybatis plus 的dao层的相关依赖 start--><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.2</version></dependency><!-- 德鲁伊启动器 --><dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>1.2.6</version></dependency><!-- 数据库依赖--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.47</version></dependency><!-- 基于 mybatis plus 的dao层的相关依赖 end-->
#开启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 避免缓存出现问题(该属性会在旧插件移除后一同移除)*/@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor() {MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));return interceptor;}}
@Test
void select() {Page<User> userPage = new Page<>(1,3);
//这里示范无条件查询,所以nulluserPage= 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 {@Autowiredprivate ProductMapper productMapper;@Transactional(rollbackFor = Exception.class,isolation = Isolation.READ_COMMITTED)//隔离级别,调整为读已提交@Overridepublic 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.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.2</version></dependency><!-- mybatis-plus-generator 代码生成器 start 需要mysql依赖 --><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-generator</artifactId><version>3.5.2</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-freemarker</artifactId><version>2.2.9.RELEASE</version></dependency><!-- mybatis-plus-generator 代码生成器 end --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.47</version></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(","));}
}
代码生成器使用流程
- 搭建springboot+mp环境
- 设计数据表
- 搭建mp代码生成器工程,使用工程生成模块代码
- 拷贝代码到指定目录
- 移植其他项目各分层代码
相关文章:
springboot的各种配置
1.AOP配置 <!-- AOP的依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId></dependency>package com.qf.HomeWork.aop;import lombok.extern.slf4j.Slf4j; im…...

OSI七层模型及TCP/IP四层模型
目录 OSI七层模型 TCP/IP四层模型 OIS七层模型和TCP/IP模型图 七层详解 两种模型比较 为什么OSI七层体系结构不常用 四层详解 网络为什么要分层? 说说 OSI 七层模型和 TCP/IP 四层模型的关系和区别 OSI七层模型 OSI(Open System Interconnect&a…...
MDN-Web APIs
参考资料 文章目录 简介DOM APIXMLHttpRequestWeb Storage APIWebsockets API 简介 Web APIs(Application Programming Interfaces)是用于与浏览器环境中的 Web 功能进行交互的一组接口和方法集合。通过 Web APIs,开发人员可以访问浏览器提…...

2023国赛数学建模C题思路分析
文章目录 0 赛题思路1 竞赛信息2 竞赛时间3 建模常见问题类型3.1 分类问题3.2 优化问题3.3 预测问题3.4 评价问题 4 建模资料 0 赛题思路 (赛题出来以后第一时间在CSDN分享) https://blog.csdn.net/dc_sinor?typeblog 1 竞赛信息 全国大学生数学建模…...
暑假集训笔记
刷题刷的好累啊...不想刷题了...然后就来写题解了... 昨天晚上打了场div2..2000来名,加了155分....现在rating1281...我是菜鸡..暑假之前就打到了1200分以上了,结果暑假一掉再掉,直接掉到1100了...然后我就一直压力很大....... 昨天在机房打…...

【枚举+推式子】牛客小白月赛 63 E
登录—专业IT笔试面试备考平台_牛客网 题意: 思路: 首先是个计数问题,考虑组合数学 组合数学就是在考虑枚举所有包含1和n的区间 这个典中典就是枚举1和n的位置然后算贡献 双指针超时,考虑推式子: Code:…...

Android多屏幕支持-Android12
Android多屏幕支持-Android12 1、概览及相关文章2、屏幕窗口配置2.1 配置xml文件2.2 DisplayInfo#uniqueId 屏幕标识2.3 adb查看信息 3、配置文件解析3.1 xml字段读取3.2 简要时序图 4、每屏幕焦点 android12-release 1、概览及相关文章 AOSP > 文档 > 心主题 > 多屏…...
python环境下载安装教程,python运行环境怎么下载
本篇文章给大家谈谈python安装步骤以及环境变量配置,以及下载python需要设置环境变量吗,希望对各位有所帮助,不要忘了收藏本站喔。 1.https://www.python.org/downloads/windows/ 下载适合自己电脑的python安装包 2.下载后安装即可 3.配置环…...

【0.2】lubancat鲁班猫4远程ubuntu22.04.2 无需任何安装
环境 lubancat4鲁班猫4 (4G0)不带emmc 系统镜像ubuntu-22.04.2-desktop-arm64-lubancat-4.img 网络环境:有线网络与本win10电脑同意环境 操作步骤ubuntu正常开机登陆用户,连接好网络进入设置>网络查看设备当前局域网IP 如192.168.199.159进入设置>共享>远程…...
Flutter 状态管理 Provider
状态管理必要性 Flutter基于声明式构建UI,原生则是命令式,状态管理是用于解决声明式开发带来的问题。 例:命令式的原生,数据更新需要拿到对应控件并更改其显示值;而声明式则需要更改数据值并通过setstate更新状态&am…...

【设计模式】观察者模式
什么是观察者模式? 观察者模式(又被称为发布-订阅(Publish/Subscribe)模式,属于行为型模式的一种,它定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态…...

ORCA优化器浅析——CDXLOperator Base class for operators in a DXL tree
如上图所示,CDXLOperator作为Base class for operators in a DXL tree,其子类CDXLLogical、CDXLScalar、CDXLPhysical作为逻辑节点、物理节点和Scalar节点的DXL表示类,因此其包含了这些类的共同部分特性,比如获取其DXL节点表示的函…...

go入门实践四-go实现一个简单的tcp-socks5代理服务
文章目录 前言socks协议简介go实现一个简单的socks5代理运行与压测抓包验证 前言 SOCKS是一种网络传输协议,主要用于客户端与外网服务器之间通讯的中间传递。协议在应用层和传输层之间。 本文使用先了解socks协议。然后实现一个socks5的tcp代理服务端。最后&#…...

div 中元素居中的N种常用方法
本文主要记录几种常用的div盒子水平垂直都居中的方法。本文主要参考了该篇博文并实践加以记录说明以加深理解记忆 css之div盒子居中常用方法大全 本文例子使用的 html body结构下的div 盒子模型如下: <body><div class"container"><div c…...

Java获取指定文件夹下目录下所有视频并复制到另一个地方
import java.io.File; import java.io.IOException; import java.nio.file.Files; import java.nio.file.StandardCopyOption;public class VideoCopier {public static void main(String[] args) {// 指定源文件夹路径和目标文件夹路径String sourceFolderPath "path/to…...

windows server 2016 搭建使用 svn 服务器教程
参考教程: https://zhuanlan.zhihu.com/p/428552058 https://blog.csdn.net/weixin_33897722/article/details/85602029 配置环境 windows server 2016 远程服务器公网 ip 安装 SVN 服务端 下载 svn 服务端安装包:https://www.visualsvn.com/download…...

【Python】如何判断时间序列数据是否为平稳时间序列或非平稳时间序列?
判断时间序列数据是否为平稳时间序列或非平稳时间序列,通常可以通过以下方法: (1)观察时间序列数据的均值和方差是否随时间变化而发生明显的改变。若均值和方差变化明显,则该时间序列数据可能为非平稳时间序列&#x…...

Labview控制APx(Audio Precision)进行测试测量(六)
用 LabVIEW 驱动 VIs生成任意波形 在 APx500 应用程序中,默认波形类型为正弦。这是指 APx 内置的正弦发生器,根据信号路径设置,许多测量还允许其他内置波形,如方波,分裂正弦波或分裂相位,以及使用导入的。w…...
【Linux】网络协议总结
目录 网络协议总结 应用层 传输层 网络层 数据链路层 网络协议总结 应用层 应用层的作用:负责应用程序间沟通,完成一系列业务处理所需服务。能够根据自己的需求,设计对应的应用层协议。了解HTTP协议。理解DNS的原理和工作流程。 传…...
如何轻松注册企业邮箱?快速掌握超简单的注册技巧!
随着互联网的发展,越来越多的企业开始使用电子邮件作为通信工具。企业邮箱不仅可以提高企业的工作效率,还可以使企业通信更加便捷、保密性更高。那么,企业邮箱怎么注册申请呢?下面我们来详细介绍一下。 第一步:选择邮箱…...
Windows 下搭建 Zephyr 开发环境
1. 系统要求 操作系统:Windows 10/11(64位)磁盘空间:至少 8GB 可用空间(Zephyr 及其工具链较大)权限:管理员权限(部分工具需要) 2. 安装必要工具 winget安装依赖工具&am…...

从上下文学习和微调看语言模型的泛化:一项对照研究
大型语言模型表现出令人兴奋的能力,但也可以从微调中表现出令人惊讶的狭窄泛化。例如,他们可能无法概括为简单的关系反转,或者无法根据训练信息进行简单的逻辑推理。这些未能从微调中概括出来的失败可能会阻碍这些模型的实际应用。另一方面&a…...
Kafka 快速上手:安装部署与 HelloWorld 实践(一)
一、Kafka 是什么?为什么要学? ** 在大数据和分布式系统的领域中,Kafka 是一个如雷贯耳的名字。Kafka 是一种分布式的、基于发布 / 订阅的消息系统,由 LinkedIn 公司开发,后成为 Apache 基金会的顶级开源项目 。它以…...

【高效开发工具系列】Blackmagic Disk Speed Test for Mac:专业硬盘测速工具
博客目录 一、Blackmagic Disk Speed Test 概述二、软件核心功能解析三、v3.3 版本的新特性与改进四、实际应用场景分析五、使用技巧与最佳实践六、与其他工具的比较及优势 一、Blackmagic Disk Speed Test 概述 Blackmagic Disk Speed Test 是 Mac 平台上广受专业人士青睐的一…...
使用WebSocket实时获取印度股票数据源(无调用次数限制)实战
使用WebSocket实时获取印度股票数据源(无调用次数限制)实战 一、前置准备 1. 获取API密钥 登录 StockTV开发者平台 → 联系客服获取测试Key(格式MY4b781f618e3f43c4b055f25fa61941ad),该密钥无调用次数限制且支持实时…...
《前端面试题:CSS3新特性》
CSS3新特性指南:从基础到实战详解 CSS3作为现代Web开发的核心样式标准,彻底改变了前端开发者的工作方式。它不仅解决了传统CSS的诸多痛点,还引入了强大的布局模型、动画系统和响应式设计能力。本文将全面解析CSS3的十大核心新特性࿰…...
Cursor 1.0 的核心功能亮点及技术价值分析
Cursor 1.0 的核心功能亮点及技术价值分析 结合官方更新和开发者实测整理: 🛠️ 一、BugBot:智能自动化代码审查 功能亮点:深度集成 GitHub,自动扫描 Pull Request(PR)中的潜在 Bug(…...
大模型编程助手-Cline
官网: https://cline.bot/ Cline 是一款深度集成在 Visual Studio Code(VSCode) 中的开源 AI 编程助手插件,旨在通过结合大语言模型(如 Claude 3.5 Sonnet、DeepSeek V3、Google Gemini 等)和工具链&#…...
《ERP原理与应用教程》第3版习题和答案
ERP原理与应用教程是一门系统介绍企业资源计划(Enterprise Resource Planning, ERP)系统核心理论、技术架构及实施应用的综合性课程。它主要面向管理类、信息类、工程类等专业学生及企业管理者,旨在培养对现代企业信息化管理的理解与实践能力。以下是该课程的详细解析: 一…...
Git Svn
github一般需要科学上网,通过SourceTree通过URL克隆,会提示无效URL或者SLL Timeout之类,如果电脑开启了VPN,在系统设置-网络-DNS查看代理端口,如:127.0.0.1:7890 手动配置git代理 git config --global ht…...