Sprinboot中配置SpringMVC主要是繼承WebMvcConfigurerAdapter(1.x版本)或者WebMvcConfigurationSupport(2.x版本)。此次主要介紹下web應用的一些經常使用配置。前端
參數解析器的做用,通俗來講,參數解析器的做用是將請求中的參數映射到咱們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
以配置一個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傳參的時候,默認狀況下會使用這個自定義的格式化器進行字符串和對象的轉換。
通常狀況下咱們使用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; }
另外對於自定義的過濾器,常規操做以下:
如:
@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。
配置攔截器的步驟是:
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 { }
在MyWebConfig類重寫方法void addInterceptors(InterceptorRegistry registry),如:
@Override public void addInterceptors(InterceptorRegistry registry) { // 能夠多個攔截器組成一個攔截器鏈 // addPathPatterns 用於添加攔截規則 // excludePathPatterns 用於排除攔截 registry.addInterceptor(new MyInterceptor()) .addPathPatterns("/**") .excludePathPatterns("/swagger*/**"); super.addInterceptors(registry); }
以上就是基於Springboot下的SpringMVC經常使用配置方法,基本上能知足經常使用項目配置需求,其餘就暫時不做了解了。