Springboot下的SpringMVC配置解析 ——WebMvcConfigurerAdapter和WebMvcConfigurationSupport

1、前言

Sprinboot中配置SpringMVC主要是继承WebMvcConfigurerAdapter(1.x版本)或者WebMvcConfigurationSupport(2.x版本)。此次主要介绍下web应用的一些经常使用配置。前端

2、开始配置

(一)配置参数解析器

参数解析器的做用,通俗来讲,参数解析器的做用是将请求中的参数映射到咱们Controller方法参数,好比说经过参数解析器,咱们能够将前端传过来的token参数作一下处理,从redis中取出用户信息,直接映射为一个userInfo对象,而后Controller方法的参数就直接是UserInfo类型的对象就能够了。如何使用勒?下面是一个简单范例,这里只贴出伪代码:web

首先咱们建立一个解析器类,而且实现HandlerMethodArgumentResolver接口。redis

public class TokenHandlerMethodArgumentResolver implements HandlerMethodArgumentResolver {
    private RedissonClient redissonClient;
    private UserDao userDao;
    public TokenHandlerMethodArgumentResolver(RedisClient redisClient, UserDao userDao) {
        this.redissonClient = redisClient;
        this.userDao = userDao;
    }
    @Override
    public boolean supportsParameter(MethodParameter methodParameter) {
        return User.class.isAssignableFrom(methodParameter.getParameterType());
    }

    @Override
    public Object resolveArgument(MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer, NativeWebRequest nativeWebRequest, WebDataBinderFactory webDataBinderFactory) throws Exception{
        HttpServletRequest nativeRequest = (HttpServletRequest) nativeWebRequest.getNativeRequest();
        String token = nativeRequest.getHeader("token");
        RBucket<String> userIdBucket = redissonClient.getBucket(token);
        if(StringUtils.isNotBlank(userIdBucket.get())){
            User user = userDao.getById(userIdBucket.get());
        }
        return user;
    }
}

而后建立类MyWebConfig,继承WebMvcConfigurerAdapter并实现ApplicationContextAware接口,为何实现ApplicationContextAware,是为了从IOC容器当中取出redissonClient和userDao,用于构造TokenHandlerMethodArgumentResolver。spring

public class MyWebConfig extends WebMvcConfigurerAdapter implements ApplicationContextAware {
    private UserDao userDao;
    private RedissonClient redissonClient;
    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
       argumentResolvers.add(new TokenHandlerMethodArgumentResolver(redissonClient,userDao));
        super.addArgumentResolvers(argumentResolvers);
    }
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        userDao = applicationContext.getBean(UserDao.class);
        redissonClient = applicationContext.getBean(RedissonClient.class);
    }
}

如上,HandlerMethodArgumentResolver最重要的两个方法是boolean supportsParameter(MethodParameter methodParameter)Object resolveArgument(MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer, NativeWebRequest nativeWebRequest, WebDataBinderFactory webDataBinderFactory),前者是若是返回ture表示使用该解析器进行解析,后者就是返回处理后的方法参数。另外例子中比较关键的方法有经过NativeWebRequest获取HttpServletRequest的方法 nativeWebRequest.getNativeRequest()。json

这里的逻辑是,若是参数中有参数的类型是User类型,那么直接经过token去获取注入在这里。对于咱们来讲,若是须要用户信息就只须要在Controller中加个User参数,就自动有了,不须要本身查,就能够很方便的引用用户的相关信息。跨域

(二)配置数据序列化

配置数据序列化有两种方式,一个是经过添加Formatter,一个是添加Converter,二者区别不大,SpingMVC内部处理Formatter时也是包装了一层Converter。同时这里值得注意的是,Formatter和Converter是在SpringMVC使用默认参数解析器状况下使用的,若是你自定义了参数解析器,那么其接管的参数,转换规则由自定义参数解析器里面的逻辑来肯定。app

另外主要被应用于form表单参数或query参数字段,Json传参不是用这个,Json传参默认参数解析器是:RequestResponseBodyMethodProcessor,针对请求头或响应头为Content-Type=application/json,调用的消息转换器会用Jackson的ObjectMapper来序列化或反序列化,因此若是是JSON传参,配置这个东西没有用。cors

1.配置Formatter

以配置一个LocalDateTime类与字符串之间的转换为例:ide

首先新建一个类LocalDateTimeFormatter以下:post

public class LocalDateTimeFormatter implements Formatter<LocalDateTime> {
    private static final DateTimeFormatter dateTimeFormatter =  DateTimeFormatter.ofPattern("yyyy-MM-dd HH:ss:mm");
    @Override
    public LocalDateTime parse(String s, Locale locale) throws ParseException {
        return LocalDateTime.parse(s, dateTimeFormatter);
    }

    @Override
    public String print(LocalDateTime localDateTime, Locale locale) {
        return dateTimeFormatter.format(localDateTime);
    }
}

其中parse方法主要是将字符串转换为对象的逻辑,print方法是将对象转换为字符串的逻辑。

而后注册该Formatter,在MyWebConfig重写public void addFormatters(FormatterRegistry registry) 方法:

@Override
    public void addFormatters(FormatterRegistry registry) {
        registry.addFormatter(new LocalDateTimeFormatter());
        super.addFormatters(registry);
    }

这样,当不是json传参的时候,默认状况下会使用这个自定义的格式化器进行字符串和对象的转换。

2.配置Converter

通常状况下咱们使用Formatter替代Converter,但有时候也会对系统默认的StringHttpMessageConverter进行覆盖,修改编码格式为UTF-8,处理contentType为text/plain的消息与String对象的转换。如在MyWebConfig重写方法void configureMessageConverters(List<HttpMessageConverter<?>> converters):

@Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        converters.add(new StringHttpMessageConverter(StandardCharsets.UTF_8));
        super.extendMessageConverters(converters);
    }

##(三)配置静态资源映射

配置静态资源重写的方法为:void addResourceHandlers(ResourceHandlerRegistry registry),如重写方法为:

@Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/upload/**").addResourceLocations("classpath:/upload/");
        super.addResourceHandlers(registry);
    }

其中addResourceHandler("/upload/**").addResourceLocations("classpath:/upload/")的意思表示将URL:项目访问url+upload/xxx映射到classpath下的upload目录里面名为XXX的静态资源,其中addResourceLocations参数为变长参数,能够映射多个路径,也能够前面加'file:',映射磁盘上任意目录,如:file:/D://upload/,表示映射到d盘的upload目录。

(四)配置过滤器

添加过滤器只须要注册一个FilterRegistrationBean类对象到spring容器便可,如在测试环境注册一个容许跨域的过滤器:

@Conditional(value = {TestCondition.class})
    @Bean
    public FilterRegistrationBean corsFilter() {
        UrlBasedCorsConfigurationSource urlBasedCorsConfigurationSource =
                new UrlBasedCorsConfigurationSource();
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        corsConfiguration.addAllowedOrigin("*");
        corsConfiguration.addAllowedHeader("*");
        corsConfiguration.addAllowedMethod("*");
        urlBasedCorsConfigurationSource.registerCorsConfiguration("/**", corsConfiguration);
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
        filterRegistrationBean.setOrder(10);
        filterRegistrationBean.setFilter(new CorsFilter(urlBasedCorsConfigurationSource));
        filterRegistrationBean.setName("corsFilter");
        filterRegistrationBean.addUrlPatterns("/*");
        return filterRegistrationBean;
    }

@Conditional注解标识在上面表示在测试环境即引用的aplication-test.yml|properties,这里的value应该传入一个org.springframework.context.annotation.Condition接口实现类的Class对象。这里传入的是TestCondition。代码以下:

@Override
    public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
        Environment environment = conditionContext.getEnvironment();
        String[] activeProfiles = environment.getActiveProfiles();
        if (null != activeProfiles) {
            for (String x : activeProfiles) {
                if ("test".equals(x)) {
                    return true;
                }
            }
        }
        return false;
    }

另外对于自定义的过滤器,常规操做以下:

  • 继承OncePerRequestFilter抽象类,实现doFilterInternal方法。
  • 将这个Filter对象注入到filterRegistrationBean,并配置其余信息,如order,已通过滤的Url。

如:

@Bean
    public FilterRegistrationBean myFilter() {
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
        filterRegistrationBean.setFilter(new MyFilter());
        //order越小,优先级越高
        filterRegistrationBean.setOrder(1);
        filterRegistrationBean.addUrlPatterns("/*");
        filterRegistrationBean.setName("myFilter");
        return filterRegistrationBean;
    }

(四)配置拦截器

拦截器与过滤器的区别在于过滤器的优先级比拦截器高,Filter是做用于Servlet前,而Interceptor则相对于Filter更靠后一点。另外Filter不可使用IOC容器资源,Interceptor则能够。过滤器能完成的功能,经过Interceptor均可以完成,一般状况下,推荐使用Interceptor。

配置拦截器的步骤是:

1.建立类继承HandlerInterceptorAdapter。

HandlerInterceptorAdapter有三个方法能够重写,未重写前不作任何处理。三个方法是:

//在业务处理器处理请求以前被执行
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)throws Exception {
        return true;
}
//在业务处理器处理请求返回响应以前执行
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)throws Exception {
}
//返回响应以后执行
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)throws Exception {
}

2.注册拦截器

在MyWebConfig类重写方法void addInterceptors(InterceptorRegistry registry),如:

@Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 能够多个拦截器组成一个拦截器链
        // addPathPatterns 用于添加拦截规则
        // excludePathPatterns 用于排除拦截
        registry.addInterceptor(new MyInterceptor())
                .addPathPatterns("/**")
                .excludePathPatterns("/swagger*/**");
        super.addInterceptors(registry);
    }

3、小结

以上就是基于Springboot下的SpringMVC经常使用配置方法,基本上能知足经常使用项目配置需求,其余就暂时不做了解了。

相关文章
相关标签/搜索