定义拦截器Slf4jComponentpublicclassRememberAuthenticationInterceptorimplementsHandlerInterceptor{AutowiredprivateSysUserServiceuserSOverridepublicbooleanpreHandle(HttpServletRequestrequest,HttpServletResponseresponse,Objecthandler)throwsException{dosomthing。。。SubjectsubjectSecurityUtils。getSubject();if(subject。isAuthenticated()){}Sessionsessionsubject。getSession(true);if(session。getAttribute(SessionConst。USERSESSIONKEY)!null){}if(!subject。isRemembered()){log。warn(未设置记住我,跳转到登录页。。。);response。sendRedirect(request。getContextPath()passportlogin);}try{LonguserIdLong。parseLong(subject。getPrincipal()。toString());UseruseruserService。getByPrimaryKey(userId);UsernamePasswordTokentokennewUsernamePasswordToken(user。getUsername(),PasswordUtil。decrypt(user。getPassword(),user。getUsername()),true);subject。login(token);session。setAttribute(SessionConst。USERSESSIONKEY,user);log。info(〔{}〕已自动登录,user。getUsername());}catch(Exceptione){log。error(自动登录失败,e);response。sendRedirect(request。getContextPath()passportlogin);}}}配置拦截器ConfigurationpublicclassWebMvcConfigimplementsWebMvcConfigurer{AutowiredprivateRememberAuthenticationInterceptorrememberAuthenticationIOverridepublicvoidaddInterceptors(InterceptorRegistryregistry){注册添加拦截器registry。addInterceptor(rememberAuthenticationInterceptor)。excludePathPatterns(passport,error,assets,getKaptcha,websocket,favicon。ico)。addPathPatterns();}} 完成详解HandlerInterceptor和WebMvcConfigurerHandlerInterceptor简介 应用场景 1、日志记录,可以记录请求信息的日志,以便进行信息监控、信息统计等。 2、权限检查:如登陆检测,进入处理器检测是否登陆,如果没有直接返回到登陆页面。 3、性能监控:典型的是慢日志。 拦截器我想大家都并不陌生,最常用的登录拦截、或是权限校验、或是防重复提交、或是根据业务像12306去校验购票时间,总之可以去做很多的事情。 定义一个Interceptor非常简单方式也有几种,我这里简单列举两种 1、类要实现Spring的HandlerInterceptor接口 2、类继承实现了HandlerInterceptor接口的类,例如已经提供的实现了HandlerInterceptor接口的抽象类HandlerInterceptorAdapter2、HandlerInterceptor方法介绍booleanpreHandle(HttpServletRequestrequest,HttpServletResponseresponse,Objecthandler)throwsEvoidpostHandle(HttpServletRequestrequest,HttpServletResponseresponse,Objecthandler,ModelAndViewmodelAndView)throwsEvoidafterCompletion(HttpServletRequestrequest,HttpServletResponseresponse,Objecthandler,Exceptionex)throwsE preHandle:在业务处理器处理请求之前被调用。预处理,可以进行编码、安全控制、权限校验等处理; postHandle:在业务处理器处理请求执行完成后,生成视图之前执行。后处理(调用了Service并返回ModelAndView,但未进行页面渲染),有机会修改ModelAndView(这个博主就基本不怎么用了); afterCompletion:在DispatcherServlet完全处理完请求后被调用,可用于清理资源等。返回处理(已经渲染了页面); 这样在我们业务中比如要记录系统日志,日志肯定是在afterCompletion之后记录的,否则中途失败了,也记录了,那就扯淡了。一定是程序正常跑完后,我们记录下那些对数据库做个增删改的操作日志进数据库。所以我们只需要继承HandlerInterceptorAdapter,并重写afterCompletion一个方法即可,因为preHandle默认是true。 运行流程总结如下: 1、拦截器执行顺序是按照Spring配置文件中定义的顺序而定的。 2、会先按照顺序执行所有拦截器的preHandle方法,一直遇到returnfalse为止,比如第二个preHandle方法是returnfalse,则第三个以及以后所有拦截器都不会执行。若都是returntrue,则按顺序加载完preHandle方法。 3、然后执行主方法(自己的controller接口),若中间抛出异常,则跟returnfalse效果一致,不会继续执行postHandle,只会倒序执行afterCompletion方法。 4、在主方法执行完业务逻辑(页面还未渲染数据)时,按倒序执行postHandle方法。若第三个拦截器的preHandle方法returnfalse,则会执行第二个和第一个的postHandle方法和afterCompletion(postHandle都执行完才会执行这个,也就是页面渲染完数据后,执行after进行清理工作)方法。(postHandle和afterCompletion都是倒序执行) WebMvcConfigurer简介 WebMvcConfigurer配置类其实是Spring内部的一种配置方式,采用JavaBean的形式来代替传统的xml配置文件形式进行针对框架个性化定制,可以自定义一些Handler,Interceptor,ViewResolver,MessageConverter。基于javabased方式的springmvc配置,需要创建一个配置类并实现WebMvcConfigurer接口; 在SpringBoot1。5版本都是靠重写WebMvcConfigurerAdapter的方法来添加自定义拦截器,消息转换器等。SpringBoot2。0后,该类被标记为Deprecated(弃用)。官方推荐直接实现WebMvcConfigurer或者直接继承WebMvcConfigurationSupport,方式一实现WebMvcConfigurer接口(推荐),方式二继承WebMvcConfigurationSupport类WebMvcConfigurer接口publicinterfaceWebMvcConfigurer{voidconfigurePathMatch(PathMatchConfigurervar1);voidconfigureContentNegotiation(ContentNegotiationConfigurervar1);voidconfigureAsyncSupport(AsyncSupportConfigurervar1);voidconfigureDefaultServletHandling(DefaultServletHandlerConfigurervar1);voidaddFormatters(FormatterRegistryvar1);voidaddInterceptors(InterceptorRegistryvar1);voidaddResourceHandlers(ResourceHandlerRegistryvar1);voidaddCorsMappings(CorsRegistryvar1);voidaddViewControllers(ViewControllerRegistryvar1);voidconfigureViewResolvers(ViewResolverRegistryvar1);voidaddArgumentResolvers(ListHandlerMethodArgumentResolvervar1);voidaddReturnValueHandlers(ListHandlerMethodReturnValueHandlervar1);voidconfigureMessageConverters(ListHttpMessageC?var1);voidextendMessageConverters(ListHttpMessageC?var1);voidconfigureHandlerExceptionResolvers(ListHandlerExceptionResolvervar1);voidextendHandlerExceptionResolvers(ListHandlerExceptionResolvervar1);ValidatorgetValidator();MessageCodesResolvergetMessageCodesResolver();} 其中常用的方法:拦截器配置voidaddInterceptors(InterceptorRegistryvar1);视图跳转控制器voidaddViewControllers(ViewControllerRegistryregistry);静态资源处理voidaddResourceHandlers(ResourceHandlerRegistryregistry);默认静态资源处理器voidconfigureDefaultServletHandling(DefaultServletHandlerConfigurerconfigurer);这里配置视图解析器voidconfigureViewResolvers(ViewResolverRegistryregistry);配置内容裁决的一些选项voidconfigureContentNegotiation(ContentNegotiationConfigurerconfigurer);解决跨域问题publicvoidaddCorsMappings(CorsRegistryregistry);addInterceptors:拦截器(常用)addInterceptor:需要一个实现HandlerInterceptor接口的拦截器实例addPathPatterns:用于设置拦截器的过滤路径规则;addPathPatterns()对所有请求都拦截excludePathPatterns:用于设置不需要拦截的过滤规则拦截器主要用途:进行用户登录状态的拦截,日志的拦截等。OverridepublicvoidaddInterceptors(InterceptorRegistryregistry){super。addInterceptors(registry);registry。addInterceptor(newTestInterceptor())。addPathPatterns()。excludePathPatterns(emptoLogin,emplogin,js,css,images);}addViewControllers:页面跳转 以前写SpringMVC的时候,如果需要访问一个页面,必须要写Controller类,然后再写一个方法跳转到页面,感觉好麻烦,其实重写WebMvcConfigurer中的addViewControllers方法即可达到效果了OverridepublicvoidaddViewControllers(ViewControllerRegistryregistry){registry。addViewController(toLogin)。setViewName(login);} 值的指出的是,在这里重写addViewControllers方法,并不会覆盖WebMvcAutoConfiguration(Springboot自动配置)中的addViewControllers(在此方法中,SpringBoot将映射至index。html),这也就意味着自己的配置和SpringBoot的自动配置同时有效,这也是我们推荐添加自己的MVC配置的方式。addResourceHandlers:静态资源 比如,我们想自定义静态资源映射目录的话,只需重写addResourceHandlers方法即可。 注:如果继承WebMvcConfigurationSupport类实现配置时必须要重写该方法,具体见其它文章ConfigurationpublicclassMyWebMvcConfigurerAdapterimplementsWebMvcConfigurer{配置静态访问资源paramregistryOverridepublicvoidaddResourceHandlers(ResourceHandlerRegistryregistry){registry。addResourceHandler(my)。addResourceLocations(classpath:my);}}addResoureHandler:指的是对外暴露的访问路径addResourceLocations:指的是内部文件放置的目录configureDefaultServletHandling:默认静态资源处理器 此时会注册一个默认的Handler:DefaultServletHttpRequestHandler,这个Handler也是用来处理静态文件的,它会尝试映射。当DispatcherServelt映射时(和是有区别的),并且没有找到合适的Handler来处理请求时,就会交给DefaultServletHttpRequestHandler来处理。注意:这里的静态资源是放置在web根目录下,而非WEBINF下。 可能这里的描述有点不好懂(我自己也这么觉得),所以简单举个例子,例如:在webroot目录下有一个图片:1。png我们知道Servelt规范中web根目录(webroot)下的文件可以直接访问的,但是由于DispatcherServlet配置了映射路径是:,它几乎把所有的请求都拦截了,从而导致1。png访问不到,这时注册一个DefaultServletHttpRequestHandler就可以解决这个问题。其实可以理解为DispatcherServlet破坏了Servlet的一个特性(根目录下的文件可以直接访问),DefaultServletHttpRequestHandler是帮助回归这个特性的。onfigureViewResolvers:视图解析器 这个方法是用来配置视图解析器的,该方法的参数ViewResolverRegistry是一个注册器,用来注册你想自定义的视图解析器等。ViewResolverRegistry常用的几个方法:配置请求视图映射returnBeanpublicInternalResourceViewResolverresourceViewResolver(){InternalResourceViewResolverinternalResourceViewResolvernewInternalResourceViewResolver();请求视图文件的前缀地址internalResourceViewResolver。setPrefix(WEBINFjsp);请求视图文件的后缀internalResourceViewResolver。setSuffix(。jsp);returninternalResourceViewR}视图配置paramregistryOverridepublicvoidconfigureViewResolvers(ViewResolverRegistryregistry){super。configureViewResolvers(registry);registry。viewResolver(resourceViewResolver());registry。jsp(WEBINFjsp,。jsp);}configureContentNegotiation:配置内容裁决的一些参数addCorsMappings:跨域OverridepublicvoidaddCorsMappings(CorsRegistryregistry){super。addCorsMappings(registry);registry。addMapping(cors)。allowedHeaders()。allowedMethods(POST,GET)。allowedOrigins();}configureMessageConverters:信息转换器消息内容转换配置配置fastJson返回json转换paramconvertersOverridepublicvoidconfigureMessageConverters(ListHttpMessageC?converters){调用父类的配置super。configureMessageConverters(converters);创建fastJson消息转换器FastJsonHttpMessageConverterfastConverternewFastJsonHttpMessageConverter();创建配置类FastJsonConfigfastJsonConfignewFastJsonConfig();修改配置返回内容的过滤fastJsonConfig。setSerializerFeatures(SerializerFeature。DisableCircularReferenceDetect,SerializerFeature。WriteMapNullValue,SerializerFeature。WriteNullStringAsEmpty);fastConverter。setFastJsonConfig(fastJsonConfig);将fastjson添加到视图消息转换器列表内converters。add(fastConverter);}