spring boot抛弃了传统xml配置文件,通过配置类(标注@Configuration的类,@Configuration配置类相当于一个xml配置文件)以JavaBean形式进行相关配置。
正常情况下,spring boot的自动配置可以满足我们的大部分需求。但在保留spring boot提供的便利,又需要增加额外SpringMVC配置的时候,可以自定义一个配置类(标注@Configuration的类)并实现WebMvcConfigurer接口来定制SpringMvc配置
SpringBoot 1.5通过继承WebMvcConfigurerAdapter抽象类来定制SpringMvc配置。SpringBoot 2.0后,WebMvcConfigurerAdapter抽象类过时了,改为实现WebMvcConfigurer接口来定制SpringMvc配置
/**
* SpringBoot 1.5
*/
@Configuration
public class SpringMvcConfiguration extends WebMvcConfigurerAdapter {
}
-------------------------------------------------------------------------------------------
/**
* SpringBoot 2.0
*/
@Configuration
public class SpringMvcConfiguration implements WebMvcConfigurer {
}
WebMvcConfigurer接口源码,具体可看WebMvcConfigurer官方文档
package org.springframework.web.servlet.config.annotation;
import java.util.List;
import org.springframework.core.convert.converter.Converter;
import org.springframework.format.Formatter;
import org.springframework.format.FormatterRegistry;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.lang.Nullable;
import org.springframework.validation.MessageCodesResolver;
import org.springframework.validation.Validator;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.servlet.DispatcherServlet;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;
/**
* 采用JavaBean的形式代替传统的xml配置文件对Spring MVC进行定制
*/
public interface WebMvcConfigurer {
//帮助配置HandlerMappings路径匹配选项,例如尾部斜杠匹配,后缀注册,路径匹配器和路径帮助器
default void configurePathMatch(PathMatchConfigurer configurer) {
}
//配置内容协商选项
default void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
}
//配置异步请求处理选项
default void configureAsyncSupport(AsyncSupportConfigurer configurer) {
}
//通过转发到Servlet容器的“默认” Servlet,配置处理程序以委派未处理的请求
default void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
}
//除了默认注册的之外,还添加Converters和Formatters
default void addFormatters(FormatterRegistry registry) {
}
//添加Spring MVC生命周期拦截器,以对控制器方法调用和资源处理程序请求进行预处理
default void addInterceptors(InterceptorRegistry registry) {
}
//添加处理程序以从Web应用程序根目录,类路径等中的特定位置提供静态资源,例如图像,js和css文件
default void addResourceHandlers(ResourceHandlerRegistry registry) {
}
//配置跨源请求处理
default void addCorsMappings(CorsRegistry registry) {
}
//配置预先配置了响应状态代码和/或用于呈现响应主体的视图的简单自动化控制器
default void addViewControllers(ViewControllerRegistry registry) {
}
//配置视图解析器,以将从控制器返回的基于字符串的视图名称转换为具体的View 实现以执行渲染
default void configureViewResolvers(ViewResolverRegistry registry) {
}
//添加解析器以支持自定义控制器方法参数类型
default void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
}
//添加处理程序以支持自定义控制器方法返回值类型
default void addReturnValueHandlers(List<HandlerMethodReturnValueHandler> handlers) {
}
//配置HttpMessageConverters用于读取或写入请求或响应主体的
default void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
}
//提供MessageCodesResolver用于从数据绑定和验证错误代码构建消息代码的自定义
default void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
}
//配置异常解析器
default void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) {
}
//扩展或修改默认配置的异常解析器列表
default void extendHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) {
}
//提供MessageCodesResolver用于从数据绑定和验证错误代码构建消息代码的自定义
default MessageCodesResolver getMessageCodesResolver() {
return null;
}
}
WebMvcConfigurer接口中定义了许多SpringMvc相关的方法,通过在配置类中重写相应的方法即可定制相关的SpringMvc配置,下面我会挑几个较常用的方法进行解析
spring boot默认将/**
静态资源访问映射到classpath:/static/
目录下.
如果spring boot的默认配置不能满足你的需求或你想修改它的默认配置,则可定义一个配置类来实现WebMvcConfigurer接口,并重写它的addResourceHandlers()方法来定制静态资源访问映射访问映射。
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.*;
@Configuration
public class SpringMvcConfiguration implements WebMvcConfigurer {
/**
* 添加静态资源访问映射配置
* @param registry
*/
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/js/**").addResourceLocations("classpath:/static/js/");
registry.addResourceHandler("/css/**").addResourceLocations("classpath:/static/css/");
registry.addResourceHandler("/image/**").addResourceLocations("classpath:/static/image/");
//意思是:url中读取到/upload时,就会自动将/upload解析成D:/idea/java_workspace/image/upload
registry.addResourceHandler("/upload/**").addResourceLocations("file:D:/idea/java_workspace/image/upload/");
/**
* Linux系统
* registry.addResourceHandler("/upload/**").addResourceLocations("file:/home/image/upload/");
*/
}
}
文件的放置目录分两种:项目内部的文件 和 项目外部的文件;具体配置方式如下:
//配置内部静态资源文件访问映射
registry.addResourceHandler("/image/**").addResourceLocations("classpath:/static/image/");
//配置外部静态资源文件访问映射(Windows系统)
registry.addResourceHandler("/image/**").addResourceLocations("file:D:/idea/java_workspace/image/");
//配置外部静态资源文件访问映射(Linux系统)
registry.addResourceHandler("/image/**").addResourceLocations("file:/home/image/");
友情提示:内部静态资源文件一般使用spring boot的默认配置即可(即:将/**
静态资源访问映射到classpath:/static/
目录);重写addResourceHandlers()方法一般用来定制外部静态资源的访问映射。
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.*;
@Configuration
public class SpringMvcConfiguration implements WebMvcConfigurer {
/**
* 添加拦截器链配置
* @param registry
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
//注册拦截器1,对商家管理系统进行权限验证
InterceptorRegistration registration1 = registry.addInterceptor(new ShopAdminInterceptor());
//指定拦截器1要拦截的请求(支持*通配符)
registration1.addPathPatterns("/shop_admin/**");
//注册拦截器2,对超级管理员系统进行权限验证
InterceptorRegistration registration2 = registry.addInterceptor(new SuperAdminInterceptor());
/*指定拦截器2要拦截的请求(支持*通配符)*/
registration2.addPathPatterns("/super_admin/**");
//指定拦截器2不拦截的请求(支持*通配符)
registration2.excludePathPatterns("/super_admin/toLogin");
}
}
自定义拦截器类1
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class ShopAdminInterceptor extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//获取用户登陆信息
Person person = (Person) request.getSession().getAttribute("person");
//判断用户是否有权限进入商家管理后台系统
if(person != null && person.getUserId() > 0
&& person.getEnableStatus() == 1 && person.getPersonType() == 2){
//如果验证通过,则返回true,放行请求,即用户接下来的操作可以正常执行
return true;
}
//如果不满足登陆验证,则跳转到登陆页面
response.sendRedirect("/o2o/local/to_login");
return false;
}
}
自定义拦截器类2
import com.cd.o2o2.entity.Person;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class SuperAdminInterceptor extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//获取用户登陆信息
Person person = (Person) request.getSession().getAttribute("person");
//判断用户是否有权限进入超级管理员后台系统
if(person != null && person.getUserId() > 0
&& person.getEnableStatus() == 1 && person.getPersonType() == 3){
//如果验证通过,则返回true,放行请求,即用户接下来的操作可以正常执行
return true;
}
//如果不满足登陆验证,则跳转到登陆页面
response.sendRedirect("/o2o/local/to_login");
return false;
}
}
项目开发中,时常会涉及到无业务逻辑的页面跳转; 这个页面跳转没有涉及到任何的业务逻辑,只是单纯的路由跳转过程;但却需要在Controller中编写路由方法来完成,每一个页面跳转都需要定义一个路由方法,个人感觉是挺麻烦滴。
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping("/frontend")
public class FrontendController {
/**
* 首页路由
*/
@RequestMapping("/index")
private String index(){
return "frontend/index";
}
/**
* 店铺列表路由
*/
@RequestMapping("/to_shop_list")
private String toShopList(){
return "frontend/shop_list";
}
/**
* 店铺列表路由
*/
@RequestMapping("/shop_detail")
private String shopDetail(){
return "frontend/shop_detail";
}
}
SpringBoot中,可以通过重写addViewControllers()方法来配置无业务逻辑的页面跳转; 摆脱路由方法这个麻烦,当然你习惯使用路由方法来实现无业务逻辑的页面跳转也是没问题滴哦.
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.*;
@Configuration
public class SpringMvcConfiguration implements WebMvcConfigurer {
/**
* 添加无业务逻辑页面跳转配置
* @param registry
*/
@Override
public void addViewControllers(ViewControllerRegistry registry) {
//首页路由
registry.addViewController("/frontend/index").setViewName("frontend/index");
//店铺列表路由
registry.addViewController("/frontend/to_shop_list").setViewName("frontend/shop_list");
//店铺列表路由
registry.addViewController("/frontend/shop_detail").setViewName("frontend/shop_detail");
}
}
package com.cd.o2o2.config.web;
import com.cd.o2o2.interceptor.ShopAdminInterceptor;
import com.cd.o2o2.interceptor.SuperAdminInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.*;
@Configuration
public class SpringMvcConfiguration implements WebMvcConfigurer {
/**
* 添加静态资源访问映射配置
*/
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
//内部静态资资源访问映射
registry.addResourceHandler("/js/**").addResourceLocations("classpath:/static/js/");
registry.addResourceHandler("/css/**").addResourceLocations("classpath:/static/css/");
registry.addResourceHandler("/image/**").addResourceLocations("classpath:/static/image/");
//外部静态资资源访问映射
registry.addResourceHandler("/upload/**").addResourceLocations("file:D:/idea/java_workspace/image/upload/");
}
/**
* 添加拦截器链配置
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
//注册拦截器1,对商家管理系统进行权限验证
InterceptorRegistration registration1 = registry.addInterceptor(new ShopAdminInterceptor());
//指定拦截器1要拦截的请求(支持*通配符)
registration1.addPathPatterns("/shop_admin/**");
//注册拦截器2,对超级管理员系统进行权限验证
InterceptorRegistration registration2 = registry.addInterceptor(new SuperAdminInterceptor());
//指定拦截器2要拦截的请求(支持*通配符)
registration2.addPathPatterns("/super_admin/**");
}
/**
* 添加无业务逻辑页面跳转配置
*/
@Override
public void addViewControllers(ViewControllerRegistry registry) {
//首页路由
registry.addViewController("/frontend/index").setViewName("frontend/index");
//店铺列表路由
registry.addViewController("/frontend/to_shop_list").setViewName("frontend/shop_list");
//店铺列表路由
registry.addViewController("/frontend/shop_detail").setViewName("frontend/shop_detail");
}
}