SpringBoot中可以通过实现WebMvcConfigurer接口来自定义Handler,Interceptor,ViewResolver,MessageConverter
Interceptor 实现拦截器
addInterceptor:需要一个实现HandlerInterceptor接口的拦截器实例
addPathPatterns:用于设置拦截器的过滤路径规则;addPathPatterns("/**")对所有请求都拦截
excludePathPatterns:用于设置不需要拦截的过滤规则
拦截器主要用途:进行用户登录状态的拦截,日志的拦截等
addResourceHandlers 自定义静态资源映射目录
addResoureHandler:指的是对外暴露的访问路径
addResourceLocations:指的是内部文件放置的目录
addCorsMappings:跨域(但是使用此方法配置之后再使用自定义拦截器时跨域相关配置就会失效)
registry.addMapping("/**")// 允许跨域访问的路径
.allowedOrigins("*")// 允许跨域访问的源
.allowedMethods("POST", "GET", "PUT", "OPTIONS", "DELETE")// 允许请求方法
.maxAge(168000)// 预检间隔时间
.allowedHeaders("*")// 允许头部设置
.allowCredentials(true); // 是否发送cookie
addViewControllers:页面跳转
例如
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/toLogin").setViewName("login");
}
configureDefaultServletHandling:默认静态资源处理器
会注册一个默认的Handler:DefaultServletHttpRequestHandler,
DispatcherServlet破坏了Servlet的一个特性(根目录下的文件可以直接访问),DefaultServletHttpRequestHandler是帮助回归这个特性的
例如
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
configurer.enable("defaultServletName");
}
configureViewResolvers:视图解析器,配置视图解析器
例如
@Bean
public InternalResourceViewResolver resourceViewResolver()
{
InternalResourceViewResolver internalResourceViewResolver = new InternalResourceViewResolver();
//请求视图文件的前缀地址
internalResourceViewResolver.setPrefix("/WEB-INF/jsp/");
//请求视图文件的后缀
internalResourceViewResolver.setSuffix(".jsp");
return internalResourceViewResolver;
}
public void configureViewResolvers(ViewResolverRegistry registry) {
super.configureViewResolvers(registry);
registry.viewResolver(resourceViewResolver());
/*registry.jsp("/WEB-INF/jsp/",".jsp");*/
}
configureContentNegotiation:配置内容裁决的一些参数
configureMessageConverters:信息转换器
例如
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
//调用父类的配置
super.configureMessageConverters(converters);
//创建fastJson消息转换器
FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter();
//创建配置类
FastJsonConfig fastJsonConfig = new FastJsonConfig();
//修改配置返回内容的过滤
fastJsonConfig.setSerializerFeatures(
SerializerFeature.DisableCircularReferenceDetect,
SerializerFeature.WriteMapNullValue,
SerializerFeature.WriteNullStringAsEmpty
);
fastConverter.setFastJsonConfig(fastJsonConfig);
//将fastjson添加到视图消息转换器列表内
converters.add(fastConverter);
}
拦截器
可以实现HandlerInterceptor接口作为拦截器实例用于
日志记录,可以记录请求信息的日志,以便进行信息监控、信息统计等。
权限检查:如登陆检测,进入处理器检测是否登陆,如果没有直接返回到登陆页面。
性能监控:典型的是慢日志。
例如:在preHandle记录方法开始时间,在afterCompletion记录方法结束时间来统计方法耗时
public interface HandlerInterceptor {
/**
* 预处理回调方法,实现处理器的预处理(如检查登陆),第三个参数为响应的处理器,自定义Controller
* 返回值:true表示继续流程(如调用下一个拦截器或处理器);false表示流程中断
(如登录检查失败),不会继续调用其他的拦截器或处理器,此时我们需要通过response来产生响应;
*/
boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;
/**
* 后处理回调方法,实现处理器的后处理(但在渲染视图之前),此时我们可以
通过modelAndView(模型和视图对象)对模型数据进行处理或对视图进行处理,modelAndView也可能为null。
*/
void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception;
/**
* 整个请求处理完毕回调方法,即在视图渲染完毕时回调,如性能监控中我们可以在此记录结束时间并输
出消耗时间,还可以进行一些资源清理,类似于try-catch-finally中的finally,但仅调用处理器执行链中
*/
void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception;
}
拦截器是单例,因此不管用户请求多少次都只有一个拦截器实现,即线程不安全,解决方案是使用ThreadLocal,它是线程绑定的变量,提供线程局部变量
例如
public class ExampleInterceptor implements HandlerInterceptor {
//static修饰的属性强调它们只有一个,final修饰的属性表明是一个常数(创建后不能被修改),static final修饰的属性表示一旦给值,就不可修改,并且可以通过类名访问
private static final ThreadLocal<String> exampleThreadLocal = new NamedThreadLocal<String>("ThreadLocalExample");
@Override
public boolean preHandle(HttpServletRequest request,HttpServletResponse response, Object handler)throws Exception{
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
exampleThreadLocal.set(df.format(new Date()));
return true;
}
@Override
public void afterCompletion(HttpServletRequest request,HttpServletResponse response, Object handler, Exception ex)throws Exception{
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println("方法开始时间:"+exampleThreadLocal.get());
System.out.println("方法结束时间:"+df.format(new Date()));
}
}
用于个人学习记录
转载自