Security:权限管理
- 常用权限拦截器
- SecurityContextPersistenceFilter
- 以前是HttpSesstionContextIntegrationFilter,位于过滤器的顶端,是第一个起作用的过滤器
- 第一个用途:在执行其他过滤器之前,率先判断用户的session是否已经存在了一个spring security上下文的securityContext,如果存在,就把securityContext拿出来,放在securityContextHolder中,供security的其他部分使用。如果不存在,就创建一个securityContext出来,放在securityContextHolder中,供security的其他部分使用。
- 第二个用途:在所有过滤器执行完毕后,清空securityContextHolder中的内容,因为securityContextHolder是基于ThreadLocal的,如果不清空,会受到服务器线程池机制的影响。
- ThreadLocal存放的值是线程内共享的,线程间互斥的,主要用于线程内共享一些数据,避免通过参数来传递。这样处理后,能够解决实际中的一些并发问题。ThreadLocalMap是ThreadLocal的一个内部类,是不对外使用的。当使用ThreadLocal存值时,首先获取到当前线程对象,然后获取到当前线程本地对象,本地变量map,最后将当前使用的所有local和传入的值放在map中。也就是说ThreadLocalMap中的key是ThreadLocal对象。这样,每个线程都对应一个本地的map,所以,一个线程可以存在多个线程本地变量。
- ThreadLocal是解决线程并发问题的一个很好的思路,通过对每个线程提供一个独立的变量副本,解决线程并发访问变量的一个冲突问题
- 当一个线程结束的时候,记得把ThreadLocal里的变量移除掉remove();
- SecurityContextPersistenceFilter
- LogoutFilter
- 只处理注销请求。在用户发送注销请求时,销毁用户的session,清空securityContextHolder,重定向到注销成功页面
- AbstractAuthenticationProcessingFilter
- 处理form登录的过滤器,与form登录有关的操作都在此进行。
- DefaultLoginPageGeneratingFilter
- 用来生成一个默认的登录页面,默认的访问地址为spring_security_login,这个登录页面虽然支持用户输入用户名密码,也支持remember me等功能,但是因为太难看了,只能在演示时做个样子,不能直接在实际项目中使用
- BasicAutenticationFilter
- 用来进行basic验证
- SecurityContextHolderAwareRequestFilter
- 用来包装客户的请求,目的是在原来请求的基础上,为后续程序提供一些额外的数据,比如getRomoteUser时,直接返回当前登录的用户名
- RememberMeAuthenticationFilter
- 实现Remember me功能,当用户cookie中存在remember me标记时,它会根据标记自动实现用户登录,并创建securityContext,授予对应的权限。spring security中的remember me依赖cookie实现,用户在登录时选择remember me,系统就会在登录成功后为用户生成一个唯一的标识,并将这个标识保存进cookie中,我们可以通过浏览器查看用户电脑中的cookie
- AnonymousAutenticationFilter
- 当用户没有登录时,默认为用户分配匿名用户的权限
- ExceptionTranslationFilter
- 处理filterSecurityInterceptor中抛出的异常,然后将请求重定向到对应页面,或返回应用的错误代码
- SessionManagementFilter
- 在用户登录成功之后,销毁用户的当前session,并重新生成一个session
- filterSecurityInterceptor
- 用户的权限控制都包含在这个过滤器中
- 第一个功能,如果用户尚未登录,抛出尚未认证的异常
- 第二个功能,如果用户已登录,但是没有访问当前资源的权限,会抛出拒绝访问的异常
- 第三个功能,如果用户已登录,也具有访问当前资源的权限,那么放行
- FilterChainProxy
- 按照顺序调用一组filter,使他们既能完成验证授权的本职工作,又能相应spring Ioc的功能来很方便地得到其他依赖的资源
- 将用户、权限、资源(url)采用数据库存储
- 自定义过滤器,代替原有的 FilterSecurityInterceptor
- 自定义实现 UserDetailsService、AccessDecisionManager和InvocationSecurityMetadataSourceService,并在配置文件进行相应的配置
- 用户表(base_user)
code | type | length |
---|---|---|
ID | varchar | 32 |
USER_NAME | varchar | 50 |
USER_PASSWORD | varchar | 100 |
NIKE_NAME | varchar | 50 |
STATUS | int | 11 |
- 用户角色表(base_user_role)
code type length ID varchar 32 USER_ID varchar 32 ROLE_ID varchar 32
- 角色表(base_role)
code type length ID varchar 32 ROLE_CODE varchar 32 ROLE_NAME varchar 64
- 角色菜单表(base_role_menu)
code type length ID varchar 32 ROLE_ID varchar 32 MENU_ID varchar 32
- 菜单表(base_menu)
code type length ID varchar 32 MENU_URL varchar 120 MENU_SEQ varchar 120 MENU_PARENT_ID varchar 32 MENU_NAME varchar 50 MENU_ICON varchar 20 MENU_ORDER int 11 IS_LEAF varchar 20
实现主要配置类
实现AbstractAuthenticationProcessingFilter
用于用户表单验证,内部调用了authenticationManager完成认证,根据认证结果执行successfulAuthentication或者unsuccessfulAuthentication,无论成功失败,一般的实现都是转发或者重定向等处理。
@Override public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException { if (postOnly && !request.getMethod().equals("POST")) { throw new AuthenticationServiceException( "Authentication method not supported: " + request.getMethod()); } //获取表单中的用户名和密码 String username = obtainUsername(request); String password = obtainPassword(request); if (username == null) { username = ""; } if (password == null) { password = ""; } username = username.trim(); //组装成username+password形式的token UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken( username, password); // Allow subclasses to set the "details" property setDetails(request, authRequest); //交给内部的AuthenticationManager去认证,并返回认证信息 return this.getAuthenticationManager().authenticate(authRequest); }
AuthenticationManager
AuthenticationManager是一个用来处理认证(Authentication)请求的接口。在其中只定义了一个方法authenticate(),该方法只接收一个代表认证请求的Authentication对象作为参数,如果认证成功,则会返回一个封装了当前用户权限等信息的Authentication对象进行返回。Authentication authenticate(Authentication authentication) throws AuthenticationException;
在Spring Security中,AuthenticationManager的默认实现是ProviderManager,而且它不直接自己处理认证请求,而是委托给其所配置的AuthenticationProvider列表,然后会依次使用每一个AuthenticationProvider进行认证,如果有一个AuthenticationProvider认证后的结果不为null,则表示该AuthenticationProvider已经认证成功,之后的AuthenticationProvider将不再继续认证。然后直接以该AuthenticationProvider的认证结果作为ProviderManager的认证结果。如果所有的AuthenticationProvider的认证结果都为null,则表示认证失败,将抛出一个ProviderNotFoundException。
校验认证请求最常用的方法是根据请求的用户名加载对应的UserDetails,然后比对UserDetails的密码与认证请求的密码是否一致,一致则表示认证通过。
Spring Security内部的DaoAuthenticationProvider就是使用的这种方式。其内部使用UserDetailsService来负责加载UserDetails。在认证成功以后会使用加载的UserDetails来封装要返回的Authentication对象,加载的UserDetails对象是包含用户权限等信息的。认证成功返回的Authentication对象将会保存在当前的SecurityContext中。
实现UserDetailsService
UserDetailsService只定义了一个方法 loadUserByUsername,根据用户名可以查到用户并返回的方法。
@Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { logger.debug("权限框架-加载用户"); List<GrantedAuthority> auths = new ArrayList<>(); BaseUser baseUser = new BaseUser(); baseUser.setUserName(username); baseUser = baseUserService.selectOne(baseUser); if (baseUser == null) { logger.debug("找不到该用户 用户名:{}", username); throw new UsernameNotFoundException("找不到该用户!"); } if(baseUser.getStatus()==2) { logger.debug("用户被禁用,无法登陆 用户名:{}", username); throw new UsernameNotFoundException("用户被禁用!"); } List<BaseRole> roles = baseRoleService.selectRolesByUserId(baseUser.getId()); if (roles != null) { //设置角色名称 for (BaseRole role : roles) { SimpleGrantedAuthority authority = new SimpleGrantedAuthority(role.getRoleCode()); auths.add(authority); } } return new org.springframework.security.core.userdetails.User(baseUser.getUserName(), baseUser.getUserPassword(), true, true, true, true, auths); }
实现AbstractSecurityInterceptor
访问url时,会被AbstractSecurityInterceptor拦截器拦截,然后调用FilterInvocationSecurityMetadataSource的方法来获取被拦截url所需的全部权限,再调用授权管理器AccessDecisionManager鉴权。
public class CustomSecurityInterceptor extends AbstractSecurityInterceptor implements Filter { private FilterInvocationSecurityMetadataSource securityMetadataSource; @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { FilterInvocation fi = new FilterInvocation(request, response, chain); invoke(fi); } @Override public void destroy() { } @Override public Class<?> getSecureObjectClass() { return FilterInvocation.class; } @Override public SecurityMetadataSource obtainSecurityMetadataSource() { return this.securityMetadataSource; } public void invoke(FilterInvocation fi) throws IOException { InterceptorStatusToken token = super.beforeInvocation(fi); try { fi.getChain().doFilter(fi.getRequest(), fi.getResponse()); } catch (ServletException e) { super.afterInvocation(token, null); } } public FilterInvocationSecurityMetadataSource getSecurityMetadataSource() { return securityMetadataSource; } public void setSecurityMetadataSource(FilterInvocationSecurityMetadataSource securityMetadataSource) { this.securityMetadataSource = securityMetadataSource; } }
FilterInvocationSecurityMetadataSource 获取所需权限
@Override public Collection<ConfigAttribute> getAttributes(Object object) throws IllegalArgumentException { //获取当前访问url String url = ((FilterInvocation) object).getRequestUrl(); int firstQuestionMarkIndex = url.indexOf("?"); if (firstQuestionMarkIndex != -1) { url = url.substring(0, firstQuestionMarkIndex); } List<ConfigAttribute> result = new ArrayList<>(); try { //设置不拦截 if (propertySourceBean.getProperty("security.ignoring") != null) { String[] paths = propertySourceBean.getProperty("security.ignoring").toString().split(","); //判断是否符合规则 for (String path: paths) { String temp = StringUtil.clearSpace(path); if (matcher.match(temp, url)) { return SecurityConfig.createList("ROLE_ANONYMOUS"); } } } //如果不是拦截列表里的, 默认需要ROLE_ANONYMOUS权限 if (!isIntercept(url)) { return SecurityConfig.createList("ROLE_ANONYMOUS"); } //查询数据库url匹配的菜单 List<BaseMenu> menuList = baseMenuService.selectMenusByUrl(url); if (menuList != null && menuList.size() > 0) { for (BaseMenu menu : menuList) { //查询拥有该菜单权限的角色列表 List<BaseRole> roles = baseRoleService.selectRolesByMenuId(menu.getId()); if (roles != null && roles.size() > 0) { for (BaseRole role : roles) { ConfigAttribute conf = new SecurityConfig(role.getRoleCode()); result.add(conf); } } } } } catch (Exception e) { e.printStackTrace(); } return result; } /** * 判断是否需要过滤 * @param url * @return */ public boolean isIntercept(String url) { String[] filterPaths = propertySourceBean.getProperty("security.intercept").toString().split(","); for (String filter: filterPaths) { if (matcher.match(StringUtil.clearSpace(filter), url) & !matcher.match(indexUrl, url)) { return true; } } return false; }
AccessDecisionManager 鉴权
@Override public void decide(Authentication authentication, Object o, Collection<ConfigAttribute> collection) throws AccessDeniedException, InsufficientAuthenticationException { if (collection == null) { return; } for (ConfigAttribute configAttribute : collection) { String needRole = configAttribute.getAttribute(); for (GrantedAuthority ga : authentication.getAuthorities()) { if (needRole.trim().equals(ga.getAuthority().trim()) || needRole.trim().equals("ROLE_ANONYMOUS")) { return; } } } throw new AccessDeniedException("无权限!"); }
配置 WebSecurityConfigurerAdapter
/** * spring-security配置 */ @Configuration @EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter { private final Logger logger = LoggerFactory.getLogger(this.getClass()); @Autowired private UserDetailsService userDetailsService; @Autowired private PropertySource propertySourceBean; @Override protected void configure(HttpSecurity http) throws Exception { logger.debug("权限框架配置"); String[] paths = null; //设置不拦截 if (propertySourceBean.getProperty("security.ignoring") != null) { paths = propertySourceBean.getProperty("security.ignoring").toString().split(","); paths = StringUtil.clearSpace(paths); } //设置过滤器 http // 根据配置文件放行无需验证的url .authorizeRequests().antMatchers(paths).permitAll() .and() .httpBasic() // 配置验证异常处理 .authenticationEntryPoint(getCustomLoginAuthEntryPoint()) // 配置登陆过滤器 .and().addFilterAt(getCustomLoginFilter(), UsernamePasswordAuthenticationFilter.class) // 配置 AbstractSecurityInterceptor .addFilterAt(getCustomSecurityInterceptor(), FilterSecurityInterceptor.class) // 登出成功处理 .logout().logoutSuccessHandler(getCustomLogoutSuccessHandler()) // 关闭csrf .and().csrf().disable() // 其他所有请求都需要验证 .authorizeRequests().anyRequest().authenticated() // 配置登陆url, 登陆页面并无需验证 .and().formLogin().loginProcessingUrl("/login").loginPage("/login.ftl").permitAll() // 登出 .and().logout().logoutUrl("/logout").permitAll(); logger.debug("配置忽略验证url"); } @Autowired @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.authenticationProvider(getDaoAuthenticationProvider()); } /** * spring security 配置 * @return */ @Bean public CustomLoginAuthEntryPoint getCustomLoginAuthEntryPoint() { return new CustomLoginAuthEntryPoint(); } /** * 用户验证 * @return */ @Bean public DaoAuthenticationProvider getDaoAuthenticationProvider() { DaoAuthenticationProvider provider = new DaoAuthenticationProvider(); provider.setUserDetailsService(userDetailsService); provider.setHideUserNotFoundExceptions(false); provider.setPasswordEncoder(new BCryptPasswordEncoder()); return provider; } /** * 登陆 * @return */ @Bean public CustomLoginFilter getCustomLoginFilter() { CustomLoginFilter filter = new CustomLoginFilter(); try { filter.setAuthenticationManager(this.authenticationManagerBean()); } catch (Exception e) { e.printStackTrace(); } filter.setAuthenticationSuccessHandler(getCustomLoginAuthSuccessHandler()); filter.setAuthenticationFailureHandler(new CustomLoginAuthFailureHandler()); return filter; } @Bean public CustomLoginAuthSuccessHandler getCustomLoginAuthSuccessHandler() { CustomLoginAuthSuccessHandler handler = new CustomLoginAuthSuccessHandler(); if (propertySourceBean.getProperty("security.successUrl")!=null){ handler.setAuthSuccessUrl(propertySourceBean.getProperty("security.successUrl").toString()); } return handler; } /** * 登出 * @return */ @Bean public CustomLogoutSuccessHandler getCustomLogoutSuccessHandler() { CustomLogoutSuccessHandler handler = new CustomLogoutSuccessHandler(); if (propertySourceBean.getProperty("security.logoutSuccessUrl")!=null){ handler.setLoginUrl(propertySourceBean.getProperty("security.logoutSuccessUrl").toString()); } return handler; } /** * 过滤器 * @return */ @Bean public CustomSecurityInterceptor getCustomSecurityInterceptor() { CustomSecurityInterceptor interceptor = new CustomSecurityInterceptor(); interceptor.setAccessDecisionManager(new CustomAccessDecisionManager()); interceptor.setSecurityMetadataSource(getCustomMetadataSourceService()); try { interceptor.setAuthenticationManager(this.authenticationManagerBean()); } catch (Exception e) { e.printStackTrace(); } return interceptor; } @Bean public CustomMetadataSourceService getCustomMetadataSourceService() { CustomMetadataSourceService sourceService = new CustomMetadataSourceService(); if (propertySourceBean.getProperty("security.successUrl")!=null){ sourceService.setIndexUrl(propertySourceBean.getProperty("security.successUrl").toString()); } return sourceService; } }
spring boot 拦截器、过滤器、监听器、定时器使用
一、application.java中配置
@EnableTransactionManagement
自动启用事务
@SpringBootApplication
@MapperScan(basePackages={"com.hxkj.waychat.dao"})
@ServletComponentScan
拦截器、过滤器、监听器的注解配置
二、监听器配置
package com.hxkj.waychat.intercept.listener;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.hxkj.waychat.core.config.Constant;
import com.hxkj.waychat.core.utils.PropertiesUtils;
@WebListener
public class ThymeleafServletContextListener implements ServletContextListener {
private static Logger logger = LoggerFactory.getLogger(ThymeleafServletContextListener.class);
@Override
public void contextDestroyed(ServletContextEvent arg0) {
logger.info("----------:ServletContext销毁");
}
@Override
public void contextInitialized(ServletContextEvent arg0) {
logger.info("----------:ServletContext初始化");
logger.info("----------:baseUrl:"+PropertiesUtils.getPropertiesValue(Constant.BASE_URL)+";fileUrl:"+PropertiesUtils.getPropertiesValue(Constant.FILE_URL));
arg0.getServletContext().setAttribute("baseUrl", PropertiesUtils.getPropertiesValue(Constant.BASE_URL));
arg0.getServletContext().setAttribute("fileUrl", PropertiesUtils.getPropertiesValue(Constant.FILE_URL));
}
}
三、过滤器配置
package com.hxkj.waychat.intercept.fliter;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/*@WebFilter(filterName="MyFilter",urlPatterns="/*")*/
public class MyFilter implements Filter {
private static Logger logger = LoggerFactory.getLogger(MyFilter.class);
@Override
public void destroy() {
logger.info("----------:过滤器销毁");
}
@Override
public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2)
throws IOException, ServletException {
logger.info("----------:过滤器执行内容");
arg2.doFilter(arg0, arg1);
}
@Override
public void init(FilterConfig arg0) throws ServletException {
logger.info("----------:过滤器初始化");
}
}
四、拦截器配置
1.spring boot拦截器默认有
HandlerInterceptorAdapter
AbstractHandlerMapping
UserRoleAuthorizationInterceptor
LocaleChangeInterceptor
ThemeChangeInterceptor
2.配置spring mvc的拦截器WebMvcConfigurerAdapter
public class WebAppConfig extends WebMvcConfigurerAdapter
3.实现添加拦截器方法
public void addInterceptors(InterceptorRegistry registry){
}
registry.addInterceptor可以通过此方法添加拦截器, 可以是spring提供的或者自己添加的
4.实例部分
public class WebAppConfig extends WebMvcConfigurerAdapter{
public static void main(String[] args) {
SpringApplication.run(WebAppConfig.class, args);
}
/**
* 配置拦截器
* @author lance
* @param registry
*/
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new UserSecurityInterceptor()).addPathPatterns("/user/**");
}
}
UserSecurityInterceptor代码
public class UserSecurityInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) throws Exception {
return true;
}
@Override
public void postHandle(HttpServletRequest request,
HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest request,
HttpServletResponse response, Object handler, Exception ex)
throws Exception {
}
}
五、定时器使用
@Component
public class Scheduler {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
@Scheduled(cron="0 0/1 * * * ?") //每分钟执行一次
public void statusCheck() {
logger.info("每分钟执行一次。开始……");
//statusTask.healthCheck();
logger.info("每分钟执行一次。结束。");
}
@Scheduled(fixedRate=20000)
public void testTasks() {
logger.info("每20秒执行一次。开始……");
//statusTask.healthCheck();
logger.info("每20秒执行一次。结束。");
}
}
六、全局异常处理器使用
package com.hxkj.fsslr.controller;
import java.io.FileNotFoundException;
import javax.lang.model.type.UnknownTypeException;
import javax.servlet.http.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import com.hxkj.fsslr.core.utils.PageReturnUtils;
/**
* @ClassName: GlobalExceptionHandler
* @Description: 全局异常处理
* @author huzhihui_c@qq.com
* @date 2016年7月18日 下午1:17:59
*/
@ControllerAdvice
public class GlobalExceptionHandler {
private static Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);
@ExceptionHandler(value=Exception.class)
@ResponseBody
public Object errorHandler(HttpServletRequest request,Exception e){
logger.info("-----捕获到异常-----");
//ajax请求异常返回
if(null != request.getHeader("X-Requested-With") && "XMLHttpRequest".equals( request.getHeader("X-Requested-With").toString())){
if (e instanceof NullPointerException) {
return PageReturnUtils.formatNormal("", PageReturnUtils.MSG_CODE_111111, PageReturnUtils.MSG_STATE_FALSE, "数据参数传入错误");
} else if (e instanceof FileNotFoundException) {
return PageReturnUtils.formatNormal("", PageReturnUtils.MSG_CODE_111111, PageReturnUtils.MSG_STATE_FALSE, "数据文件上传出错");
} else if (e instanceof ClassNotFoundException) {
return PageReturnUtils.formatNormal("", PageReturnUtils.MSG_CODE_111111, PageReturnUtils.MSG_STATE_FALSE, "系统未找到该jar包");
} else if (e instanceof UnknownTypeException) {
return PageReturnUtils.formatNormal("", PageReturnUtils.MSG_CODE_111111, PageReturnUtils.MSG_STATE_FALSE, "未知错误");
} else{
return PageReturnUtils.formatNormal("", PageReturnUtils.MSG_CODE_111111, PageReturnUtils.MSG_STATE_FALSE, e.toString());
}
}
return PageReturnUtils.formatNormal("", PageReturnUtils.MSG_CODE_111111, PageReturnUtils.MSG_STATE_FALSE, e.toString());
}
}
一、application.java中配置 自动启用事务 (basePackages={"com.hxkj.waychat.dao"}) 拦截器、过滤器、监听器的注解配置 二、监听器配置 package com.hxkj.waychat.intercept.listener; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; import javax.servlet.annotation.WebListener; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.hxkj.waychat.core.config.Constant; import com.hxkj.waychat.core.utils.PropertiesUtils; publicclass ThymeleafServletContextListener implements ServletContextListener { privatestatic Logger logger = LoggerFactory.getLogger(ThymeleafServletContextListener.class); public void contextDestroyed(ServletContextEvent arg0) { logger.info("----------:ServletContext销毁"); } public void contextInitialized(ServletContextEvent arg0) { logger.info("----------:ServletContext初始化"); logger.info("----------:baseUrl:"+PropertiesUtils.getPropertiesValue(Constant.BASE_URL)+";fileUrl:"+PropertiesUtils.getPropertiesValue(Constant.FILE_URL)); arg0.getServletContext().setAttribute("baseUrl", PropertiesUtils.getPropertiesValue(Constant.BASE_URL)); arg0.getServletContext().setAttribute("fileUrl", PropertiesUtils.getPropertiesValue(Constant.FILE_URL)); } } 三、过滤器配置 package com.hxkj.waychat.intercept.fliter; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.annotation.WebFilter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /*@WebFilter(filterName="MyFilter",urlPatterns="/*")*/publicclass MyFilter implements Filter { privatestatic Logger logger = LoggerFactory.getLogger(MyFilter.class); public void destroy() { logger.info("----------:过滤器销毁"); } public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2) throws IOException, ServletException { logger.info("----------:过滤器执行内容"); arg2.doFilter(arg0, arg1); } public void init(FilterConfig arg0) throws ServletException { logger.info("----------:过滤器初始化"); } } 四、拦截器配置 1.spring boot拦截器默认有 HandlerInterceptorAdapter AbstractHandlerMapping UserRoleAuthorizationInterceptor LocaleChangeInterceptor ThemeChangeInterceptor 2.配置spring mvc的拦截器WebMvcConfigurerAdapter publicclass WebAppConfig extends WebMvcConfigurerAdapter 3.实现添加拦截器方法 public void addInterceptors(InterceptorRegistry registry){ } registry.addInterceptor可以通过此方法添加拦截器, 可以是spring提供的或者自己添加的 4.实例部分 publicclass WebAppConfig extends WebMvcConfigurerAdapter{ public static void main(String[] args) { SpringApplication.run(WebAppConfig.class, args); } /** * 配置拦截器 * @author lance * @param registry */public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new UserSecurityInterceptor()).addPathPatterns("/user/**"); } } UserSecurityInterceptor代码 publicclass UserSecurityInterceptor implements HandlerInterceptor { public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { returntrue; } 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 { } } 五、定时器使用 publicclass Scheduler { privatefinal Logger logger = LoggerFactory.getLogger(this.getClass()); (cron="0 0/1 * * * ?") //每分钟执行一次 public void statusCheck() { logger.info("每分钟执行一次。开始……"); //statusTask.healthCheck(); logger.info("每分钟执行一次。结束。"); } (fixedRate=20000) public void testTasks() { logger.info("每20秒执行一次。开始……"); //statusTask.healthCheck(); logger.info("每20秒执行一次。结束。"); } } 六、全局异常处理器使用 package com.hxkj.fsslr.controller; import java.io.FileNotFoundException; import javax.lang.model.type.UnknownTypeException; import javax.servlet.http.HttpServletRequest; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseBody; import com.hxkj.fsslr.core.utils.PageReturnUtils; /** * @ClassName: GlobalExceptionHandler * @Description: 全局异常处理 * @author huzhihui_c@qq.com * @date 2016年7月18日 下午1:17:59 */publicclass GlobalExceptionHandler { privatestatic Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class); (value=Exception.class) public Object errorHandler(HttpServletRequest request,Exception e){ logger.info("-----捕获到异常-----"); //ajax请求异常返回if(null != request.getHeader("X-Requested-With") && "XMLHttpRequest".equals( request.getHeader("X-Requested-With").toString())){ if (e instanceof NullPointerException) { return PageReturnUtils.formatNormal("", PageReturnUtils.MSG_CODE_111111, PageReturnUtils.MSG_STATE_FALSE, "数据参数传入错误"); } elseif (e instanceof FileNotFoundException) { return PageReturnUtils.formatNormal("", PageReturnUtils.MSG_CODE_111111, PageReturnUtils.MSG_STATE_FALSE, "数据文件上传出错"); } elseif (e instanceof ClassNotFoundException) { return PageReturnUtils.formatNormal("", PageReturnUtils.MSG_CODE_111111, PageReturnUtils.MSG_STATE_FALSE, "系统未找到该jar包"); } elseif (e instanceof UnknownTypeException) { return PageReturnUtils.formatNormal("", PageReturnUtils.MSG_CODE_111111, PageReturnUtils.MSG_STATE_FALSE, "未知错误"); } else{ return PageReturnUtils.formatNormal("", PageReturnUtils.MSG_CODE_111111, PageReturnUtils.MSG_STATE_FALSE, e.toString()); } } return PageReturnUtils.formatNormal("", PageReturnUtils.MSG_CODE_111111, PageReturnUtils.MSG_STATE_FALSE, e.toString()); } }