1.3Security:權限管理,過濾、監聽、攔截


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();
  • 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中配置 @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; @WebListenerpublicclass ThymeleafServletContextListener implements ServletContextListener { privatestatic Logger logger = LoggerFactory.getLogger(ThymeleafServletContextListener.class); @Overridepublic void contextDestroyed(ServletContextEvent arg0) { logger.info("----------:ServletContext銷毀"); } @Overridepublic 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); @Overridepublic void destroy() { logger.info("----------:過濾器銷毀"); } @Overridepublic void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2) throws IOException, ServletException { logger.info("----------:過濾器執行內容"); arg2.doFilter(arg0, arg1); } @Overridepublic 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 { @Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { returntrue; } @Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { } @Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { } } 五、定時器使用 @Componentpublicclass Scheduler { privatefinal 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 */@ControllerAdvicepublicclass GlobalExceptionHandler { privatestatic Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class); @ExceptionHandler(value=Exception.class) @ResponseBodypublic 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()); } }


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM