认识springboot
什么是SpringBoot
- JavaEE的一站式解决方案,一套真正的Spring全家桶应用
- Spring Boot是为了简化Spring应用的创建、运行、调试、部署等而出现的。
- 使用它可以做到专注于Spring应用的开发,无需过多关注XML的配置。
- 它提供了一堆依赖包,并已经按照使用习惯解决了依赖问题。使用默认方式实现快速开发。
- 提供大多数项目所需的非功能特性,诸如:嵌入式服务器(Jetty)、安全、心跳检查、外部配置等。
- Spring Boot 不生成代码,完全无需 XML配置,创建即用。
第一个SpringBoot项目
idea快速创建SpringBoot
通过idea快速创建的SpringBoot项目的pom.xml中已经导入了我们选择的web的起步依赖的坐标
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.4.RELEASE</version>
<relativePath/>
</parent>
<groupId>com.javasm</groupId>
<artifactId>day1026</artifactId>
<version>0.0.1-SNAPSHOT</version>
<!--打包方式默认是jar包打包-->
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
parent父工程:指定当前项目的父工程,父工程统一了各个组件之间的版本兼容;统一maven插件配置
packaging打包方式:默认是jar包打包
starter启动器:
springboot对组件提供了启动器的概念,把该组件整合项目需要用到的各个依赖包进行整理,并把该组件需要加入spring容器的bean对象做了预配置。
官方的启动器:spring-boot-starter-web;spring-boot-starter-json;spring-boot-starter-jdbc;spring-boot-starter-redis
第三方的启动器:Druid-spring-boot-starter;mybatis-spring-boot-starter
spring-boot-maven-plugin插件:把项目打包为jar包,并设置Main-class启动类,目的是让该jar包是一个可执行的jar包
可以使用快速入门的方式创建Controller进行访问,此处不再赘述
IDEA使用Maven创建
1.在pom中加入SpringBoot依赖
<!-- Inherit defaults from Spring Boot -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.3.RELEASE</version>
</parent>
<!-- Add typical dependencies for a web application -->
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<!-- Package as an executable jar 不怎么用 -->
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
2.创建SpringBoot启动类(必须在所有类的最上层包中 com.javasm下)
@SpringBootApplication
public class SpringBootTestApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootTestApplication.class,args);
}
}
3.创建一个SpringMVC的控制类
@Controller
@RequestMapping("/hello")
public class HelloController {
@RequestMapping("/test1")
@ResponseBody
public String test1() {
return "index";
}
}
springboot项目结构
src/main/resources/static:静态资源
src/main/resources/templates:放html视图模板(jsp/freemarker/thymeleaf)
src/main/resources/application.properties:核心配置文件
启动类认识
-
被@SpringBootApplication标注的类就是当前SpringBoot应用的入口类。SpringBoot会在当前类中查找main方法并执行
-
@SpringBootApplication
-
@SpringBootConfiguration:表明该类是一个spring的配置类
-
@ComponentScan:开启包扫描,具体的扫描路径由EnableAutoConfiguration来做配置。
-
@EnableAutoConfiguration :开启自动配置信息
-
@AutoConfigurationPackage:配置包的扫描范围,把当前启动类所在的包名作为包的扫描范围
-
@Import({AutoConfigurationImportSelector.class}):
通过配置类选择器,去所有jar包的META-INFO/spring.factories文件中
查找key为org.springframework.boot.autoconfigure.EnableAutoConfiguration的配置信息
选择到全部的预配置类
-
-
-
SpringApplication.run(Application.class, args)
- 初始化spring容器,加载配置类(当前类)
- 确定当前项目类型:(servlet项目)
- 错误分析器:初始化19个内置的错误分析器对象,把框架运行中产生的异常信息输出为可阅读的信息。
- 打印输出Banner: Banner printedBanner = this.printBanner(environment);
- 容器初始化: context = this.createApplicationContext()
注意 : 自定义的配置类放在启动类的同级或下级包下能生效;放在上级包不生效。是因为自动配置的包扫描路径是启动类的包名。
部署springboot项目
-
打jar包,cmd 通过 java -jar 包名 指令运行jar包。
-
打war包,把war放在服务器下的指定应用服务器tomcat,weblogic目录下。
- 指定war
- 指定war包名
- 把自带的tomcat启动器的scope指定为provided,不参与打包
<!--指定war--> <groupId>com.javasm</groupId> <artifactId>0827boot</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>war</packaging> <!--tomcat启动器修改--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> <scope>provided</scope> </dependency> <!--指定war包名--> <build> <finalName>0827boot</finalName> <!--<plugins>--> <!--<!–对springboot项目打jar使用,与maven默认的打包有区别–>--> <!--<plugin>--> <!--<groupId>org.springframework.boot</groupId>--> <!--<artifactId>spring-boot-maven-plugin</artifactId>--> <!--</plugin>--> <!--</plugins>--> </build>
- 从SpringBootServletInitializer接口重写configure方法,指定程序的入口。
- 从SpringBootServletInitializer类派生程序入口类,重写configure方法,把主配置类传给SpringApplicationBuiler对象。当tomcat启东时,查找SpringBootServletInitializer子类,并调用configure方法,SpringApplicationBuiler内会执行SpringApplication.run方法
@SpringBootApplication public class Day1026Application extends SpringBootServletInitializer { @Override protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) { return builder.sources(Day1026Application.class); } }
- 将打包好的war包放在Tomcat的webapps下 启动Tomcat
- 注 : 注掉插件里的 spring-boot-maven-plugin
springboot配置文件
@PropertySource("classpath:jdbc.properties") // 加载自定义properties配置文件
@ImportResource("classpath:spring.xml") // 加载自定义的spring风格的xml配置文件
@Import(MyAnnotationConfig.class) // 加载自定义的spring风格的配置类
这些注解是写在配置类中的,任何一个配置类中都可以。
配置信息以Application开头的文件,会自动加载。
配置文件格式:properties或者yml,properties优先级更高
properties
- 格式
常见配置如下:application.properties配置
#内嵌服务器端口号
server.port=8081
#当前项目访问路径
server.servlet.context-path=/javasm
#application.properties或者自定义的properties 格式一样
user.uname=fyt
user.uage=12
#时间格式固定
user.ubirthday=2011/11/11 12:12:12
#数组
user.ustrs=aa,bb,cc,dd
#map
user.umaps={home:"home",ccc:"home"}
- 使用
//application.properties可自动加载
//自定义的properties需 @PropertySource("classpath:名字.properties") 导入
//@Value取单个数据
//通过@ConfigurationProperties注解指定前缀批量获取数据。
//@ConfigurationProperties(prefix = "user")
@Configuration
//@PropertySource("classpath:test.properties")
//@ConfigurationProperties(prefix = "user")
public class MyCustomConfig {
@Value("${user.uname}")
private String uname;
@Value("${user.uage}")
private Integer uage;
@Value("${user.ubirthday}")
private Date ubirthday;
@Value("${user.ustrs}")
private String[] ustrs;
//map取值方式注意
@Value("#{${user.umaps}}")
private Map<String,String> umaps;
yml
- 语法规则
1、大小写敏感
2、使用缩进表示层级关系
3、禁止使用tab缩进,只能使用空格键
4、缩进长度没有限制,只要元素对齐就表示这些元素属于一个层级。
5、使用#表示注释
6、字符串可以不用引号标注 - 格式
#application.yml 不叫这个名字不行
server:
port: 8080
servlet:
context-path: /boot33333
user:
uname: fyt
uage: 12
ubirthday: 2011/11/11 12:12:12
ustrs: aa,bb,cc,dd
#冒号后都要空格
umaps: {a: 1,b: 2,c: 3}
#maps--格式2
umaps:
a: cccc
b: bbb
-
使用如上
注: @Value 不支持map list这种复杂的数据结构 只能取单个值
-
配置文件可以放的位置:
- 项目下/config
- 项目下
- 项目下/resources/config
- 项目下/resources
SpringBoot静态资源
在springboot中默认提供了4个静态资源目录,推荐使用src/main/resources/static目录做静态目录:
src/main/resources/META-INF/resources/, 优先级最高
src/main/resources/resources/,
src/main/resources/static/,
src/main/resources/public/ 优先级最低
欢迎页
在四个静态资源目录下加index.html即可。按照优先级查找,查找到就生效。
替换项目浏览器图标
-
用的是外部tomcat:
把favicon.ico放在root目录
-
用的时内嵌tomcat:
把favicon.ico放在静态资源目录即可
thymeleaf模板引擎
简介
- 作用:做同步开发使用,前端代码与后端代码在一个项目中。类似于jsp,用来获取后端java代码的数据(request,session,servletContext),在html中使用模板引擎技术来获取数据。
- 同步:用户发起请求url(http://ip:port/后端接口url)–>进入我们控制层代码–>调用服务层代码–>得到数据–>把数据放在request对象–>返回html视图–>在视图中使用jsp或thymeleaf等类似的引擎技术来获取request对象中的数据–>动态生成纯静态的html代码(遍历或显示数据)–>生成的html代码返回客户端。
- 异步:用户请求(请求页面html)–>页面加载函数中发起异步请求(ajax或axios)–>调用服务层代码–>得到数据–>把数据返回客户端–>异步请求回调函数中解析数据渲染视图.
- jsp:编写.jsp–>当用户第一次请求XXX.jsp–>jsp引擎对XXX.jsp进行翻译,翻译成XXX.java–>虚拟机把XXX.java编译成XXX.class–>–>加载字节码到虚拟机–>实例化对象,执行service方法,获取数据,进行渲染,输出纯静态的html字符串给前端
- thymeleaf:编译.html–>当用户第一次请求XXX.html–>thymeleaf引擎把.html加载到内存进行引擎语法解析–>基于内存把视图模板存储–>生成静态的html
- 总结:解析动态数据,生成静态html.与jsp功能一样。
- springBoot官方不支持jsp,推荐同步开发使用thymeleaf。
- 相对于jsp来说,执行效率更加优秀。对于前端ui与程序员更加友好。
使用thymeleaf
-
加thymeleaf启动器依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency>
-
开发时,都要把thymleaf基于内存存储模板禁用掉。
#禁用thymeleaf内存缓存,提高开发效率。 spring: thymeleaf: cache: false
模板语法:
-
表达式
1.属性表达式:${},专用来获取request,session,servletContext对象中的数据:
request:[[${key}]] sesison:[[${session.key}]] sesison:[[${#session.getAttribute('key')}]] servletContext:[[${#servletContext.getAttribute('key')}]]
2.链接表达式:@{},自动补全项目的根路径。
<script src="/js/jquery-3.4.1.js" th:src="@{/js/jquery-3.4.1.js}"></script> //链接传参 <a th:href="@{/url(key=${},key=${})}">点我</a> //注:这个也自动补全项目的根路径 var url="[[@{/user/gomain}]]"; console.log(url);
3.文档表达式:~{} 用来做页面的嵌套,写文档名即可
//commons.html <div th:fragment="topFragment" style="height: 50px;background-color:greenyellow"> 公共的top页面 </div> <div th:fragment="bottomFragment" style="height: 50px;background-color:greenyellow"> 公共的bottom页面 </div>
<div th:insert="~{common :: topFragment}"></div> <div th:replace="~{common :: bottomFragment}"></div> common是要引入模块的文件名。
-
属性:
th:text:结合属性表达式使用,为双标签赋值
<span th:text="${requestData.uname}"></span>
th:value:结合属性表达式使用,给单标签赋值。
<input type="text" value="sss" th:value="${requestData.uname}">
th:src: 结合链接表达式使用
<script src="/js/jquery-3.4.1.js" th:src="@{/js/jquery-3.4.1.js}"></script>
th:href:结合链接表达式使用
<a th:href="@{/user/gomain(uname=${uname})}">点我</a>
th:action:结合链接表达式使用
th:insert: 结合文档表达式使用,做页面嵌套
th:replace:结合文档表达式使用,做页面嵌套
th:fragment:结合文档表达式使用,做局部页面嵌套
th:each:结合属性表达式获取后端的集合数据,遍历显示数据。
<table style=" border: 1px solid black;" > <th> <td>序号</td> <td>id</td> <td>uname</td> </th> <tr th:each="user,status : ${users}" th:if="${status.count%2!=0}"> <td>[[${status.count}]]</td> <td>[[${user.uid}]]</td> <td th:text="${user.uname}"></td> </tr> </table>
WebMvcConfigurer接口进行springMVC扩展使用
- addCorsMappings方法添加的跨域支持,在拦截器中需要对预检请求放行。
@Component
public class MyWebMvcConfig implements WebMvcConfigurer {
//视图映射器,同步开发中使用
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/user/userlist").setViewName("userlist");
registry.addViewController("/role/rolelist").setViewName("rolelist");
registry.addViewController("/login").setViewName("login");//进入到/templates/login.html
}
//不重要,前端日期字符串,springMVC收到数据转Date对象,与@DateTimeFormate
//MyDateConverter是需要转化的类
@Override
public void addFormatters(FormatterRegistry registry) {
registry.addConverter(new MyDateConverter());
}
//拦截器
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new MyLoginIntercetptor())
// 拦截
.addPathPatterns("/**")
// 忽略
.excludePathPatterns("/user/valicode/**","/login","/css/**","/js/**");
}
//跨域配置
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedHeaders("*")
.allowedMethods("*")
.allowCredentials(true)
.exposedHeaders("token");
}
}
springboot的异常处理
异常处理流程:当应用产生异常,转向/error的处理器,如果是浏览器请求,则进入BasicErrorController的errorHtml方法进行异常处理,通过DefaultErrorAttributes对象获取异常数据,是先去templates下查找error/错误码视图资源,找到则返回;找不到的话去四个静态资源目录下查找视图名为error/404.html ,以及error/4xx.html,如果找不到则返回默认错误视图StaticView。
如果不是浏览器请求,通过DefaultErrorAttributes对象获取异常数据,转json字符串返回调用者。
- 针对于同步开发使用。不能达到返回的前端不同的错误信息(比如token过期,密码有误等等自定义的错误信息).
- 使用浏览器测试请求:返回的是错误页面。
- 使用postman测试:返回的是json数据。
- 异常处理机制:
ErrorMvcAutoConfiguration配置类中有三个核心的异常处理的bean:
1.BasicErrorController:映射路径/error,出现异常tomcat会把请求转到/error的处理器中。
errorHtml:浏览器请求的处理器方法,查找错误视图,如果查找不到,则使用viewName为error的错误 视图。
error:异步请求的处理器方法,直接返回json数据。
2.DefaultErrorAttributes:该对象中getErrorAttributes方法,生成了一个Map,该集合中包含了固定的错误信息。
3.StaticView默认错误视图,该视图的名字叫:error
4.在四个静态资源路径下定义error/错误码.html|error/4xx.html,5xx.html
5.怎么扩展错误信息,从DefaultErrorAttributes派生子类,注入容器,替换掉默认的bean对象。
- 日常开发中,仍然使用全局统一异常处理:
- @ControllerAdivce,@ExceptionHandler,自定义异常,状态枚举,响应体对象。
日志集成
- 加入log4j2启动器
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
- 加入log4j2.xml到resources目录
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appenders>
<!-- 控制台输出 -->
<console name="Console" target="SYSTEM_OUT">
<PatternLayout
pattern="%d{HH:mm:ss.SSS} [%t] %-5level %class %L %M -- %msg%n" />
</console>
<!-- fileName:输出路径 filePattern:命名规则 -->
<RollingFile name="RollingFileDebug"
fileName="D:/logs/debug.log"
filePattern="D:/logs/$${date:yyyy-MM-dd}/debug-%d{yyyy-MM-dd}-%i.log">
<Filters>
<ThresholdFilter level="DEBUG" />
<ThresholdFilter level="INFO" onMatch="DENY"
onMismatch="NEUTRAL" />
</Filters>
<!-- 输出格式 -->
<PatternLayout
pattern="%d{HH:mm:ss.SSS} [%t] %-5level %class{36} %L %M - %msg%n" />
<Policies>
<!-- 单个日志文件的大小限制 -->
<SizeBasedTriggeringPolicy size="100 MB" />
</Policies>
<!-- 最多保留20个日志文件 -->
<DefaultRolloverStrategy max="20" />
</RollingFile>
<RollingFile name="RollingFileInfo"
fileName="D:/logs/info.log"
filePattern="D:/logs/$${date:yyyy-MM-dd}/info-%d{yyyy-MM-dd}-%i.log">
<Filters>
<ThresholdFilter level="INFO" />
<ThresholdFilter level="WARN" onMatch="DENY"
onMismatch="NEUTRAL" />
</Filters>
<!-- 输出格式 -->
<PatternLayout
pattern="%d{HH:mm:ss.SSS} %-5level %class{36} %L %M - %msg%xEx%n" />
<Policies>
<!-- SizeBasedTriggeringPolicy单个文件的大小限制 -->
<SizeBasedTriggeringPolicy size="100 MB" />
</Policies>
<!-- DefaultRolloverStrategy同一个文件下的最大文件数 -->
<DefaultRolloverStrategy max="20" />
</RollingFile>
<RollingFile name="RollingFileWarn"
fileName="D:/logs/warn.log"
filePattern="D:/logs/$${date:yyyy-MM}/warn-%d{yyyy-MM-dd}-%i.log">
<Filters>
<ThresholdFilter level="WARN" />
<ThresholdFilter level="ERROR" onMatch="DENY"
onMismatch="NEUTRAL" />
</Filters>
<PatternLayout
pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n" />
<Policies>
<!--<TimeBasedTriggeringPolicy modulate="true" interval="1"/> -->
<SizeBasedTriggeringPolicy size="100 MB" />
</Policies>
<!--最多保留20个日志文件 -->
<DefaultRolloverStrategy max="20" min="0" />
</RollingFile>
<RollingFile name="RollingFileError"
fileName="D:/logs/error.log"
filePattern="D:/logs/$${date:yyyy-MM}/error-%d{yyyy-MM-dd}-%i.log">
<Filters>
<ThresholdFilter level="ERROR" />
<ThresholdFilter level="FATAL" onMatch="DENY"
onMismatch="NEUTRAL" />
</Filters>
<PatternLayout
pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n" />
<Policies>
<!--<TimeBasedTriggeringPolicy modulate="true" interval="1"/> -->
<SizeBasedTriggeringPolicy size="100 MB" />
</Policies>
<!--最多保留20个日志文件 -->
<DefaultRolloverStrategy max="20" min="0" />
</RollingFile>
</appenders>
<loggers>
<!--异步日志-->
<!--<AsyncLogger name="org.springframework" level="error" includeLocation="true">-->
<!--<AppenderRef ref="RollingFileError"></AppenderRef>-->
<!--</AsyncLogger>-->
<!--<AsyncLogger name="com.alibaba.druid" level="error" includeLocation="true">-->
<!--<AppenderRef ref="RollingFileError"></AppenderRef>-->
<!--</AsyncLogger>-->
<!--<AsyncRoot level="DEBUG" includeLocation="true">-->
<!--<appender-ref ref="Console"/>-->
<!--<appender-ref ref="RollingFileDebug"/>-->
<!--<appender-ref ref="RollingFileInfo"/>-->
<!--<appender-ref ref="RollingFileWarn"/>-->
<!--<appender-ref ref="RollingFileError"/>-->
<!--</AsyncRoot>-->
<!--同步日志-->
<logger name="org.springframework" level="error"></logger>
<logger name="org.mybatis.spring" level="ERROR"></logger>
<logger name="com.zaxxer.hikari" level="ERROR"></logger>
<root level="DEBUG">
<appender-ref ref="Console"/>
<appender-ref ref="RollingFileDebug"/>
<appender-ref ref="RollingFileInfo"/>
<appender-ref ref="RollingFileWarn"/>
<appender-ref ref="RollingFileError"/>
</root>
</loggers>
</configuration>
- 排除掉可能重复导入的jar包。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<artifactId>spring-boot-starter-logging</artifactId>
<groupId>org.springframework.boot</groupId>
</exclusion>
</exclusions>
</dependency>
定时任务
-
springboot内部集成,不需要引入jar包,不需要配置。
-
定时任务使用务必存进redis或mysql,以防服务器挂掉定时任务丢失。
-
使用(基本同spring):
- 启动类添加注解
@EnableScheduling
- 编写定时任务
@Component
public class ScheduleService {
@Scheduled(cron = "*/5 15 18 * * ?")
public void scheduledTest(){
System.out.println("定时任务");
}
}
mybatis集成
- 引入mybatis-spring-boot-starter启动器,内部依赖了spring-jdbc;spring-tx;mybatis;mybatis-spring
- 引入Druid-spring-boot-starter启动器,DruidDataSourceAutoConfigure自动配置类生效,初始化DataSource对象。
<!-- mybatis依赖-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.2</version>
</dependency>
<!-- mysql驱动依赖-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!--durid依赖-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.10</version>
</dependency>
<!--分页依赖-->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.2.12</version>
</dependency>
<!--mybatis逆向工程插件-->
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.4.0</version>
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
</dependencies>
<configuration>
<configurationFile>src/main/resources/generator.xml</configurationFile>
</configuration>
</plugin>
- 配置 application.yml
spring:
#配置数据库连接信息
datasource:
type: com.alibaba.druid.pool.DruidDataSource
#基本属性
url: jdbc:mysql://localhost:3306/数据库名?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&serverTimezone=GMT%2B8&useSSL=false
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
druid:
#配置初始化大小
initial-size: 3
#开发时候thymleaf缓存禁用
thymeleaf:
cache: false
#mybatis配置,只有mapper-locations是必须
mybatis:
#xml文件扫描
mapper-locations: classpath:com/javasm/*/mapper/*.xml
#别名
type-aliases-package: com.javasm
configuration:
#驼峰映射
map-underscore-to-camel-case: true
#分页配合,不必要 下面分页用
pagehelper:
properties: reasonable=true
- 在启动类上加@MapperScan(“com.javasm.*.mapper”)进行mapper接口扫描创建代理对象。
- 在启动类上@EnableTransactionManagment开启事务控制
@MapperScan("com.javasm.*.mapper") //mapper接口扫描
@EnableTransactionManagement //事务控制
- 在pom文件中配置resources资源
<!--build 里添加-->
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*</include>
</includes>
</resource>
</resources>
- 在pom文件中引入PageHelper-spring-boot-starter
<!--指定好版本 最上面加上了-->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.2.12</version>
</dependency>
redis集成
- 引入启动器:spring-boot-starter-data-redis,去掉默认的lettuce,引入jedis
<!--redis-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<exclusions>
<exclusion>
<groupId>io.lettuce</groupId>
<artifactId>lettuce-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
- 在applicatin.yml中配置redis服务器连接信息(host,port,password,database)
spring:
redis:
host: 127.0.0.1
database: 0
port: 6379
password: root
-
操作redis服务器
-
使用spring-data-redis中提供的redis操作工具类RedisTemplate<String,Object>,建议使用
-
更加灵活,用的更多
- 使对象自动序列化成JSON
RedisTemplate:内部默认的序列化方案是:JdkSerializationRedisSerializer,使用时候需要重新配置key与value,hashKey与hashValue的序列化方案。 StringRedisTemplate:内部默认的序列化方案是StringRedisSerializer 在实际的开发中,我们会经常讲用户信息或其他对象信息以json的方式保存至redis中。而每次我们都需要在代码中将对象给重新序列化成json,这样就会很麻烦。实际上在RedisAutoConfiguration中,我们可以看到以下两个方法,他们分别向容器中注册了redisTemplate和stringRedisTemplate两个方法,并向容器中注册了两个对象。而StringRedisTemplate就是我们上述使用的字符串操作对象。 RedisTemplate就是可以直接保存对象的模板。而在RedisTemplate类中我们可以看到如下信息:
该类分别由两个成员对象,key序列化和值序列化对象。基于这样的情况,我们只需要在Spring初始化的时候,自己创建一个RedisTemplate对象并给它设置自定义的值序列化对象。
当我们重新定义了RedisTemplate之后,我们就可以直接进行对象保存了。
@Configuration public class MyCustomConfiguation { @Bean(name="redisTemplate") public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) throws UnknownHostException { RedisTemplate<String, Object> template = new RedisTemplate(); template.setKeySerializer(new StringRedisSerializer()); template.setValueSerializer(new GenericJackson2JsonRedisSerializer()); template.setHashKeySerializer(new StringRedisSerializer()); template.setHashValueSerializer(new GenericJackson2JsonRedisSerializer()); template.setConnectionFactory(redisConnectionFactory); return template; } }
@Service public class SysuserServiceImpl implements ISysuseService { @Resource private SysUserMapper sm; @Resource private RedisTemplate<String, Object> rt; @Override public SysUser selectUserById(Integer uid) { String key="userinfo:"+uid; ValueOperations<String, Object> vo = rt.opsForValue();//操作字符串 Object o = vo.get(key);//ObjectInputStream执行对象的反序列化操作, if(o!=null){ return (SysUser)o; }else{ SysUser sysUser = sm.selectByPrimaryKey(uid); //底层会调用jdk对象序列化把value序列化成字符串 vo.set(key,sysUser,10,TimeUnit.MINUTES); //ObjectOutputStream 要求:对象是可序列化的,从Serializable接口派生。 return sysUser; } // ListOperations<Object, Object> lo = rt.opsForList();//操作list } }
-
-
使用注解,@Cacheable,@CacheEvict
- 用的较少,适合于经典redis应用,查数据先查询缓存,有的话则返回,没有则查询数据库,把数据库查询结果放缓存。数据不需要设置有效期。
- 要使用注解首先在启动类开启注解识别。@EnableCaching
@EnableCaching //开启redis注解识别
- Cacheable应用在查询方法上。
- CacheEvict应用在删,改方法上。
@Service public class SysuserServiceImpl implements ISysuseService { @Resource private SysUserMapper sm; //condition:对参数进行条件判断,条件为true,则放缓存 // unless:对返回结果进行条件判断,条件为true,则不放缓存 //cacheNames-分组名字 key-key @Cacheable(cacheNames = "userinfo",key = "#uid",condition = "#uid>0",unless = "#result==null") @Override public SysUser selectUserById(Integer uid) { SysUser sysUser = sm.selectByPrimaryKey(uid); return sysUser; } @CacheEvict(cacheNames ="userinfo",key="#user.uid") @Override public void updateUser(SysUser user) { sm.updateByPrimaryKeySelective(user); } }
-
mybatis-plus
-
创建 Developer Tools–>Spring Boot DevTools Web–>Spring Web Template
Engines–>Thymeleaf SQL–>MySQL Driver
-
引入mybatis-plus的pom,基于mybatis,所以不需要重复引入mybatis的pom。
-
与pagehelper包冲突,排出冲突的jar包(pagehelper不需要就删掉)
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.0</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.10</version>
</dependency>
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.2.13</version>
<exclusions>
<exclusion>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
</exclusion>
<exclusion>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
</exclusion>
</exclusions>
</dependency>
- Application.java配置MapperScan
@MapperScan("com.javasm.mapper")
@EnableTransactionManagement
- 配置datasource
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://192.168.14.241:3306/crm?characterEncoding=UTF8&useSSL=true&serverTimezone=Asia/Shanghai
username: root
password: root
实体类用到的注解
@TableName("test_mybatisplus") //指定表名,默认是实体类做表名
public class TestMybatisplus {
@TableId(type = IdType.ASSIGN_ID) // 分布式唯一id,雪花算法
private Long tid;
private String tname;
private String tadd;
private String tcreatetime;
private String tupdatetime;
@TableField(exist = false) // 非数据库字段 指定某个成员变量不属于数据库表的字段
private String authControl;
@Version // 乐观锁注解
private Integer tversion;
}
12345678910111213141516
crud测试
@SpringBootTest
public class MyBatisPlusTest {
@Resource
private ApplySimpleMapper2 sm;
@Test
public void add(){
TestMybatisplus mp = new TestMybatisplus();
mp.setTname("测试");
int insert = sm.insert(mp);
// mybatisplus会自动把当前插入对象在数据库中的id写回到该实体中
System.out.println(mp.getTid());
}
@Test
public void update(){
TestMybatisplus mp = new TestMybatisplus();
mp.setTid(123L);
mp.setTname("测试9");
// 乐观锁插件配置之后,更新成功version会自增加一,version不一致更新返回值为0
mp.setTversion(1);
//根据id进行更新,没有传值的属性就不会更新
int i = sm.updateById(mp);
System.out.println(i);
}
@Test
public void select(){
// 条件构造器
QueryWrapper wrapper = new QueryWrapper();
wrapper.between("tcreatetime","2020-08-20","2020-09-20");
wrapper.like("tname","测试");
List<TestMybatisplus> testMybatispluses = sm.selectList(wrapper);
// Map<String, Object> map = new HashMap<>();
// map.put("tname","测试4");
// List<TestMybatisplus> testMybatispluses = sm.selectByMap(map);
System.out.println(testMybatispluses);
}
}
自定义配置类,配置分页插件及乐观锁插件
@Configuration
public class MyConfiguration {
//Jackson中通过ObejctMapper对象的writeValueAsString
// 由于分布式id过长,js会精度损失,将id转为string再序列化
@Bean
ObjectMapper jacksonObjectMapper(Jackson2ObjectMapperBuilder builder) {
ObjectMapper build = builder.createXmlMapper(false).build();
build.setSerializationInclusion(JsonInclude.Include.NON_NULL);//非空才序列化
SimpleModule module = new SimpleModule();
module.addSerializer(Long.class,ToStringSerializer.instance);
module.addSerializer(long.class,ToStringSerializer.instance);
build.registerModule(module);
return build;
}
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
//分页拦截器
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
//乐观锁拦截器
interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
return interceptor;
}
}
逆向工程
- pom引入,使用freemarker模板引擎
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.4.0</version>
</dependency>
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.30</version>
</dependency>
- 生成代码使用官网模板,稍作修改即可。
分页插件使用
@RestController
@RequestMapping("/generator")
public class TestMybatisplusController {
@Resource
private ITestMybatisplusService ms;
@GetMapping("mp")
public ResponseEntity getmp(@RequestParam(defaultValue = "1") Integer pageNum, @RequestParam(defaultValue = "2")Integer pageSize){
IPage<MP> page = new Page<>(pageNum,pageSize);
IPage<MP> page1 = ms.page(page);
return ResponseEntity.ok(page1);
}
}