一、SpringBoot介绍
1.1 SpringBoot简介
SpringBoot是由Pivotal团队研发的,SpringBoot并不是一门新技术,只是将之前常用的Spring,SpringMVC,data-jpa等常用的框架封装到了一起,帮助你隐藏这些框架的整合细节,实现敏捷开发。
Spring Boot是基于约定优于配置的,主要作用就是用来简化Spring应用的初始搭建以及开发过程!
后期要学习的微服务框架SpringCloud需要建立在SpringBoot的基础上。
1.2 SpringBoot的特点
1.基于Spring的开发提供更快的入门体验。
2.开箱即用,没有代码生成,也无需XML配置,同时也可以修改默认值来满足特定的需求。
3.提供了一些大型项目中常见的非功能性特性,外部配置等。
4.SpringBoot不是对Spring功能上的增强,而是提供了一种快速使用Spring的方式。
1.3 SpringBoot的核心功能
1.起步依赖
起步依赖本质上是一个Maven项目对象模型(Project Object Model,POM),定义了对其他库的传递依赖,这些东西加在一起即支持某项功能。
简单的说,起步依赖就是将具备某种功能的坐标打包到一起,并提供一些默认的功能。
2.自动配置
Spring Boot的自动配置是一个运行时(更准确地说,是应用程序启动时)的过程,考虑了众多因素,才决定Spring配置应该用哪个,不该用哪个。该过程是Spring自动完成的。
二、SpringBoot快速入门
2.1创建基础项目
网站创建地址:https://start.spring.io/
Spring官方提供了非常方便的工具Spring Initializr来帮助我们创建Spring Boot应用。
2.2使用IntelliJ IDEA创建
如果是使用IntelliJ IDEA来写Java程序的话,那么还可以直接在编译器中创建Spring Boot应用。
第一步:菜单栏中选择:File => New => Project…,我们可以看到如下图所示的创建功能窗口。
其中Initial Service Url指向的地址就是Spring官方提供的Spring Initializr工具地址,所以这里创建的工程实际上也是基于它的Web工具来实现的。
第二步:点击Next,等待片刻后,我们可以看到如下图所示的工程信息窗口:
Type:使用什么构建工具,Maven还是Gradle;本教程将采用大部分Java人员都熟悉的Maven,以方便更多读者入门学习。Language:使用什么编程语言,Java、Kotlin还是Groovy;本教程将采用Java为主编写,以方便更多读者入门学习。
第三步:继续点击Next,进入选择Spring Boot版本和依赖管理的窗口:
Spring Boot:选用的Spring Boot版本;这里将使用当前最新的2.4.1
版本。
在这里值的我们关注的是,它不仅包含了Spring Boot Starter POMs中的各个依赖,还包含了Spring Cloud的各种依赖。
第四步:点击Next,进入最后关于工程物理存储的一些细节。最后,点击Finish就能完成工程的构建了。
项目创建完成!此时pom.xml文件中会自动导入springboot所需依赖,并且在src下会生成一个配置类。注意:若pom.xml中依赖无法下载,需要修改maven工程对应的settings.xml文件,找到settings.xml文件中的镜像配置,原因是maven中央仓库下载不下来springboot关联的架包,所以建议使用阿里云的镜像.<mirrors><!-- mirror| Specifies a repository mirror site to use instead of a given repository. The repository that| this mirror serves has an ID that matches the mirrorOf element of this mirror. IDs are used| for inheritance and direct lookup purposes, and must be unique across the set of mirrors.|--><mirror><id>nexus-aliyun</id><mirrorOf>*</mirrorOf><name>Nexus-aliyun</name><url>/nexus/content/groups/public</url></mirror></mirrors>
2.3项目结构
通过上面步骤完成了基础项目的创建。如上图所示,Spring Boot的基础结构共三个文件(具体路径根据用户生成项目时填写的Group所有差异):
src/main/java
下的程序入口:SpringbootHelloworldApplication
src/main/resources
下的配置文件:application.properties
src/test/
下的测试入口:SpringbootHelloworldApplicationTests
生成的SpringbootHelloworldApplication
和SpringbootHelloworldApplicationTests
类都可以直接运行来启动当前创建的项目,由于目前该项目未配合任何数据访问或Web模块,程序会在加载完Spring之后结束运行。
2.3.1pom.xml
打开pom.xml
,一起来看看Spring Boot项目的依赖:
<?xml version="1.0" encoding="UTF-8"?><project xmlns="/POM/4.0.0" xmlns:xsi="/2001/XMLSchema-instance"xsi:schemaLocation="/POM/4.0.0 /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.4.1</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.cf</groupId><artifactId>springboot-01-helloworld</artifactId><version>0.0.1-SNAPSHOT</version><name>springboot-01-helloworld</name><description>Demo project for Spring Boot</description><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-starter-test</artifactId><scope>test</scope></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin><!--在这里修改版本--><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-resources-plugin</artifactId><version>2.4.3</version></plugin><!----></plugins></build></project>
如上所示,主要有四个部分:
项目元数据:创建时候输入的Project Metadata部分,也就是Maven项目的基本元素,包括:groupId、artifactId、version、name、description等parent:继承spring-boot-starter-parent
的依赖管理,控制版本与打包等内容dependencies:项目具体依赖,这里包含了spring-boot-starter-web
用于实现HTTP接口(该依赖中包含了Spring MVC);spring-boot-starter-test
用于编写单元测试的依赖包。更多功能模块的使用我们将在后面的教程中逐步展开。build:构建配置部分-插件。默认使用了spring-boot-maven-plugin
,配合spring-boot-starter-parent
就可以把Spring Boot应用打包成JAR来直接运行。
2.3.2src目录
-src-main-java-包名启动类.java # 需要将controller类,放在启动类的子包中或同级包下-resources-static # 存放静态资源的-templates # 存储模板页面的application.properties#SpringBoot提供的唯一的配置文件-test#只是为了测试用的
2.4 SpringBoot三种启动方式
2.4.1 运行启动类的main方法
运行main方法即可
2.4.2 maven命令
mvn spring-boot:run
2.4.3采用jar包的方式运行
将当前项目打包成一个jar文件,并通过java -jar jar文件
2.5编写一个HTTP接口
创建package命名为com.cf.helloworld.controller。(根据实际情况修改)创建HelloController
类,内容如下:@RestControllerpublic class HelloController {@RequestMapping("/hello")public String index(){return "hello world";}}
启动主程序,使用PostMan等工具发起请求:http://localhost:8080/hello
,可以看到页面返回:Hello World
三、工程结构典型示例
一般项目的工程结构是有模板的,以下结构是比较推荐的package组织方式:
com+- example+- Application.java|+- entity| +- Customer.java|+- dao| +- CustomerDao.java|+- service| +- CustomerService.java +- impl| +- CustomerServiceImpl.java ||+- controller| +- CustomerController.java|
root package
:com.example
,所有的类和其他package都在root package之下。应用主类:Application.java
,该类直接位于root package
下。通常我们会在应用主类中做一些框架配置扫描等配置,我们放在root package下可以帮助程序减少手工配置来加载到我们希望被Spring加载的内容com.example.entity
包:用于定义实体映射关系com.example.dao
包:用于定义数据访问相关的接口和实现com.example.service
包:用于编写业务逻辑相关的接口com.example.service.impl
包:用于编写业务逻辑相关接口的实现com.example.controller
:用于编写Web层相关的实现,比如:Spring MVC的Controller等
上面的结构中,root package
与应用主类的位置是整个结构的关键。由于应用主类在root package
中,所以按照上面的规则定义的所有其他类都处于root package
下的其他子包之后。默认情况下,Spring Boot的应用主类会自动扫描root package
以及所有子包下的所有类来进行初始化。
加载root package
下的内容。使用@ComponentScan
注解指定具体的加载包,比如:
@SpringBootApplication@ComponentScan(basePackages="com.example")public class Bootstrap {public static void main(String[] args) {SpringApplication.run(Bootstrap.class, args);}}
这种方法通过注解直接指定要扫描的包,比较直观。如果有这样的需求也是可以用的,但是原则上还是推荐以上面的典型结构来定义,这样也可以少写一些注解,代码更加简洁。
四、SpringBoot热部署配置
为了方便开发,可以在创建项目时手动勾选热部署,或导入该依赖,就不需要每次重启配置类
<!--热部署配置--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><optional>true</optional></dependency>
配置自动编译
最后Shift+Ctrl+Alt+/,选择Registry(选完之后再次查看一下是否勾选上)
再次重新运行一次配置类即可!
五、SpringBoot中的配置
5.1常用配置
SpringBoot的配置文件支持properties和yml,甚至他还支持json
更推荐使用yml文件格式:
1、yml文件,会根据换行和缩进帮助咱们管理配置文件所在位置
2、yml文件,相比properties更轻量级一些
yml文件的劣势
1、严格遵循换行和缩进
2、在填写value时,一定要在
:
后面跟上空格
5.1.1多环境配置
在application.yml文件中添加一个配置项:
spring:profiles:active: 环境名
在resource目录下,创建多个applications-环境名.yml文件即可
在部署工程时,通过java -jar jar文件 --spring.profiles.active=环境
在指定为test环境时,
server.port
将使用8882端口;而在prod环境,server.port
将使用8883端口;如果没有指定环境,server.port
将使用8881端口。
server:port: 8881---spring:profiles: active: testserver:port: 8882---spring:profiles: active: prodserver:port: 8883
5.1.2引入外部配置文件信息
和传统的SSM方式一样,通过@value的注解获取properties/yml文件中的内容。
如果在yml文件中需要编写大量的自定义配置,并且具有统一的前缀时,采用如下方式
//java程序@ConfigurationProperties(prefix="aliyun")@Component@Datapublic class AliyunProperties{private String xxxx;private ... ...;}//配置文件aliyun:xxxx: xxxxxx...
5.1.3
5.2默认配置
可以从jar包中找到SpringBoot的默认配置文件位置
SpringBoot是基于约定的,所以很多配置都有默认值,但如果想使用自己的配置替换默认配置的话,就可以使用application.properties或者application.yml(application.yaml)进行配置,SpringBoot默认会从Resources目录下加载application.properties或application.yml(application.yaml)文件。
其中,application.properties文件是键值对类型的文件,除此之外,SpringBoot还可以使用yml文件进行配置,YML文件格式是YAML (YAML Aint Markup Language)编写的文件格式,YAML是一种直观的能够被电脑识别的的数据数据序列化格式,并且容易被人类阅读,容易和脚本语言交互的,可以被支持YAML库的不同的编程语言程序导入,比如: C/C++, Ruby, Python, Java, Perl, C#, PHP等。YML文件是以数据为核心的,比传统的xml方式更加简洁,YML文件的扩展名可以使用.yml或者.yaml。
application.properties方式修改默认配置
application.yml方式修改默认配置:(注意:yml文件中空格表示层级关系)
5.2.1自定义参数
yml文件支持的配置
#普通数据的配置name: jack#对象的配置user:username: rosepassword: 123#配置数组array:beijing,tianjin,shanghai#配置集合yangl:test:name: tomarr: 1,jack,2,tom #这种对象形式的,只能单独写一个对象去接收,所以无法使用@value注解获取list1:- zhangsan- lisilist2:- driver: mysqlport: 3306- driver: oracleport: 1521map:key1: value1key2: value2#端口配置server:port: 8081
把yml文件中配置的内容注入到成员变量中,
第一种方式,创建UserController,使用@Value注解方式注入
import org.springframework.beans.factory.annotation.Value;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;import java.util.ArrayList;import java.util.List;@RestControllerpublic class UserController {@Value("${name}")private String name;@Value("${user.username}")private String username;@Value("${user.password}")private String password;@Value("${array}")private String [] array;@RequestMapping("/test")public String[] test(){System.out.println(name);System.out.println(username);System.out.println(password);System.out.println(array[0]);return array;}}
@Value
注解加载属性值的时候可以支持两种表达式来进行配置:
一种是我们上面介绍的PlaceHolder方式,格式为${...}
,大括号内为PlaceHolder另外还可以使用SpEL表达式(Spring Expression Language), 格式为#{...}
,大括号内为SpEL表达式
5.2.1.1参数引用
在application.properties
中的各个参数之间,我们也可以直接通过使用PlaceHolder的方式来进行引用,就像下面的设置:
book.name=SpringCloudbook.author=ZhaiYongchaobook.desc=${book.author} is writing《${book.name}》
book.desc
参数引用了上文中定义的book.name
和book.author
属性,最后该属性的值就是ZhaiYongchao is writing《SpringCloud》
第二种方式,使用@ConfigurationProperties注解方式,提供GET/SET方法
创建YmlController
import org.springframework.boot.context.properties.ConfigurationProperties;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;import java.util.Arrays;import java.util.List;import java.util.Map;@Data@RestController@ConfigurationProperties(prefix = "yangl.test")public class YmlController {private String name;private String[] arr;private List<String> list1;private List<Map<String,String>> list2;private Map<String,String> map;@RequestMapping("/yml")public void yml(){System.out.println(name);System.out.println(Arrays.toString(arr));System.out.println(list1);System.out.println(list2);System.out.println(map);}}
如果使用@ConfigurationProperties注解时提示以下信息\
导入以下依赖即可(也可以不导入)
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-configuration-processor</artifactId><optional>true</optional></dependency>
5.2.2使用随机数
在一些特殊情况下,有些参数我们希望它每次加载的时候不是一个固定的值,比如:密钥、服务端口等。在Spring Boot的属性配置文件中,我们可以通过使用${random}
配置来产生随机的int值、long值或者string字符串,这样我们就可以容易的通过配置来属性的随机生成,而不是在程序中通过编码来实现这些逻辑。
${random}
的配置方式主要有一下几种,读者可作为参考使用。
# 随机字符串com.didispace.blog.value=${random.value}# 随机intcom.didispace.blog.number=${random.int}# 随机longcom.didispace.blog.bignumber=${random.long}# 10以内的随机数com.didispace.blog.test1=${random.int(10)}# 10-20的随机数com.didispace.blog.test2=${random.int[10,20]}
该配置方式可以用于设置应用端口等场景,避免在本地调试时出现端口冲突的麻烦
5.3配置文件绑定
5.3.1简单类型
在Spring Boot 2.0中对配置属性加载的时候会除了像1.x版本时候那样移除特殊字符外,还会将配置均以全小写的方式进行匹配和加载。所以,下面的4种配置方式都是等价的:
properties格式:
spring.jpa.databaseplatform=mysqlspring.jpa.database-platform=mysqlspring.jpa.databasePlatform=mysqlspring.JPA.database_platform=mysql
yaml格式:
spring:jpa:databaseplatform: mysqldatabase-platform: mysqldatabasePlatform: mysqldatabase_platform: mysql
Tips:推荐使用全小写配合-
分隔符的方式来配置,比如:spring.jpa.database-platform=mysql
5.3.2List类型
在properties文件中使用[]
来定位列表类型,比如:
spring.my-example.url[0]=spring.my-example.url[1]=http://spring.io
也支持使用逗号分割的配置方式,上面与下面的配置是等价的:
spring.my-example.url=,http://spring.io
而在yaml文件中使用可以使用如下配置:
spring:my-example:url:- - http://spring.io
也支持逗号分割的方式:
spring:my-example:url: , http://spring.io
注意:在Spring Boot 2.0中对于List类型的配置必须是连续的,不然会抛出UnboundConfigurationPropertiesException
异常,所以如下配置是不允许的:
foo[0]=afoo[2]=b
在Spring Boot 1.x中上述配置是可以的,foo[1]
由于没有配置,它的值会是null
5.3.3Map类型
Map类型在properties和yaml中的标准配置方式如下:
properties格式:
spring.my-example.foo=barspring.my-example.hello=world
yaml格式:
spring:my-example:foo: barhello: world
注意:如果Map类型的key包含非字母数字和-
的字符,需要用[]
括起来,比如:
spring:my-example:'[foo.baz]': bar
5.4环境属性绑定
简单类型
在环境变量中通过小写转换与.
替换_
来映射配置文件中的内容,比如:环境变量SPRING_JPA_DATABASEPLATFORM=mysql
的配置会产生与在配置文件中设置spring.jpa.databaseplatform=mysql
一样的效果。
List类型
由于环境变量中无法使用[
和]
符号,所以使用_
来替代。任何由下划线包围的数字都会被认为是[]
的数组形式。比如:
MY_FOO_1_ = my.foo[1]MY_FOO_1_BAR = my.foo[1].barMY_FOO_1_2_ = my.foo[1][2]
另外,最后环境变量最后是以数字和下划线结尾的话,最后的下划线可以省略,比如上面例子中的第一条和第三条等价于下面的配置:
MY_FOO_1 = my.foo[1]MY_FOO_1_2 = my.foo[1][2]
5.5系统属性绑定
简单类型
系统属性与文件配置中的类似,都以移除特殊字符并转化小写后实现绑定,比如下面的命令行参数都会实现配置spring.jpa.databaseplatform=mysql
的效果:
-Dspring.jpa.database-platform=mysql-Dspring.jpa.databasePlatform=mysql-Dspring.JPA.database_platform=mysql
List类型
系统属性的绑定也与文件属性的绑定类似,通过[]
来标示,比如:
-D"spring.my-example.url[0]="-D"spring.my-example.url[1]=http://spring.io"
同样的,他也支持逗号分割的方式,比如:
-Dspring.my-example.url=,http://spring.io
5.6属性的读取
上文介绍了Spring Boot 2.0中对属性绑定的内容,可以看到对于一个属性我们可以有多种不同的表达,但是如果我们要在Spring应用程序的environment中读取属性的时候,每个属性的唯一名称符合如下规则:
通过.
分离各个元素最后一个.
将前缀与属性名称分开必须是字母(a-z)和数字(0-9)必须是小写字母用连字符-
来分隔单词唯一允许的其他字符是[
和]
,用于List的索引不能以数字开头
所以,如果我们要读取配置文件中spring.jpa.database-platform
的配置,可以这样写:
this.environment.containsProperty("spring.jpa.database-platform")
而下面的方式是无法获取到spring.jpa.database-platform
配置内容的:
this.environment.containsProperty("spring.jpa.databasePlatform")
注意:使用@Value
获取配置内容的时候也需要这样的特点
5.7全新的绑定API
在Spring Boot 2.0中增加了新的绑定API来帮助我们更容易的获取配置信息。下面举个例子来帮助大家更容易的理解:
例子一:简单类型
假设在propertes配置中有这样一个配置:com.didispace.foo=bar
我们为它创建对应的配置类:
@Data@ConfigurationProperties(prefix = "com.didispace")public class FooProperties {private String foo;}
接下来,通过最新的Binder
就可以这样来拿配置信息了:
@SpringBootApplicationpublic class Application {public static void main(String[] args) {ApplicationContext context = SpringApplication.run(Application.class, args);Binder binder = Binder.get(context.getEnvironment());// 绑定简单配置FooProperties foo = binder.bind("com.didispace", Bindable.of(FooProperties.class)).get();System.out.println(foo.getFoo());}}
例子二:List类型
如果配置内容是List类型呢?比如:
com.didispace.post[0]=Why Spring Bootcom.didispace.post[1]=Why Spring Cloudcom.didispace.posts[0].title=Why Spring Bootcom.didispace.posts[0].content=It is perfect!com.didispace.posts[1].title=Why Spring Cloudcom.didispace.posts[1].content=It is perfect too!
要获取这些配置依然很简单,可以这样实现:
ApplicationContext context = SpringApplication.run(Application.class, args);Binder binder = Binder.get(context.getEnvironment());// 绑定List配置List<String> post = binder.bind("com.didispace.post", Bindable.listOf(String.class)).get();System.out.println(post);List<PostInfo> posts = binder.bind("com.didispace.posts", Bindable.listOf(PostInfo.class)).get();System.out.println(posts);
六、SpringBoot中的异常处理
6.1 创建ExceptionController测试类
import com.qf.exception.MyException;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;@RestControllerpublic class ExceptionController {@RequestMapping("/exception")public String exception(){int i = 1/0;return "exception";}@RequestMapping("/myexception")public String myexception()throws MyException{throw new MyException("自定义异常");}}
6.2 创建自定义异常类
public class MyException extends Exception{public MyException(String msg){super(msg);}}
6.3 创建MyExceptionHandler全局异常处理类
import org.springframework.web.bind.annotation.ExceptionHandler;import org.springframework.web.bind.annotation.RestControllerAdvice;import javax.servlet.http.HttpServletRequest;import java.util.HashMap;//拦截异常@RestControllerAdvicepublic class MyExceptionHandler {//处理指定异常@ExceptionHandler(value = Exception.class)public Object Handler1(Exception e, HttpServletRequest request){System.out.println("Handler1");HashMap<String, Object> map = new HashMap<>();map.put("msg",e.getMessage());map.put("url",request.getRequestURL());return map;}@ExceptionHandler(value = MyException.class)public Object Handler2(MyException e, HttpServletRequest request){System.out.println("Handler2");HashMap<String, Object> map = new HashMap<>();map.put("msg",e.getMessage());map.put("url",request.getRequestURL());return map;}}
访问:http://localhost:8080/exception 以及 http://localhost:8080/myexception测试
七、SpringBoot中的过滤器(Listener操作同理)
7.1 创建过滤器
import javax.servlet.*;import javax.servlet.annotation.WebFilter;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.io.IOException;@WebFilter(urlPatterns = "/filter/*")//指定拦截路径public class LoginFilter implements Filter {@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {System.out.println("LoginFilter ");HttpServletRequest req = (HttpServletRequest)request;HttpServletResponse resp = (HttpServletResponse)response;chain.doFilter(req,resp);}}
7.2 创建Controller测试类
import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;@RestController@RequestMapping("/filter")public class FilterController {@RequestMapping("/login")public String login() {System.out.println("登录");return "login";}}
7.3 在启动类添加@ServletComponentScan注解
import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.boot.web.servlet.ServletComponentScan;@SpringBootApplication@ServletComponentScan//Servlet、Filter、Listener可以直接通过@WebServlet、@WebFilter、@WebListener注解自动注册public class Springboot02Application {public static void main(String[] args) {SpringApplication.run(Springboot02Application.class, args);}}
访问controller测试即可
八、SpringBoot中的拦截器
8.1.创建自定义拦截器
import org.omg.PortableInterceptor.Interceptor;import org.springframework.web.servlet.HandlerInterceptor;import org.springframework.web.servlet.ModelAndView;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;public class MyInterceptor implements HandlerInterceptor {//进入controller方法之前调用@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {System.out.println("preHandle");return true;//true表示放行,false表示不放行}//调用完controller之后,视图渲染之前@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {System.out.println("postHandle");}//页面跳转之后,整个流程执行之后,一般用于资源清理操作@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {System.out.println("afterCompletion");}}
8.2创建拦截器配置类
import org.springframework.context.annotation.Configuration;import org.springframework.web.servlet.config.annotation.InterceptorRegistry;import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;@Configurationpublic class MyInterceptorConfig implements WebMvcConfigurer {@Overridepublic void addInterceptors(InterceptorRegistry registry) {//设置拦截器并指定拦截路径registry.addInterceptor(new MyInterceptor()).addPathPatterns("/interceptor/*");//registry.addInterceptor(new MyInterceptor()).addPathPatterns("/**");//拦截所有//registry.addInterceptor(new MyInterceptor()).addPathPatterns("/**").excludePathPatterns("/test");//指定不拦截//添加自定义拦截器WebMvcConfigurer.super.addInterceptors(registry);}}
8.3在static目录下创建index.html以及controller测试类
import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;@Controllerpublic class InterceptorController {@RequestMapping("/interceptor/myinterceptor")public String myinterceptor(){System.out.println("myinterceptor");return "/index.html";}}
访问controller测试即可
九、SpringBoot整合MyBatis
9.0 xml整合Mybatis
xml方式在编写复杂SQL时,更合适
9.1导入依赖
<!-- 引入mybatis相关依赖,必须写版本号 --><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.1.1</version></dependency><!-- 引入mysql相关依赖,如果不写版本号,引入的8.0以上版本可以设置为其他版本--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency>
9.2在application.properties中配置数据库信息
# 数据库配置# 默认使用mysql的驱动是8.x的版本,注意driver-class-name,url中增加时区的配置spring.datasource.url=jdbc:mysql://localhost:3306/java1909?serverTimezone=Asia/Shanghaispring.datasource.username=rootspring.datasource.password=rootspring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
9.3使用之前的Account表,创建实体类
@Datapublic class Account implements Serializable{private Integer id;private String name;private Double money;@Overridepublic String toString() {return "Account{" +"id=" + id +", name='" + name + '\'' +", money=" + money +'}';}}
9.4创建mapper
import com.qf.pojo.Account;import org.springframework.stereotype.Repository;import java.util.List;@Repositorypublic interface AccountMapper {public List<Account> findAll();}
9.5在src\main\resources\mapper路径下创建对应的AccountMapper.xml文件
<?xml version="1.0" encoding="utf-8" ?><!DOCTYPE mapper PUBLIC "-////DTD Mapper 3.0//EN""/dtd/mybatis-3-mapper.dtd" ><mapper namespace="com.qf.mapper.AccountMapper"><select id="findAll" resultType="com.qf.pojo.Account">select * from account</select></mapper>
9.6在application.properties中添加mybatis的信息
# mybatis配置# 配置别名需要扫描的包mybatis.type-aliases-package=com.qf.pojo# 引入映射文件mybatis.mapper-locations=classpath:mapper/*.xml# 配置日志在控制台显示sql语句mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
9.7创建service
import com.qf.pojo.Account;import java.util.List;public interface AccountService {public List<Account> findAll();}
9.8创建serviceImpl
import com.qf.mapper.AccountMapper;import com.qf.pojo.Account;import com.qf.service.AccountService;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import java.util.List;@Servicepublic class AccountServiceImpl implements AccountService {@Autowiredprivate AccountMapper accountMapper;@Overridepublic List<Account> findAll() {return accountMapper.findAll();}}
9.9创建controller
import com.qf.pojo.Account;import com.qf.service.AccountService;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;import java.util.List;@RestController@RequestMapping("/account")public class AccountController {@Autowiredprivate AccountService accountService;@RequestMapping("/findAll")public List<Account> findAll(){List<Account> accounts = accountService.findAll();return accounts;}}
9.10启动配置类,进行测试(注意:需要在启动类上添加@MapperScan扫描Mapper)
import org.mybatis.spring.annotation.MapperScan;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication@MapperScan("com.qf.mapper")public class Springboot02Application {public static void main(String[] args) {SpringApplication.run(Springboot02Application.class, args);}}
9.11分页插件
9.11.1导入依赖
<!-- pagehelper--><dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper-spring-boot-starter</artifactId><version>1.2.13</version></dependency>
9.11.2添加方法
@RequestMapping("/findByPage")public PageInfo findByPage(@RequestParam(defaultValue = "1") Integer pageNum,@RequestParam(defaultValue = "2") Integer pageSize){PageHelper.startPage(pageNum,pageSize);List<Account> accounts = accountService.findAll();PageInfo pageInfo = new PageInfo(accounts);return pageInfo;}
启动工程,进行测试
十、使用Druid连接池进行测试
10.1导入依赖
<dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>1.1.10</version></dependency>
10.2在application.properties文件中添加配置
#使用阿里巴巴druid数据源,默认使用自带的spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
10.3使用yml方式配置,需要创建application.yml
mybatis:# 配置别名扫描的包type-aliases-package: com.qf.pojo# 扫描映射文件mapper-locations: classpath: mapper/*.xmlconfiguration:# 开启驼峰映射配置log-impl: org.apache.ibatis.logging.stdout.StdOutImpl# 连接数据库的信息spring:datasource:type: com.alibaba.druid.pool.DruidDataSourceurl: jdbc:mysql://localhost:3306/java2001?serverTimezone=Asia/Shanghaiusername: rootpassword: rootdriver-class-name: com.mysql.cj.jdbc.Driver
启动工程,进行测试
10.4测试
import org.junit.Test;import org.junit.runner.RunWith;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.test.context.SpringBootTest;import org.springframework.test.context.junit4.SpringRunner;import com.qf.mapper.AccountMapper;import com.qf.pojo.Account;import java.util.List;@RunWith(SpringRunner.class)@SpringBootTestpublic class ShiuwuApplicationTests {@Autowiredprivate AccountMapper accountMapper;@Overridepublic List<Account> findAll() {return accountMapper.findAll();}}
十一、SpringBoot整合FreeMarker
11.1导入依赖
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-freemarker</artifactId></dependency>
11.2在application.properties文件添加配置
########## 配置freemarker ###########是否开启缓存spring.freemarker.cache=false#路径spring.freemarker.template-loader-path=classpath:/templates#文件后缀spring.freemarker.suffix=.ftlspring.freemarker.charset=UTF-8spring.freemarker.content-type=text/html
11.3创建实体类
@Data@NoArgsConstructor@AllArgsConstructorpublic class Student {private Integer id;private String name;private Integer age;private String address;}
11.4在templates目录下创建student.ftl文件(然后把该ftl文件拷贝到D:/ftl目录下,一会用)
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>Title</title></head><body><table border="1" width=600><tr><th>index</th><th>id</th><th>name</th><th>age</th><th>address</th></tr><#list students as student><#if student_index % 2 == 0><tr bgcolor="red"><#else><tr bgcolor="yellow"></#if><td>${student_index}</td><td>${student.id}</td><td>${student.name}</td><td>${student.age}</td><td>${student.address}</td></tr></#list></table></body></html>
11.5创建controller
import freemarker.template.Configuration;import freemarker.template.Template;import org.springframework.stereotype.Controller;import org.springframework.ui.Model;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.ResponseBody;import javax.servlet.http.HttpServletRequest;import java.io.File;import java.io.FileWriter;import java.util.ArrayList;import java.util.HashMap;@Controller@RequestMapping("/freemarker")public class FreeMarkerController {@RequestMapping("/student")public String hello(Model model) throws Exception {//创建List集合获取多个元素ArrayList<Student> students = new ArrayList<>();students.add(new Student(1, "jack", 18, "郑州二七"));students.add(new Student(2, "rose", 19, "郑州中原"));students.add(new Student(3, "tom", 20, "郑州金水"));model.addAttribute("students",students);return "/student";}//生成静态页面的方法@RequestMapping("createHtml")@ResponseBodypublic String createHtml()throws Exception{//获取配置对象Configuration configuration = new Configuration(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS);//设置字符集configuration.setDefaultEncoding("utf-8");//设置加载的模版目录configuration.setDirectoryForTemplateLoading(new File("D:/ftl"));//创建List集合获取多个元素ArrayList<Student> students = new ArrayList<>();students.add(new Student(1,"张三",18,"北京"));students.add(new Student(2,"李四",19,"上海"));students.add(new Student(3,"王五",20,"广州"));//使用map集合加载数据HashMap<String,ArrayList> map = new HashMap<>();map.put("students",students);//创建输出流对象FileWriter fileWriter = new FileWriter(newFile("D:/ftl_html/student.html"));//获取加载的模板Template template = configuration.getTemplate("student.ftl");//生成html文件template.process(map,fileWriter);//关流fileWriter.close();return "success";}}
启动工程,进行测试
十二、SpringBoot整合Thymeleaf
Thymeleaf、 freemarker用于网页静态化,Thymeleaf 是Java服务端的模板引擎,与传统的JSP不同,Thymeleaf 可以使用浏览器直接打开,相当于打开html原生页面。
12.1导入依赖
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId></dependency>
12.2在application.properties文件添加配置
########## 配置thymeleaf ##########spring.thymeleaf.cache=falsespring.thymeleaf.encoding=utf-8spring.thymeleaf.prefix=classpath:/templatesspring.thymeleaf.suffix=.htmlspring.thymeleaf.mode=HTML5spring.thymeleaf.servlet.content-type=text/html
12.3创建实体类
import java.util.Date;@Data@NoArgsConstructor@AllArgsConstructorpublic class User {private Integer id;private String username;private String password;private Date birthday;@Overridepublic String toString() {return "User{" +"id=" + id +", username='" + username + '\'' +", password='" + password + '\'' +", birthday=" + birthday +'}';}}
12.4创建Controller
import com.qf.pojo.User;import org.springframework.stereotype.Controller;import org.springframework.ui.Model;import org.springframework.web.bind.annotation.RequestMapping;import java.util.ArrayList;import java.util.Date;@Controller@RequestMapping("user")public class UserController {@RequestMapping("findAll")public String findAll(Model model) {ArrayList<User> users = new ArrayList<>();users.add(new User(1001, "张三", "123", new Date()));users.add(new User(1002, "李四", "456", new Date()));users.add(new User(1003, "王五", "789", new Date()));model.addAttribute("users", users);return "/list";}@RequestMapping("findById")public String findById(Model model, String uid) {System.out.println(uid);if (uid.equals("1001")) {User user = new User(1001, "张三", "123", new Date());model.addAttribute("user", user);}return "/queryOne";}}
12.5在templates目录下创建list.html以及queryOne.html
list.html
<!DOCTYPE html><html lang="en" xmlns:th="/1999/xhtml"><head><meta charset="UTF-8"><title>Title</title></head><body><div th:if="${users!=null}"><table border="1" width="600"><tr th:each="user,state : ${users}"><td th:text="${state.count}"></td><td th:text="${user.id}"></td><td th:text="${user.username}"></td><td th:text="${#dates.format(user.birthday, 'yyyy-MM-dd HH:mm:ss')}"></td></tr></table><hr><table border="1" width="600"><!-- 第二个变量,可以获取遍历的元素的状态--><tr th:each="user,state : ${users}"><td th:text="${state.index}"></td><td th:text="${user.id}"></td><td th:text="${user.username}"></td><td th:text="${#dates.format(user.birthday, 'yyyy-MM-dd HH:mm:ss')}"></td></tr></table><hr><table border="1" width="600"><!--如果不设置表示状态的变量,默认遍历的元素的变量名+Stat表示状态的变量--><tr th:each="user : ${users}"><td th:text="${userStat.count}"></td><td th:text="${user.id}"></td><td th:text="${user.username}"></td><td th:text="${#dates.format(user.birthday, 'yyyy-MM-dd HH:mm:ss')}"></td></tr></table></div><hr color="red"><table border="1" width="600"><tr><th>序号</th><th>姓名</th><th>生日</th><th>详情</th></tr><tr th:each="user : ${users}"><td th:text="${userStat.count}"></td><td th:text="${user.username}"></td><td th:text="${#dates.format(user.birthday, 'yyyy-MM-dd HH:mm:ss')}"></td><td><a th:href="@{/user/findById(uid=${user.id})}">查询</a></td></tr></table></body></html>
queryOne.html
<!DOCTYPE html><html lang="en" xmlns:th="/1999/xhtml"><head><meta charset="UTF-8"><title>Title</title></head><body><form th:object="${user}"><!-- *{...}选择表达式一般跟在th:object后,直接选择object中的属性--><input type="hidden" th:id="*{id}" name="id">用户名:<input type="text" th:value="*{username}" name="username" /><br /><br />密码:<input type="text" th:value="*{password}" name="password"/></form></body></html>
十三、SpringBoot整合Redis
13.1导入依赖
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency>
13.2在application.properties文件添加配置
#配置redis数据库索引(默认0号库)spring.redis.database=0#配置redis服务器ip地址spring.redis.host=192.168.228.135#配置redis服务器的端口号spring.redis.port=6379
13.3创建controller
import org.springframework.beans.factory.annotation.Autowired;import org.springframework.data.redis.core.RedisTemplate;import org.springframework.data.redis.core.StringRedisTemplate;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;@RestController@RequestMapping("/redis")public class RedisController {@Autowiredprivate RedisTemplate redisTemplate ;@Autowiredprivate StringRedisTemplate stringRedisTemplate;@RequestMapping("/testString")public String test(){//redisTemplate.opsForValue();//操作字符串//redisTemplate.opsForList();//操作List//redisTemplate.opsForSet();//操作Set//redisTemplate.opsForZSet();//操作ZSet//redisTemplate.opsForHash();//操作MapredisTemplate.opsForValue().set("username","jack");String username = (String)redisTemplate.opsForValue().get("username");System.out.println(username);stringRedisTemplate.opsForValue().set("password","123");String password = stringRedisTemplate.opsForValue().get("password");System.out.println(password);return "success";}}
启动工程,进行测试
十四、SpringBoot整合Quartz
14.1导入依赖
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-quartz</artifactId></dependency>
14.2创建任务类
import org.springframework.scheduling.annotation.Scheduled;import org.ponent;import java.util.Date;@Componentpublic class MyQuartz {@Scheduled(cron="*/2 * * * * ? ")public void testQuartz(){System.out.println("testQuartz:"+new Date().toLocaleString());}}
14.3在启动类添加@EnableScheduling配置,然后直接启动测试
import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.scheduling.annotation.EnableScheduling;@SpringBootApplication@EnableSchedulingpublic class Springboot02Application {public static void main(String[] args) {SpringApplication.run(Springboot02Application.class, args);}}
十五、SpringBoot日志
SpringBoot默认使用的日志是Logback,官方建议日志文件命名为:logback-spring.xml
15.1在resources目录下创建logback-spring.xml
<?xml version="1.0" encoding="UTF-8"?><!-- scan:当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true --><!-- scanPeriod:设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当scan为true时,此属性生效。默认的时间间隔为1分钟。 --><!-- debug:当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。 --><configuration scan="true" scanPeriod="60 seconds" debug="true"><!-- 定义变量,可通过 ${log.path}和${CONSOLE_LOG_PATTERN} 得到变量值 --><property name="log.path" value="D:/log" /><property name="CONSOLE_LOG_PATTERN"value="%d{yyyy-MM-dd HH:mm:ss.SSS} |-[%-5p] in %logger.%M[line-%L] -%m%n"/><!-- 输出到控制台 --><appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"><!-- Threshold=即最低日志级别,此appender输出大于等于对应级别的日志(当然还要满足root中定义的最低级别)--><filter class="ch.qos.logback.classic.filter.ThresholdFilter"><level>debug</level></filter><encoder><!-- 日志格式(引用变量) --><Pattern>${CONSOLE_LOG_PATTERN}</Pattern><!-- 设置字符集 --><charset>UTF-8</charset></encoder></appender><!-- 追加到文件中 --><appender name="file1" class="ch.qos.logback.core.FileAppender"><file>${log.path}/mylog1.log</file><encoder><pattern>${CONSOLE_LOG_PATTERN}</pattern></encoder></appender><!-- 滚动追加到文件中 --><appender name="file2" class="ch.qos.logback.core.rolling.RollingFileAppender"><!-- 正在记录的日志文件的路径及文件名 --><file>${log.path}/mylog2.log</file><!--日志文件输出格式--><encoder><pattern>${CONSOLE_LOG_PATTERN}</pattern><charset>UTF-8</charset> <!-- 设置字符集 --></encoder><!-- 日志记录器的滚动策略,按日期,按大小记录文件超过最大尺寸后,会新建文件,然后新的日志文件中继续写入如果日期变更,也会新建文件,然后在新的日志文件中写入当天日志--><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><!-- 新建文件后,原日志改名为如下 %i=文件序号,从0开始 --><fileNamePattern>${log.path}/newlog-%d{yyyy-MM-dd}.%i.log</fileNamePattern><!-- 每个日志文件的最大体量 --><timeBasedFileNamingAndTriggeringPolicyclass="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"><maxFileSize>1kb</maxFileSize></timeBasedFileNamingAndTriggeringPolicy><!-- 日志文件保留天数,1=则只保留昨天的归档日志文件 ,不设置则保留所有日志--><maxHistory>1</maxHistory></rollingPolicy></appender><root level="INFO"><appender-ref ref="CONSOLE"/><appender-ref ref="file1"/><appender-ref ref="file2"/></root></configuration>
启动工程,进行测试
十六、SpringBoot整合EasyExcel
EasyExcel官网:https://alibaba-easyexcel.github.io/index.html
16.1导入依赖
<dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>2.2.3</version></dependency>
16.2写入操作
16.2.1创建pojo
import com.alibaba.excel.annotation.ExcelIgnore;import com.alibaba.excel.annotation.ExcelProperty;import lombok.Data;import java.util.Date;@Datapublic class DemoData {@ExcelProperty("字符串标题")private String string;@ExcelProperty("日期标题")private Date date;@ExcelProperty("数字标题")private Double doubleData;/*** 忽略这个字段*/@ExcelIgnoreprivate String ignore;}
16.2.2创建测试类
import com.alibaba.excel.EasyExcel;import com.qf.pojo.DemoData;import org.junit.Test;import java.util.ArrayList;import java.util.Date;import java.util.List;public class TestEasyExcel {private List<DemoData> data() {List<DemoData> list = new ArrayList<DemoData>();for (int i = 0; i < 10; i++) {DemoData data = new DemoData();data.setString("字符串" + i);data.setDate(new Date());data.setDoubleData(0.56);list.add(data);}return list;}@Testpublic void simpleWrite() {// 写法1String fileName = "D:/TestEasyExcel.xlsx";// 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭EasyExcel.write(fileName, DemoData.class).sheet("模板").doWrite(data());}}
运行测试类即可
16.3读取操作
16.3.1创建监听器
import com.alibaba.excel.context.AnalysisContext;import com.alibaba.excel.event.AnalysisEventListener;import com.alibaba.fastjson.JSON;import com.qf.pojo.DemoData;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import java.util.ArrayList;import java.util.List;// 有个很重要的点 DemoDataListener 不能被spring管理,要每次读取excel都要new,然后里面用到spring可以构造方法传进去public class DemoDataListener extends AnalysisEventListener<DemoData> {private static final Logger LOGGER = LoggerFactory.getLogger(DemoDataListener.class);/*** 每隔5条存储数据库,实际使用中可以3000条,然后清理list ,方便内存回收*/private static final int BATCH_COUNT = 5;List<DemoData> list = new ArrayList<DemoData>();/*** 假设这个是一个DAO,当然有业务逻辑这个也可以是一个service。当然如果不用存储这个对象没用。*/private DemoDAO demoDAO;public DemoDataListener() {// 这里是demo,所以随便new一个。实际使用如果到了spring,请使用下面的有参构造函数demoDAO = new DemoDAO();}/*** 如果使用了spring,请使用这个构造方法。每次创建Listener的时候需要把spring管理的类传进来** @param demoDAO*/public DemoDataListener(DemoDAO demoDAO) {this.demoDAO = demoDAO;}/*** 这个每一条数据解析都会来调用** @param data* one row value. Is is same as {@link AnalysisContext#readRowHolder()}* @param context*/@Overridepublic void invoke(DemoData data, AnalysisContext context) {LOGGER.info("解析到一条数据:{}", JSON.toJSONString(data));list.add(data);// 达到BATCH_COUNT了,需要去存储一次数据库,防止数据几万条数据在内存,容易OOMif (list.size() >= BATCH_COUNT) {saveData();// 存储完成清理 listlist.clear();}}/*** 所有数据解析完成了 都会来调用** @param context*/@Overridepublic void doAfterAllAnalysed(AnalysisContext context) {// 这里也要保存数据,确保最后遗留的数据也存储到数据库saveData();LOGGER.info("所有数据解析完成!");}/*** 加上存储数据库*/private void saveData() {LOGGER.info("{}条数据,开始存储数据库!", list.size());demoDAO.save(list);LOGGER.info("存储数据库成功!");}}
16.3.2创建Dao
import com.qf.pojo.DemoData;import java.util.List;/*** 假设这个是你的DAO存储。当然还要这个类让spring管理,当然你不用需要存储,也不需要这个类。**/public class DemoDAO {public void save(List<DemoData> list) {// 如果是mybatis,尽量别直接调用多次insert,自己写一个mapper里面新增一个方法batchInsert,所有数据一次性插入}}
16.3.3创建测试类
@Testpublic void simpleRead() {// 有个很重要的点 DemoDataListener 不能被spring管理,要每次读取excel都要new,然后里面用到spring可以构造方法传进去// 写法1:String fileName = "D:/TestEasyExcel.xlsx";// 这里 需要指定读用哪个class去读,然后读取第一个sheet 文件流会自动关闭EasyExcel.read(fileName, DemoData.class, new DemoDataListener()).sheet().doRead();}
十七、SpringBoot整合Swagger
17.1swagger介绍
现在开发,很多采用前后端分离的模式,前端只负责调用接口,进行渲染,前端和后端的唯一联系,变成了API接口。因此,API文档变得越来越重要。swagger是一个方便我们更好的编写API文档的框架,而且swagger可以模拟http请求调用。
大部分采取的方式:Vue + SpringBoot,Vue通过js渲染页面,后端把数据传递给js,早期前端只负责写页面,然后把写好的HTML页面给后端,后端使用模板引擎(Jsp,Thymeleaf、 freemarker)进行开发。
前后端分离的好处:各自开发,相对独立,松耦合,前后端通过API进行交互,后端提供接口给前端,前端去调用该接口,但可能会导致前后端团队人员不能做到及时协商,出现一些问题。解决方式:早期使用实时更新文档,但非常繁琐,后来又使用postman来进行一些测试。
swagger是目前最流行的Api框架,官网:https://swagger.io/
17.2导入依赖
<dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger-ui</artifactId><version>2.9.2</version></dependency><dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger2</artifactId><version>2.9.2</version></dependency>
17.3创建配置类
@Configuration@EnableSwagger2//开启Swagger2public class SwaggerConfig {}
然后启动测试运行,访问:http://localhost:8080/swagger-ui.html,看到如下页面:
17.4手动配置实例,修改SwaggerConfig配置类
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.spi.DocumentationType;import springfox.documentation.spring.web.plugins.Docket;import springfox.documentation.swagger2.annotations.EnableSwagger2;@Configuration@EnableSwagger2//开启Swagger2public class SwaggerConfig {//配置Swagger的Bean实例@Beanpublic Docket createDocket() {return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo());}//配置API的基本信息(会在http://项目实际地址/swagger-ui.html页面显示)private ApiInfo apiInfo() {return new ApiInfoBuilder().title("测试API文档标题").description("测试api接口文档描述").termsOfServiceUrl("").version("1.0").build();}}
再次启动测试运行,访问:http://localhost:8080/swagger-ui.html,看到如下页面:
17.5创建实体类
import io.swagger.annotations.ApiModel;import io.swagger.annotations.ApiModelProperty;@ApiModel("用户")@Data@NoArgsConstructor@AllArgsConstructorpublic class User {@ApiModelProperty("编号")private String uid;@ApiModelProperty("用户名")private String username;@ApiModelProperty("密码")private String password;}
17.6创建controller
import com.qf.entity.User;import io.swagger.annotations.Api;import io.swagger.annotations.ApiOperation;import io.swagger.annotations.ApiParam;import org.springframework.web.bind.annotation.*;import java.util.ArrayList;import java.util.List;//@Api(description = "用户接口")@Api(tags = "用户接口")@RestController@RequestMapping("/user")public class UserController {@ApiOperation("查询单个用户")@RequestMapping("/findById")public User findById(@RequestParam @ApiParam("用户ID") String uid){User user = new User();user.setUid(uid);user.setUsername("张三");user.setPassword("123");return user;}@ApiOperation("删除单个用户")@PostMapping("/delete")public User delete(String uid){User user = new User();user.setUid(uid);user.setUsername("李四");user.setPassword("456");return user;}@ApiOperation("查询所有用户")@GetMapping("/findAll")public List<User> findAll(){User user1 = new User();user1.setUid("1001");user1.setUsername("张三");user1.setPassword("123");User user2 = new User();user2.setUid("1002");user2.setUsername("李四");user2.setPassword("456");ArrayList<User> users = new ArrayList<>();users.add(user1);users.add(user2);return users;}}
17.7修改SwaggerConfig配置类
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.spi.DocumentationType;import springfox.documentation.spring.web.plugins.Docket;import springfox.documentation.swagger2.annotations.EnableSwagger2;@Configuration@EnableSwagger2//开启Swagger2public class SwaggerConfig {//配置Swagger的Bean实例@Beanpublic Docket createDocket(){return new Docket(DocumentationType.SWAGGER_2).apiInfo(createApiInfo()).groupName("yangl")分组名称(可以创建多个Docket就有多个组名).enable(true)//enable表示是否开启Swagger.select()//RequestHandlerSelectors指定扫描的包.apis(RequestHandlerSelectors.basePackage("com.qf.controller")).build();}//配置API的基本信息(会在http://项目实际地址/swagger-ui.html页面显示)public ApiInfo createApiInfo(){return new ApiInfoBuilder().title("测试标题").description("测试描述").version("1.0").termsOfServiceUrl("").build();//return ApiInfo.DEFAULT;}}
Swagger通过注解表明该接口会生成文档,包括接口名、请求方法、参数、返回信息
@Api:修饰整个类,描述Controller的作用
@ApiOperation:描述一个类的一个方法,或者说一个接口
@ApiModel:用对象来接收参数 ,修饰类
@ApiModelProperty:用对象接收参数时,描述对象的一个字段
@ApiResponse:HTTP响应其中1个描述
@ApiResponses:HTTP响应整体描述,一般描述错误的响应
@ApiIgnore:使用该注解忽略这个API
@ApiError :发生错误返回的信息
@ApiParam:单个参数描述
@ApiImplicitParam:一个请求参数,用在方法上
@ApiImplicitParams:多个请求参数