一、springboot 概述
-
非常轻易的构建独立的、生产级别的 spring 应用。
-
二、了解 js 的后台程序的编写与运行
-
人们把 spring boot 称为搭建程序的脚手架。极大地减轻了开发的工作量,好处在于设计者可以把精力更多的用在业务逻辑的设计上。
二、为什么会出现 spring boot
- 基于 spring 框架的开发需要写很多配置,它提供了大量的默认配置(默认优于配置),可以大大减轻配置工作量。
- 当项目中使用的第三方库或框架比较多时,通过 maven 引入的依赖就很复杂,常常出现依赖(jar)冲突及版本之间的冲突(无意义的工作)。它利用启动器来引入依赖,另外它为项目提供了 parent 启动器,因此使用第三方的库或框架时不再需要指定版本号了,由 spring boot 来提供合适的版本号。
三、spring boot 的主要特征
- 创建独立的spring应用程序;
- 直接内嵌 tomcat、jetty 和 undertow(不需要打包成 war 包部署,是 jar 包,因此不需要专门安装 tomcat,只需要 java -jar XXX.jar 就可以使用了);
- 提供了固定化的 “starter”(启动器) 配置,以简化构建配置(写依赖),由 spring 提供的启动器名称以 spring-boot 开头,如果由第三方提供,名称以框架的名称开头。比如说 mybatis 的启动器是由 mybatis 提供,名称就是 mybatis-spring-boot-starter;
- 尽可能的自动配置 spring 和第三方库,自动配置是 springboot 工作原理中最核心的部分;
- 提供产品级的功能,如:安全指标、运行状况监测和外部化配置等;
- 绝对不会生成代码(不需要写自动配置的代码),并且不需要 XML 配置,用 springboot 时,不再使用 xml 配置;
四、创建 springboot 项目的三种方式
-
通过官网提供的项目创建器来创建。
-
通过 idea 提供的 springboot 的创建器来创建。
-
直接创建 maven 项目,自己手动指定启动器及 parent 项目的依赖。
-
引入依赖:
-
spring-boot-starter-parent;
-
web 项目的启动器:spring-boot-starter-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 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.zhong</groupId> <artifactId>micro-service</artifactId> <version>1.0-SNAPSHOT</version> <packaging>jar</packaging> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.5.4</version> </parent> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies> </project>
-
-
执行项目:
-
package com.zhong.microservice.controller; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; /** * @author 华韵流风 * @ClassName MyController * @Date 2021/9/10 17:50 * @packageName com.zhong.microservice.controller * @Description TODO */ @RestController @RequestMapping("/microservice") @EnableAutoConfiguration public class MyController { @RequestMapping("/hello") public String hello(){ return "hello springboot 2.5.4"; } public static void main(String[] args) { SpringApplication.run(MyController.class, args); } }
-
当前项目默认不具备热部署的功能,需要设置:
- 添加 spring-boot-devtools 依赖;
- 勾选 Compiler→Build project automatically;
- ctrl + shift + alt + / 找到 compiler.automake.allow.when.app.running 并勾选。
-
-
五、在 spring 中创建专门的启动类
-
框架要求在项目中创建一个专门的用来启动项目的类,该类必须有 main 方法。
-
package com.zhong.microservice; import com.zhong.microservice.controller.MyController; import org.springframework.boot.SpringApplication; /** * @author 华韵流风 * @ClassName SpringBootApplication * @Date 2021/9/12 10:20 * @packageName com.zhong.microservice.controller * @Description TODO */ @org.springframework.boot.autoconfigure.SpringBootApplication public class SpringBootApplication { public static void main(String[] args) { SpringApplication.run(SpringBootApplication.class, args); } }
-
@org.springframework.boot.autoconfigure.SpringBootApplication,它由三个注解组成:
- @SpringBootConfiguration java 配置注解,可以使用它实现 spring 的配置功能,因此启动类可以具有配置的功能;
- @EnableAutoConfiguration 开启自动配置;
- @ComponentScan 它可以扫描本类所在的包及所有的子包,所以项目中其他需要扫描的包都会被扫到。
六、关于自动配置
-
spring 框架配置方式的演变过程
- spring 1.0 时代,采用 xml 配置,这种配置需要添加额外的文件,它具有严格的语法要求,书写标签及其属性用到的符号比较多,较为麻烦。
- spring 2.0 时代,采用注解配置,因此项目中的配置由注解和 xml 文件组成。
- spring 3.0 时代,采用 java 配置,专门创建一个类作为配置类,该类中的方法都要加 @Bean 注解,返回值就是需要创建的 Bean,取代 <Bean> 标签。因此项目的配置由注解和 java 配置组成。当前的 springboot 采用的就是这种方式。
-
一般的配置中都有属性,springboot 中专门定义了设置属性的类型,让相关的属性也成为一个 Bean,然后在配置 Bean 中注入属性 Bean,从而在两者之间实现解耦,这样属性 Bean 就具有了共用性。
-
@ConfigurationProperties 表示当前类是属性类,它用类中的成员变量来表示在属性文件中所定义的属性值。它是 springboot 中的注解,springboot 中的配置文件只能有一个,按照规定的默认的名称,application.properties(application.yml 或 yaml)。因此,该注解引用的属性值必须来源于这个配置文件而不能是其它的文件。
-
在 springboot 的 java 配置类中引用外部的属性对象有四种方式:
-
jdbc.driverClassName =com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/goods?serverTimezone=GMT%2B8&characterEncoding=utf-8&useSSL=false jdbc.username= jdbc.password=
-
package com.zhong.microservice.config; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Configuration; /** * @author 华韵流风 * @ClassName JdbcProperties * @Date 2021/9/12 11:22 * @packageName com.zhong.microservice.config * @Description TODO */ @Configuration @ConfigurationProperties(prefix = "jdbc") public class JdbcProperties { private String driverClassName ; private String url; private String username; private String password; public String getDriverClassName() { return driverClassName; } public void setDriverClassName(String driverClassName) { this.driverClassName = driverClassName; } public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } }
-
@Autowired
-
package com.zhong.microservice.config; import com.alibaba.druid.pool.DruidDataSource; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.PropertySource; /** * @author 华韵流风 * @ClassName JdbcConfig * @Date 2021/9/12 11:05 * @packageName com.zhong.microservice.config * @Description TODO */ @Configuration @EnableConfigurationProperties(JdbcProperties.class) public class JdbcConfig { @Autowired private JdbcProperties jdbcProperties; @Bean public DruidDataSource druidDataSource(){ DruidDataSource dataSource = new DruidDataSource(); dataSource.setDriverClassName(jdbcProperties.getDriverClassName()); dataSource.setUrl(jdbcProperties.getUrl()); dataSource.setUsername(jdbcProperties.getUsername()); dataSource.setPassword(jdbcProperties.getPassword()); return dataSource; } }
-
-
采用构造方法注入
-
package com.zhong.microservice.config; import com.alibaba.druid.pool.DruidDataSource; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.PropertySource; /** * @author 华韵流风 * @ClassName JdbcConfig * @Date 2021/9/12 11:05 * @packageName com.zhong.microservice.config * @Description TODO */ @Configuration @EnableConfigurationProperties(JdbcProperties.class) public class JdbcConfig { // @Autowired private JdbcProperties jdbcProperties; public JdbcConfig(JdbcProperties jdbcProperties) { this.jdbcProperties = jdbcProperties; } @Bean public DruidDataSource druidDataSource(){ DruidDataSource dataSource = new DruidDataSource(); dataSource.setDriverClassName(jdbcProperties.getDriverClassName()); dataSource.setUrl(jdbcProperties.getUrl()); dataSource.setUsername(jdbcProperties.getUsername()); dataSource.setPassword(jdbcProperties.getPassword()); return dataSource; } }
-
-
采用方法参数
-
package com.zhong.microservice.config; import com.alibaba.druid.pool.DruidDataSource; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.PropertySource; /** * @author 华韵流风 * @ClassName JdbcConfig * @Date 2021/9/12 11:05 * @packageName com.zhong.microservice.config * @Description TODO */ @Configuration @EnableConfigurationProperties(JdbcProperties.class) public class JdbcConfig { /*@Autowired private JdbcProperties jdbcProperties;*/ @Bean public DruidDataSource druidDataSource(JdbcProperties jdbcProperties){ DruidDataSource dataSource = new DruidDataSource(); dataSource.setDriverClassName(jdbcProperties.getDriverClassName()); dataSource.setUrl(jdbcProperties.getUrl()); dataSource.setUsername(jdbcProperties.getUsername()); dataSource.setPassword(jdbcProperties.getPassword()); return dataSource; } }
-
-
在 @Bean 方法上添加注解 @ConfigurationProperties(“jdbc”),利用反射技术进行自动属性装配。此时 JdbcProperties.java 可不加注解。
-
package com.zhong.microservice.config; import com.alibaba.druid.pool.DruidDataSource; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.PropertySource; /** * @author 华韵流风 * @ClassName JdbcConfig * @Date 2021/9/12 11:05 * @packageName com.zhong.microservice.config * @Description TODO */ @Configuration //@EnableConfigurationProperties(JdbcProperties.class) public class JdbcConfig { /*@Autowired private JdbcProperties jdbcProperties;*/ @Bean @ConfigurationProperties("jdbc") public DruidDataSource druidDataSource(){ DruidDataSource dataSource = new DruidDataSource(); /*dataSource.setDriverClassName(jdbcProperties.getDriver()); dataSource.setUrl(jdbcProperties.getUrl()); dataSource.setUsername(jdbcProperties.getUsername()); dataSource.setPassword(jdbcProperties.getPassword());*/ return dataSource; } }
-
-
-
了解 springboot 的自动配置
- springboot 项目需要使用的依赖主要通过启动器来完成,启动器会引用与自动配置内容相关的 jar。
- spring.factories 文件,EnableAutoConfiguration 属性的值就是可以使用自动配置的所有的功能,相当于总阀门。
- spring-configuration-metadata.json 文件,其中的数据就是所有的默认配置及值。
- spring-boot-autoconfigure-2.5.4.jar 中的 autoconfigure 包中,包含了可以实现配置功能的所有的 java 配置对象和属性对象,它与 spring.factories 文件中的 EnableAutoConfiguration 属性是一一对应的。
七、关于 springmvc 的内容
-
三大器:处理器映射器、处理器适配器、视图解析器。spring-boot-starter-web 被引用,项目中就可以使用 springmvc 的功能。
-
几个主要的注解:@Controller,@RequestMapping,@ResponseBody,@RequestParam 等在 springboot 中都可以使用。
-
中央调度器,它的处理路径(url-pattern)是 /,它会拦截所有的请求。因此可以处理 restful 风格的请求。
-
关于静态资源(CSS,JS,image,HTML 等)的处理,静态资源存放在项目中的位置可以通过配置的方式来指定的。
- CLASSPATH_RESOURCE_LOCATIOINS={“classpath:/resources/”,“classpath:/META-INF/resources/”,“classpath:/static/”,“classpath:/public/”};
- 以上四个位置都可以用来存放静态资源,放在这四个位置的静态资源可以在项目中直接使用,也可以被外部直接访问。
-
文件上传,对应的解析器不用专门配置,可以设置相关属性。(在 application.properties 文件中)
-
创建并配置拦截器,在 springmvc 中,创建拦截器必须实现 HandlerInterceptor 接口,然后在配置文件中对它进行配置,还需要指定它所拦截的路径。在 springboot 中配置拦截器采用 java 配置,实现 WebMvcConfigurer 接口,在接口的 addPathPatterns 中来指定拦截器及路径。
-
preHandle:
- 执行时机:Controller 方法执行之前;
- 执行顺序:链式 Intercepter 情况下,Intercepter 按照声明的顺序一个接一个执行;
- 若返回 false,则中断执行,注意:不会进入 afterCompletion
-
postHandle:
- 执行前提:preHandle 返回 true;
- 执行时机:Controller 方法处理完之后,DispatcherServlet 进行视图的渲染之前,也就是说在这个方法中你可以对 ModelAndView 进行操作;
- 执行顺序:链式 Intercepter 情况下,Intercepter 按照声明的顺序倒着执行;
- postHandle虽然post打头,但 post、get 方法都能处理;
-
afterCompletion:
- 执行前提:preHandle 返回true;
- 执行时机:DispatcherServlet 进行视图的渲染之后;
- 多用于清理资源。
-
package com.zhong.microservice.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; /** * @author 华韵流风 * @ClassName MyInterceptor * @Date 2021/9/12 15:12 * @packageName com.zhong.microservice.interceptor * @Description TODO */ @Component public class MyInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("preHandle"); return true; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("postHandle"); } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("afterCompletion"); } }
-
package com.zhong.microservice.config; import com.zhong.microservice.interceptor.MyInterceptor; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; /** * @author 华韵流风 * @ClassName MyWebMvcConfiguration * @Date 2021/9/12 15:15 * @packageName com.zhong.microservice.config * @Description TODO */ @Configuration public class MyWebMvcConfiguration implements WebMvcConfigurer { @Autowired private MyInterceptor myInterceptor; @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(myInterceptor).addPathPatterns("/**"); } }
-
八、如何应用 mybatis
-
引入 mybatis 的启动器(一整套):
-
<dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.1.3</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper-spring-boot-starter</artifactId> <version>1.2.5</version> </dependency>
-
-
映射文件放在 resources 下面。
-
mybatis 的主配置文件 SqlMapConfig.xml,放在 resources 下面。
-
创建 mapper 接口所在的包,放入相关的接口。
-
进行必要的配置:
-
mybatis.config-location=classpath:SqlMapConfig.xml mybatis.mapper-locations=classpath:mappers/*.xml
-
-
为了使用 mapper 代理技术,mapper 接口所在的包必须要被扫描。
-
package com.zhong.microservice; import org.mybatis.spring.annotation.MapperScan; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; /** * @author 华韵流风 * @ClassName SpringBootApplication * @Date 2021/9/12 10:20 * @packageName com.zhong.microservice.controller * @Description TODO */ @SpringBootApplication @MapperScan(basePackages = "com.zhong.microservice.mapper") public class SpringbootApplication { public static void main(String[] args) { SpringApplication.run(SpringbootApplication.class, args); } }
-
-
配置连接池,springboot 推荐使用 hikari 连接池,在配置时只要引入了 jdbc 启动器就可以使用了。
-
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.url=jdbc:mysql://localhost:3306/kangan?serverTimezone=GMT%2B8&characterEncoding=utf-8&useSSL=false spring.datasource.username= spring.datasource.password=
-
-
创建 service,springboot 的项目要求代码越少越好,在 service 层不建议写接口只需要直接创建类。
九、任何使用通用 mapper
-
什么是通用 mapper?
- 通用 mapper 可以极大的方便开发人员进行 ORM,提供极其方便的单表增删改查。一句话简单说, 它就是个辅助 mybatis 极简单表开发的组件。它不是为了替代 mybatis,而是让 mybatis 的开发更方便。
- 可以按照自己的需要选择通用方法,还能很方便的开发自己的通用方法。但是,没有针对多表的操作方法,可是针对互联网的应用要尽量针对单表进行操作。万一需要多表操作或特殊的单表操作时,也可以自定义 sql。它与springboot 是绝配。
-
为什么要用通用 mapper?
- 原生 Mybatis 的痛点
1、mapper.xml文件里有大量的 sql,当数据库表字段变动,配置文件就要修改。
2、需要自己实现sq1分页,select * from table where… limit 1,3。自己手写分页,除了传参 page、pageSize,还需要返回条目总数 count。
3、数据库可移植性差:如果项目更换数据库,比如 oracle–>mysql,mapper.xml 中的 sql 要重新写,因为 oracle 的 PLSQL 和 mysql 支持的函数是不同的。
4、生成的代码量过大。
5、批量操作,批量插入,批量更新,需要自写。
- 原生 Mybatis 的痛点
-
使用通用 mapper。
-
通过 mapper 的启动器;
-
在 springboot 中不需要任何配置;
-
针对单表的操作,接口中不需要自己书写方法,但是要求接口去继承 mapper 接口;
-
接口所在的包仍然需要扫描,但是使用的注解由通用 mapper 来提供;
-
在 service 中使用接口的代理对象时,调用的方法由 tk 提供;
-
针对表的 pojo 类型需要添加相应的注解,例如:
-
package com.zhong.microservice.pojo; import javax.persistence.*; import java.io.Serializable; import java.util.Date; /** * @author 华韵流风 */ @Table(name = "t_member")//指定数据库表名 public class Member implements Serializable{ @Id//指定主键 @GeneratedValue(strategy = GenerationType.IDENTITY)//指定主键自动增长方式 private Integer id;//主键 @Column(name = "fileNumber")//驼峰式的命名,需要数据库的字段名为file_number,如果不是,需要指定 private String fileNumber;//档案号 private String name;//姓名 private String sex;//性别 @Column(name = "idCard") private String idCard;//身份证号 @Column(name = "phoneNumber") private String phoneNumber;//手机号 @Column(name = "regTime") private Date regTime;//注册时间 private String password;//登录密码 private String email;//邮箱 private Date birthday;//出生日期 private String remark;//备注 //…… }
-
-
它提供了几乎所有的针对单表的操作,增删改查都有,比如复杂条件的查询。它本身内部已经执行了逆向工程;
-
自定义 sql,在接口中添加方法,并给方法添加相应的注解,例如。
-
package com.zhong.microservice.mapper; import com.zhong.microservice.pojo.Member; import org.apache.ibatis.annotations.Insert; import org.apache.ibatis.annotations.Param; import tk.mybatis.mapper.common.Mapper; /** * @author 华韵流风 */ public interface MemberDao extends Mapper<Member> { /** * 添加Member * * @param name name */ @Insert("insert into t_member(name) values(#{name})") public void addMember(@Param("name")String name); }
-
-
十、使用 thymeleaf 模板
-
springboot 不支持 jsp,推荐使用 thymeleaf 模板来代替 jsp 的作用。
- spring 对应的是 jar 而不是 war,jsp 根本没有放置的位置;
- jsp 的执行需要 tomcat,而前端不可能使用 tomcat;
- thymeleaf 可以被前端直接使用,哪怕并没有后台传递的数据,并且页面没有任何不同;
- thymeleaf 提供了一些简单的标签,它们可以渲染后台的数据;
- springboot 默认支持 thymeleaf。
-
使用 thymeleaf 需要启动器:
-
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency>
-
-
thymeleaf 模板文件所在的位置:DEFAULT_PREFIX=“classpath:/templates/”;
-
使用模板作为视图时,用法与 jsp 类似;
-
在前后端分离的项目中,springboot 的项目并不会使用 thymeleaf,否则可能会使用。
-
<!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <table> <thead> <tr> <td>id</td> <td>name</td> <td>sex</td> <td>idCard</td> </tr> </thead> <tbody> <tr th:each="member:${members}"> <td th:text="${member.id}"></td> <td th:text="${member.name}"></td> <td th:text="${member.sex}"></td> <td th:text="${member.idCard}"></td> </tr> </tbody> </table> </body> </html>
-
十一、在项目中使用 lombok
-
Lombok 插件用来简化 pojo 的书写,有了它,getter,setter,toString,常用的构造方法等都不用再写了,可以使用相应的注解来进行替换。
-
idea 中必须按照 Lombok 插件。
-
添加 lombok 的依赖:
-
<dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency>
-
-
使用示例:
-
package com.zhong.microservice.pojo; import lombok.*; import javax.persistence.*; import java.io.Serializable; import java.util.Date; /** * @author 华韵流风 */ @Table(name = "t_member") //get方法 @Getter //set方法 @Setter //toString方法 @ToString //无参构造 @NoArgsConstructor //所有参数的构造 @AllArgsConstructor //生成有@NonNull和final修饰的成员变量的构造 @RequiredArgsConstructor //以下注解的集合:@ToString @EqualsAndHashCode @Getter @Setter @RequiredArgsConstructor //@Data public class Member implements Serializable{ @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id;//主键 @Column(name = "fileNumber") private String fileNumber;//档案号 @NonNull private String name;//姓名 private String sex;//性别 @Column(name = "idCard") private String idCard;//身份证号 @Column(name = "phoneNumber") private String phoneNumber;//手机号 @Column(name = "regTime") private Date regTime;//注册时间 private String password;//登录密码 private String email;//邮箱 private Date birthday;//出生日期 private String remark;//备注 }
-