springboot

认识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>-->
    			<!--&lt;!&ndash;对springboot项目打jar使用,与maven默认的打包有区别&ndash;&gt;-->
    			<!--<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);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值