SpringMVC 知识点总结
MVC 设计思想
mvc: (Model View Controller), 将一个web应用程序进行分层、model专注于
业务逻辑(业务层、持久层、实体层), view 专注于页面表现,通过将 业务和表现 进行分离
可以降低程序的耦合度,让程序变得更加容易维护,通过 controller 将 view 和 model进行
关联,从而实现web应用程序的开发,mvc强调所有的请求应该有一个统一的访问入口,在SpringMVC
中,通过 DispatcherServlet 核心控制器进行实现
DispatcherServlet
DispatcherServlet 是一个 Servlet, 所以 SpringMVC 本质上仍旧是Servlet, 只是对Servlet
进行了深度的封装, DispatcherServlet会产生一个 springmvc容器,该容器默认的配置文件是
-servlet.xml, 可以通过contextConfigLocation进行配置文件的设置
- 在 web.xml 中 配置 核心控制器 DispatcherServlet
<servlet>
<servlet-name>spring</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:spring-mvc.xml</param-value>
</init-param>
<!-- DispatcherServlet中的init方法会随tomcat启动而加载,如果不配置,会在第一次使用servlet的时候才会执行 -->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
- 在 web.xml 中,配置 Spring容器
Spring容器不是必须的,可以整个环境只有一个springmvc容器,官方推荐使用两个容器
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:spring-context.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
Spring容器, SpringMVC容器扫描配置
- 将 控制层 交给 SpringMVC 容器 负责扫描
spring-mvc.xml
<context:component-scan base-package="com.qikux" use-default-filters="false">
<!-- 添加一个 白名单,只让它扫描 Controller 注解注释的类 -->
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
use-default-filters 默认是true, 代表会扫描类上的 @Controller, @Service, @Repository, @Component注解
如果设置为false, 那么只会扫描 白名单中配置的某个注解
- 将除控制层 之外的其他对象交给 Spring容器负责扫描
spring-context.xml
<context:component-scan base-package="com.qikux">
<!-- 添加一个 黑名单,让它扫描 除 Controller 注解注释的类之外的类 -->
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
视图解析器 InternalResourceViewResolver
视图解析器是为了映射控制层返回的结果,控制层,返回String或者 ModelAndView ,那么如果找到对应的 view 页面
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
控制器的编写
@Controller
@RequestMapping("/index")
public class IndexController {
@GetMapping("/")
public ModelAndView index() {
return new ModelAndView("index");
}
}
@RequestMapping 可以写在 类上,用来定义访问请求的一级路径,可以写在方法上,用来定义二级路径
在方法上,推荐使用 @GetMapping, @PostMapping, @PutMapping, @DeleteMapping …
PS: http://localhost:8080/index/ 即可找到 /WEB/INF/jsp/index.jsp 视图
SpringMVC 接收页面参数
- 在控制器上,直接通过 @RequestParam 注解 接收传入的参数
缺点: 如果参数过多,那么控制器的方法声明会显得非常臃肿,并且在接收数据后可能还要进行数据组装
@Controller
@RequestMapping("/index")
public class IndexController {
@GetMapping("/")
public ModelAndView index(@RequestParam(value="name", required=true) String name) {
return new ModelAndView("index");
}
}
PS: http://localhost:8080/index/?name=张三
@RequestParam 注解
- value : 用来设置表单提交参数的key, 如果不指定,默认和被注解的变量名称保持一致
- required: 是否必传,默认为 true, 用来限定参数是否必传
- defaultValue : 设置默认值,通过和 required=false 配合使用
- 使用模型对象接收页面参数
优点: 可以将多个参数直接组装成一个模型对象
缺点: 不能限制某个参数是否必传,可以配置后期的数据校验来实现参数的限制
@Controller
@RequestMapping("/index")
public class IndexController {
@GetMapping("/")
public ModelAndView index(User user) {
return new ModelAndView("index");
}
}
class User {
private String username ;
private String password ;
... set, get ...
}
PS: http://localhost:8080/index/?username=admin&password=123456
- 使用 Map 来接收页面参数
@Controller
@RequestMapping("/index")
public class IndexController {
@GetMapping("/")
public ModelAndView index(@RequestParam Map<String, Object map) {
return new ModelAndView("index");
}
}
PS: http://localhost:8080/index/?name=admin&pwd=123456
参数 会自动被放入到 Map 中,在 Map参数前,必须添加 @RequestParam注解,且不能设置 value
- 路径参数
路径参数支持的写法有
{key} : key用来匹配一个路径参数,但不能匹配 /
{key:regexp} 在key的后面允许使用 正则表达式进行值的限制
支持 * , ? 等通配符
@Controller
@RequestMapping("/index")
public class IndexController {
@GetMapping("/{id}")
public ModelAndView index(@PathVariable Long id) {
return new ModelAndView("index");
}
}
@PathVariable 注解
- value : 用来设置 /{id} 占位符中的key, 和占位符中的key保持一致,如果不设置,则 需要变量名和占位符保持一致
- json格式参数接收
主要配合 异步请求实现 JSON数据格式的传输
@Controller
@RequestMapping("/index")
public class IndexController {
@PostMapping("/json")
@ResponseBody
public User index(@RequestBody User user) {
return user;
}
}
fetch('http://localhost:8080/index/json', {
method: 'post' ,
headers: {
'Content-Type': 'application/json' ,
},
body: JSON.stringify( {username: 'admin', password: '123456'} )
})
响应方式
-
返回 String
- 通过视图解析器转换到 jsp页面
@Controller @RequestMapping("/index") public class IndexController { @GetMapping("/") public String index() { return "index"; } }
pS: 会找到 /WEB-INF/jsp/index.jsp
- 转发到一个内部请求中
@Controller @RequestMapping("/index") public class IndexController { @GetMapping("/") public String index() { return "forward:/index/a"; } @GetMapping("/a") public String a() { return "a"; } }
当访问 /index/ 的时候,会通过转发 跳转到 /index/a 最终呈现的是 a.jsp页面效果
- 重定向
@Controller @RequestMapping("/index") public class IndexController { @GetMapping("/") public String index() { return "redirect:/index/a"; } @GetMapping("/a") public String a() { return "a"; } }
当访问 /index/ 的时候,会通过重定向 跳转到 /index/a 最终呈现的是 a.jsp页面效果
-
返回 ModelAndView (官方推荐写法)
返回一个ModelAndView 对象,可以通过 构造方法或者setViewName 设置视图名,
视图名的写法参考返回String
的三种写法
return new ModelAndView("index") ;
return new ModelAndView("forward:/index/a")
return new ModelAndView("redirect:/index/a")
- 返回 HttpEntity 或者 ResponseEntity
主要应用于文件下载
@Controller
@RequestMapping("/index")
public class IndexController {
@GetMapping("/")
public HttpEntity<String> index() {
return ResponseEntity.ok("hello world!");
}
}
Ps:当访问 http://localhost:8080/index/ 的时候,浏览器会显示一个 hello world!
-
返回 JSON
- 方式一:
@Controller @RequestMapping("/index") public class IndexController { @GetMapping("/") public HttpEntity<User> index() { return ResponseEntity.ok(User....); } }
- 方式二:
@Controller @RequestMapping("/index") public class IndexController { @GetMapping("/") @ResponseBody public User index() { return User...; } }
如果需要返回JSON, 那么需要添加 jackson对应的依赖包,并配置消息转换器。
如果一个类所有的请求都需要返回JSON, 可以直接在类上使用@ResponseBody
或者 使用 @RestController 替代 @Controller + @ResponseBody
消息转换器配置
<bean id="mappingJackson2HttpMessageConverter"
class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="defaultCharset" value="utf-8"/>
<property name="supportedMediaTypes">
<list>
<value>text/html;charset=utf-8</value>
<value>application/json;charset=utf-8</value>
</list>
</property>
<property name="objectMapper">
<bean class="com.qikux.modules.Jdk8TimeMapper"/>
</property>
</bean>
<bean id="stringHttpMessageConverter" class="org.springframework.http.converter.StringHttpMessageConverter">
<property name="defaultCharset" value="utf-8"/>
<property name="supportedMediaTypes" value="text/html;charset=utf-8"/>
</bean>
<mvc:annotation-driven>
<mvc:message-converters>
<ref bean="stringHttpMessageConverter"/>
<ref bean="mappingJackson2HttpMessageConverter"/>
</mvc:message-converters>
</mvc:annotation-driven>
服务器向客户端传递数据方式
- 使用 ModelMap 传递数据
@Controller
@RequestMapping("/index")
public class IndexController {
@GetMapping("/")
public String index(ModelMap modelMap) {
// 传递一个键值对格式的数据
modelMap.addAttribute(key, val) ;
// 传递 一组 键值对格式的数据
modelMap.addAllAttributes(map);
...
return "index";
}
}
值会被携带到 /WEB-INF/jsp/index.jsp中,并放在了request作用域中,
可以通过EL表达式,根据键 获取值
- 使用 Model 传递数据
用法和 ModelMap 完全相同
- 使用 ModelAndView 传递数据
@Controller
@RequestMapping("/index")
public class IndexController {
@GetMapping("/")
public ModelAndView index(ModelAndView mav) {
mav.setViewName("index") ;
mav.addObject(key, val);
mav.addAllObjects(map) ;
...
return mav ;
}
}
值会被携带到 /WEB-INF/jsp/index.jsp中,并放在了request作用域中,
可以通过EL表达式,根据键 获取值
- 使用 原生 request 传递数据
@Controller
@RequestMapping("/index")
public class IndexController {
//@Resource
//private HttpServletRequest request ;
@GetMapping("/")
public String index(HttpServletRequest request) {
request.setAttribute(key, val) ;
...
return "index" ;
}
}
需要引入 servlet-api 依赖包, request对象也可以通过 属性依赖注入的方式获取
- 使用 RedirectAttributes 传递数据
解决 重定向 无法 通过 request 向下一个请求 传值的问题
@Controller
@RequestMapping("/index")
public class IndexController {
@GetMapping("/")
public String index(RedirectAttributes ra) {
// 通过闪存属性将数据传递到下一个请求中
ra.addFlashAttribute(key, val) ;
return "redirect:/index/a" ;
}
@GetMapping("/a")
public String a(ModelMap model) {
// 获取上一个请求通过闪存 传递的数据
Object obj = model.getAttribute(key)
...
return "a" ;
}
}
- 使用 session 传递数据
public class IndexController {
//@Resource
//private HttpSession session ;
@GetMapping("/")
public String index(HttpSession session) {
session.setAttribute(key, val) ;
...
return "index" ;
}
}
文件上传
- 通用文件上传解析器实现文件上传
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!--设置 文件上传编码方式-->
<property name="defaultEncoding" value="UTF-8"/>
<!--默认值是 -1 ,代表 不限制上传文件的大小-->
<property name="maxUploadSize" value="-1"/>
</bean>
需要 依赖 commons-fileupload 依赖包 , 在控制层上 使用 MultipartFile 接收上传的文件
public class IndexController {
//@Resource
//private HttpSession session ;
@PostMapping("/upload")
public String upload(@RequestPart("photo") MultipartFile photo) {
// 获取上传的文件名
photo.getOriginalFilename();
// 上传的文件是否是空的
photo.isEmpty();
// 获取上传的文件大小
photo.getSize();
// 用 byte[] 存储上传的文件
photo.getBytes();
// 以 字节流的形式存储上传的文件
photo.getInputStream();
// 将文件存储到指定的位置
photo.transferTo(file);
...
return "index" ;
}
}
MultipartFile 用来接收上传的文件对象,如果是多个文件,可以采用数组方式进行接收,
可以使用 @RequestParam 注解来限定上传对象对象,也可以通过 @RequestPart 来限定
- 基于 servlet3.0 文件上传
配置servlet标准文件上传解析器
<bean id="multipartResolver"
class="org.springframework.web.multipart.support.StandardServletMultipartResolver" />
在 核心控制器 DispatcherServlet中,添加 支持文件上传 , 使用 Part 对象接收上传的文件
支持 @RequestPart注解来限定文件上传
public class IndexController {
//@Resource
//private HttpSession session ;
@PostMapping("/upload")
public String upload(@RequestPart("photo") Part photo) {
// 获取上传的文件名
photo.getSubmittedFileName();
// 获取上传的文件大小
photo.getSize();
// 以 字节流的形式存储上传的文件
photo.getInputStream();
// 将文件存储到指定的位置
photo.write(file);
...
return "index" ;
}
}
无论使用那种文件上传,文件上传解析器的bean的ID必须叫 multipartResolver
文件下载 HttpEntity
public class IndexController {
//@Resource
//private HttpSession session ;
@PostMapping("/download")
public HttpEntity<byte[]> download() {
byte[] files = ... ;
String filename = ... ;
// 解决下载中文乱码问题
filename = URLEncoder.encode(filename, StandardCharsets.UTF_8);
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + filename)
.body(files)
}
}
数据校验
Spring 提供了数据校验的功能,但Spring本身对数据校验实现的很少,
需要依赖 javax.validation 和 hibernate-validator 依赖包
常见的注解
- @Email : 用来校验 邮箱
- @Max : 用来限定数字的最大值
- @Min : 用来限定数字的最小值
- @Null / @NotNull : 用来限制值是否允许为空/非空
- @Pattern : 使用正则表达式 验证字符串
- @Past : 是否是 过去日期
- @Future : 是否是未来日期
- @Size(): 限制字符串最大/小长度
- @Lenght(): 限制字符串最大/小长度
- @Range(): 用来限定数字的范围
public class User {
@Pattern(regexp = "[a-zA-Z][a-zA-Z0-9]{6,20}", message = "用户名以字母开头,且由字母和数组组成长度为6~20位")
@NotEmpty(message = "用户名不能为空")
private String username;
@NotNull(message = "密码不允许为空")
@Length(max = 20, min = 6, message = "密码长度在6~20位")
private String password;
...
}
校验数据
public class IndexController {
//@Resource
//private HttpSession session ;
@PostMapping("/regist")
public String regist(@Valid User user, BindingResult bindingResult) {
// 如果 校验失败
if (bindingResult.hasErrors()) {
// 获取错误消息
bindingResult.getFieldErrors();
// 将错误信息 放到 Map 对象中
Map<String, String> error = fieldErrors.stream()
.reduce(new HashMap<>(), (map, f) -> {
map.put(f.getField(), f.getDefaultMessage());
return map;
}, (a, b) -> a) ;
....
}
return "index" ;
}
}
数据校验需要配置一个 LocalValidatorFactoryBean 对象,
可以通过 <mvc:annotation-driven /> 来启用该 bean 。
bindingResult.getFieldErrors()得到的错误信息,在jsp页面中,可以通过 spring 标签库获取
常见的过滤器
- CharacterEncodingFilter : 字符集编码过滤器
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
字符集编码过滤器通常配置在其他过滤器的前面
- HiddenHttpMethodFilter : 让表单支持 PUT, DELETE, PATCH 请求方式
<filter>
<filter-name>hiddenHttpMethodFilter</filter-name>
<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>hiddenHttpMethodFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
在提交表单是时候,提交方式设置为 POST, 传递一个 _method 参数,值为 PUT, DELETE, PATCH ,
让传统的同步表单提交支持 PUT , DELETE, PATCH 请求
- FormContentFilter : XMLHttpRequest异步请求无法使用PUT,DELETE, PATCH 传递表单参数
<filter>
<filter-name>formContentFilter</filter-name>
<filter-class>org.springframework.web.filter.FormContentFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>formContentFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
- CorsFilter : 解决 异步请求 跨域
静态资源处理
方式一:
<mvc:default-servlet-handler/>
底层使用 DefaultServletHttpRequestHandler 处理静态资源
方式二:
<mvc:resources mapping="/css/**" location="/css/" />
<mvc:resources mapping="/js/**" location="/js/" />
<mvc:resources mapping="/images/**" location="/images/" />
底层使用 ResourceHttpRequestHandler 处理静态资源
拦截器 HandlerInterceptor
拦截器 是 SpringMVC 特有的 切面手段,可以拦截 控制层对应的请求,
主要采用反射技术实现
- preHandler : 前置处理器
会在进行到 控制器对应的方法前,执行 preHandler处理器中定义的代码,
如果 preHandler 返回 true, 则 继续执行下一个拦截器的preHandler或者
执行控制器对应的方法, 如果返回 false, 则会中断程序的执行,默认情况下
在浏览器上会呈现一片空白的效果。可以借助 request, response 进行合适的跳转
- postHandler : 后置处理器
会在控制器方法执行完成(没有异常)的情况下,执行 postHandler后置处理器中的代码
可以获取到 控制器方法返回的结果 ModelAndView
- afterCompletion : 最终处理器
无论控制器的方法是否有异常,都会执行的代码, 如果产生了异常,可以通过Exception异常对象来获取
拦截器 VS 过滤器
相同点:
- 都采用的切面技术
- 都可以拦截请求和响应
不同点:
- 过滤器filter 是 servlet容器提供的, 拦截器interceptor是 springmvc 框架提供的
- 过滤器filter 采用链式调用,拦截器是采用反射调用的
- 过滤器原则上可以拦截几乎所有请求,而拦截器只能拦截action请求
- 过滤器 先于 拦截器 执行
- 如果只需要对Action请求进行拦截,那么优先使用拦截器,如果对所有请求进行拦截,那么优先采用过滤器
国际化 (国内开发实际应用较少)
国际化主要通过 拦截器技术实现的,主要使用的类是 LocaleChangeInterceptor
在一些大型网站中,通常为了方便大众的使用,会对网站提供多语言的支持,例如支持
中文、英文、日文、韩文、俄文。那么此时网站需要对页面呈现的数据进行国际化处理
-
配置 语言解析器
- AcceptHeaderLocaleResolver
- CookieLocaleResolver
- SessionLocaleResolver
<bean id="localeResolver"
class="org.springframework.web.servlet.i18n.CookieLocaleResolver" />
默认采用的是 AcceptHeaderLocaleResolver 解析器,根据浏览器请求的 Accept-language 头信息
获取 对应的语言环境 , 可以使用 CookieLocaleResolver 和 SessionLocaleResolver 将要切换的语言
放到 Cookie / Session 中 ,解析器beanID 必须设置为 localeResolver
- 管理国际化配置文件 ResourceBundleMessageSource
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="defaultEncoding" value="UTF-8" />
<!-- 国际化配置文件的前缀名,默认是 messages -->
<property name="basename" value="messages" />
</bean>
国际化配置文件的命名规范是 _语言.properties, 例如
messages_zh_CN.properties (中文), message_en_US.properties (英文)
messages_ja_JP.properties (日文) …
messages_zh_CN.properties
messages_en_US.properties
- 配置 语言拦截器
<mvc:interceptors>
<bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor"
p:paramName="locale"/>
</mvc:interceptors>
- 配置超链接,切换语言
<a href="?locale=zh_CN">中文</a>
<a href="?locale=en_US">英文</a>
<a href="?locale=ja_JP">日文</a>
- 在 jsp 页面,使用 <spring:message /> 标签国际化页面数据
<spring:message code="" arguments="..."/>
code 是 国际化配置文件中定义的键,arguments 是该键对应值需要的参数
在 值上可以使用 {n} 进行占位, n 从 0开始
- 在代码中,使用国际化
@Autowired
private MessageSource messageSource ;
...
messageSource.getMessage(code, args, locale);
异常处理器
SpringMVC 提供了异常解决方案,可以通过 xml 或者 注解的方式 来进行配置
xml配置异常处理器 SimpleMappingExceptionResolver
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<!--
配置 默认错误发生的时候,进入的 视图页面, 会自动找 /WEB-INF/jsp/error.jsp
程序产生异常 才会进入的 页面
-->
<property name="defaultErrorView" value="error" />
<!-- 当 进入 错误页面的时候,默认显示的状态码 , 默认是 200 -->
<property name="defaultStatusCode" value="500" />
<!-- 根据 程序返回的异常,跳转 不同的视图页面 -->
<property name="exceptionMappings">
<props>
<prop key="java.lang.RuntimeException">error_run</prop>
<prop key="java.lang.Exception">error</prop>
</props>
</property>
</bean>
注解配置异常处理器 @ExceptionHandler
- 局部配置 异常处理器
@Controller
@RequestMapping("/index")
public class IndexController {
@GetMapping("/")
public ModelAndView index() {
return new ModelAndView("index");
}
@ExceptionHandler
public ModelAndView error(Throwable e) {
... 获取 异常信息
return new ModelAndView("error");
}
}
如果在一个控制器中,添加一个 @ExceptionHandler,那么该注解注释的方法
只能在该控制器下的请求发生异常的时候,才会触发,其他控制器产生异常,不会
触发该异常处理
- 全局配置 异常处理器
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler
public ModelAndView error(Throwable e) {
... 获取 异常信息
return new ModelAndView("error");
}
}
- 全局 JSON 异常处理器
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler
public Object error(Throwable e) {
... 获取 异常信息
return ... ;
}
}
@ExceptionHandler 可以通过 value 设置 针对具体哪种异常进行处理
其它注解
- @ModelAttribute : 在接收参数的模型对象上,可以使用该注解,将 参数放到 request作用域中
@Controller
public class IndexController {
public String register(@ModelAttribute("user")User user) {
return "..." ;
}
}
- @SessionAttributes : 该注解主要应用于类上,将指定的数据放入到 session中
@Controller
@SessionAttributes(AppConst.LOGIN_FLAG)
public class LoginController {
public ModelAndView login(String username ,String password) {
...
// 当向 ModelAndView 中,添加一个
键为 AppConst.LOGIN_FLAG(和 sessionattributes中的键相同)
的时候,那么会自动将 该数据添加到 session中
mav.addObject(AppConst.LOGIN_FLAG, user) ;
return "..." ;
}
}
- @SessionAttribute : 获取 Session中对应的数据
@Controller
public class IndexController {
/**
从 session中获取 User 对象
*/
public String index(
@SessionAttribute(value=AppConst.LOGIN_FLAG, required=false)User user) {
// 直接通过 @SessionAttribute 获取登录标记
return "index" ;
}
}
- SessionStatus 清除 session 中的数据
@Controller
public class IndexController {
/**
从 session中获取 User 对象
*/
public String logout(SessionStatus status) {
...
if (status.isComplete()) {
// 清除 session 中的数据
status.setComplete();
}
return "index" ;
}
}
-
@CookieValue : 用来获取Cookie中指定键对应的值
-
@RequestHeader : 用来获取 Header请求头中某个键对应的值
任务调度
添加依赖包
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.3.2</version>
</dependency>
- 基于XML的实现方式
- 编写一个任务
public class SimpleJob {
/**
* 负责打印内容
*/
public void printText() {
System.out.println("job is running .... 打印的内容是: hello");
}
}
- 定义一个 jobDetail 任务
<bean id="jobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<property name="targetObject">
<bean class="com.qikux.quartz.SimpleJob" />
</property>
<property name="targetMethod" value="printText"/>
</bean>
- 定义一个 Trigger 任务触发器
<bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
<property name="jobDetail" ref="jobDetail" />
<property name="cronExpression" value="0/3 * * * * ?"></property>
</bean>
- 定义一个 Schedule 任务调度器
<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="triggers">
<array>
<ref bean="cronTrigger" />
</array>
</property>
</bean>
- 基于 JavaConfig 开发
-
在 配置类上,添加 @EnableScheduling
-
在 任务类上,添加 @Scheduled
@Component
public class SimpleJob {
/**
* 负责打印内容
*/
@Scheduled(cron="0/3 * * * * ?")
public void printText() {
System.out.println("job is running .... 打印的内容是: hello");
}
}
- 定义一个 jobDetail 任务
<bean id="jobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<property name="targetObject">
<bean class="com.qikux.quartz.SimpleJob" />
</property>
<property name="targetMethod" value="printText"/>
</bean>
- 定义一个 Trigger 任务触发器
<bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
<property name="jobDetail" ref="jobDetail" />
<property name="cronExpression" value="0/3 * * * * ?"></property>
</bean>
- 定义一个 Schedule 任务调度器
<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="triggers">
<array>
<ref bean="cronTrigger" />
</array>
</property>
</bean>