springboot学习(三)整合web开发
整合web开发
静态资源默认在 resources/static 目录,Spring Boot 中默认情况下,一共有5个位置可以放静态资源,五个路径分别是如下5个:
-
classpath:/META-INF/resources/
-
classpath:/resources/
-
classpath:/static/
-
classpath:/public/
-
/
前四个目录分别对应了resources目录下不同的目录,第5个 /
表示 webapp 目录中的静态资源也不被拦截。
@ControllerAdvice
@ControllerAdvice 可以实现三个功能:
-
全局异常处理
-
全局数据绑定
-
全局数据预处理
-
全局异常处理
使用 @ControllerAdvice 实现全局异常处理,只需要定义类,添加该注解即可定义方式如下:
@ExceptionHandler 注解用来指明异常的处理类型,即如果这里指定为 NullpointerException,则数组越界异常就不会进到这个方法中来。
如果程序有异常抛出,且抛出的异常和@ExceptionHandler指明的异常类型相同,则@ExceptionHandler注解的方法捕获并处理这个异常。
-
全局数据绑定
全局数据绑定功能可以用来做一些数据初始化操作,我们可以将一些公共的数据定义在添加了 @ControllerAdvice 注解的类中,这样,在每一个 Controller 的接口中,就都能够访问导致这些数据
//使用@ModelAttribute定义全局数据,定义完成后,在任何一个Controller 的接口中,都可以获取到这里定义的数据
-
全局数据预处理
当有两个实体类的属性相同时,在接口传递这两个接口的属性,因为有相同属性会使前端无法区分, 解决步骤:
-
在接口中给实体参数取别名
-
@ControllerAdvice 标记的类中进行请求数据预处理
请求接口时,使用a.xx 和b.xx来区分
异常处理方案
-
静态异常页面
自定义静态异常页面,又分为两种,第一种 是使用 HTTP 响应码来命名页面,例如 404.html、405.html、500.html ....,另一种就是直接定义一个 4xx.html,表示400-499 的状态都显示这个异常页面,5xx.html 表示 500-599 的状态显示这个异常页面,默认存放在 classpath:/static/error/
路径下
-
动态的异常页
动态的异常页面定义方式和静态的基本 一致,可以采用的页面模板有 jsp、freemarker、thymeleaf。动态异常页面,也支持 404.html 或者 4xx.html,默认存放在 classpath:/templates/error/
路径下
注意,动态页面模板,不需要开发者自己去定义控制器,直接定义异常页面即可 ,Spring Boot 中自带的异常处理器会自动查找到异常页面
-
自定义异常数据
继承 org.springframework.boot.web.servlet.error.DefaultErrorAttributes ,重写 getErrorAttributes方法,并将这个类注册为bean
定义系统启动任务
项目启动阶段要做一些数据初始化操作,这些操作有一个共同的特点,只在项目启动时进行,以后都不再执行,这里,容易想到web基础中的三大组件( Servlet、Filter、Listener )之一 Listener ,这种情况下,一般定义一个 ServletContextListener,然后就可以监听到项目启动和销毁,进而做出相应的数据初始化和销毁操作。Spring Boot 中针对系统启动任务提供了两种解决方案,分别是 CommandLineRunner 和 ApplicationRunner
-
CommandLineRunner
-
实现CommandLineRunner接口和run方法,并注册为一个bean
-
添加 @Order注解,表示这个启动任务的执行优先级,因为在一个项目中,启动任务可能有多个,所以需要有一个排序。
-
run 方法中,写启动任务的核心逻辑,当项目启动时,run方法会被自动执行。run方法的参数来自于项目的启动参数,即项目入口类中,main方法的参数会被传到这里
-
传入项目启动参数有两种方式:
-
在IDEA的启动项目处 edit configurations,设置 program arguments
-
使用命令 Java -jar启动项目时传入参数
-
-
ApplicationRunner
ApplicationRunner 和 CommandLineRunner 功能一致,用法也基本一致,唯一的区别主要体现在对参数的处理上,ApplicationRunner 可以接收更多类型的参数(ApplicationRunner 除了可以接收 CommandLineRunner 的参数之外,还可以接收 key/value形式的参数)。
ApplicationRunner 的run方法参数ApplicationArguments 说明:
-
args.getNonOptionArgs();可以用来获取命令行中的无key参数(和CommandLineRunner一样)。
-
args.getOptionNames();可以用来获取所有key/value形式的参数的key。
-
args.getOptionValues(key));可以根据key获取key/value 形式的参数的value。
-
args.getSourceArgs(); 则表示获取命令行中的所有参数。
传入参数方式也和 CommandLineRunner 相同,传递键值对时使用 --key=value
定时任务
spring boot(spring+springMVC)实现定时任务有两种方案,一种是使用 Spring 自带的定时任务处理器 @Scheduled 注解,另一种就是使用第三方框架 Quartz
-
@Scheduled:只适合处理简单的计划任务,不能处理分布式计划任务。优势:是spring框架提供的计划任务,开发简单,执行效率比较高。且在计划任务数量太多的时候,可能出现阻塞,崩溃,延迟启动等问题。
-
在spring boot的启动类上添加 @EnableScheduling 注解,开启定时任务
-
使用 @Scheduled 添加一个方法上,表示一个定时任务,这个类注册为bean
-
@Scheduled的参数解析:
-
fixedRate 表示任务执行之间的时间间隔,具体是指两次任务的开始时间间隔,即第二次任务开始时,第一次任务可能还没结束。单位ms
-
fixedDelay 表示任务执行之间的时间间隔,具体是指本次任务结束到下次任务开始之间的时间间隔。单位ms
-
initialDelay 表示首次任务启动的延迟时间。
-
cron,支持cron表达式
-
Quartz:Quartz可以用来创建简单或为运行十个,百个,甚至是好几万个Jobs这样复杂的程序。
一般在项目中,除非定时任务涉及到的业务实在是太简单,使用 @Scheduled 注解来解决定时任务,否则大部分情况可能都是使用 Quartz 来做定时任务。
在开发Quartz相关应用时,只要定义了Job(任务),Trigger(触发器)和Scheduler(调度器),即可实现一个定时调度能力。其中Scheduler是Quartz中的核心,Scheduler负责管理Quartz应用运行时环境,Scheduler不是靠自己完成所有的工作,是根据Trigger的触发标准,调用Job中的任务执行逻辑,来完成完整的定时任务调度首先添加jar包依赖
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.3.1</version>
</dependency>
<!-- scheduled所属资源为spring-context-support,在Spring中对Quartz的支持,是集成在spring-context-support包中。org.springframework.scheduling.quartz -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
</dependency>
-
在spring boot的启动类上添加 @EnableScheduling 注解,开启定时任务
-
定义JOB任务以及JOB任务调用的模拟业务对象
-
创建Trigger以及JobDetail对象,并用Schedule配置定时任务
-
重写JobFactory
Swagger
自动生成接口文档,地址为 http://localhost:8080/swagger-ui.html
,首先添加swagger2的依赖
<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>
-
Swagger2配置
Swagger2的配置也是比较容易的,只需要开发者自己提供一个Docket的Bean即可,@EnableSwagger2注解启用Swagger2
-
创建controller和实体类
注解解析:
-
@Api注解用来标记当前Controller的功能。
-
@ApiOperation注解用来标记一个方法的作用。
-
@ApiImplicitParam注解用来描述一个参数,可以配置参数的中文含义,也可以给参数设置默认值,这样在接口测试的时候可以避免手动输入。
-
如果有多个参数,则需要使用多个@ApiImplicitParam注解来描述,多个@ApiImplicitParam注解需要放在一个@ApiImplicitParams注解中。
-
需要注意的是,@ApiImplicitParam注解中虽然可以指定参数是必填的,但是却不能代替@RequestParam(required = true),前者的必填只是在Swagger2框架内必填,抛弃了Swagger2,这个限制就没用了,所以假如开发者需要指定一个参数必填,@RequestParam(required = true)注解还是不能省略。
-
如果参数是一个对象,对于参数的描述也可以放在实体类中。例如下面一段代码:
-
在Security中的配置
如果我们的Spring Boot项目中集成了Spring Security,那么如果不做额外配置,Swagger2文档可能会被拦截,此时只需要在Spring Security的配置类中重写configure方法,添加如下过滤即可: