1. 程式人生 > >淺談JavaWeb中監聽器、過濾器、攔截器

淺談JavaWeb中監聽器、過濾器、攔截器

執行順序:

Javaweb

context-param-->listener-->filter-->servlet

Springmvc

context-param-->listener-->filter-->servlet-->interceptor(指的是攔截器),為什麼攔截器是在servlet執行之後,因為攔截器本身就是在servlet內部的

使用技巧:

需要監聽到專案中的一些資訊,並且不需要對流程做更改時,用監聽器;當需要過濾掉其中的部分資訊,只留一部分時,就用過濾器;當需要對其流程進行更改,做相關的記錄時用攔截器。過濾器是處於客戶端與伺服器資原始檔之間的一道過濾網,在訪問資原始檔之前,通過一系列的過濾器對請求進行修改、判斷等,把不符合規則的請求在中途攔截或修改。也可以對響應進行過濾,攔截或修改響應

(ps:類似aop)

過濾器

public class urlEncodeFilter implements Filter{



Logger logger = LoggerFactory.getLogger(urlEncodeFilter.class);

Map<String,Object> paramMap = new HashMap<String,Object>();



@Override

public void destroy() {

}



@Override

public void doFilter(ServletRequest arg0, ServletResponse arg1,

FilterChain arg2) throws IOException, ServletException {

System.out.println("urlEncodeFilter doFilter..."+paramMap.get("urlEncode").toString());

arg0.setCharacterEncoding(paramMap.get("urlEncode").toString());

arg2.doFilter(arg0, arg1);

}



@Override

public void init(FilterConfig arg0) throws ServletException {

String urlEncode = arg0.getInitParameter("urlEncode");

paramMap.put("urlEncode",urlEncode);

}



}
<filter>

<filter-name>urlEncodeFilter</filter-name>

<filter-class>com.mycompany.mvc.filter.urlEncodeFilter</filter-class>

<init-param>

<param-name>urlEncode</param-name>

<param-value>UTF-8</param-value>

</init-param>

</filter>

<filter-mapping>

<filter-name>urlEncodeFilter</filter-name>

<url-pattern>/*</url-pattern>

</filter-mapping>

攔截器:

<mvc:interceptors>  

    <!-- 使用bean定義一個Interceptor,直接定義在mvc:interceptors根下面的Interceptor將攔截所有的請求 -->  

    <bean class="com.host.app.web.interceptor.AllInterceptor"/>  

    <mvc:interceptor>  

        <mvc:mapping path="/test/number.do"/>  

        <!-- 定義在mvc:interceptor下面的表示是對特定的請求才進行攔截的 -->  

        <bean class="com.host.app.web.interceptor.LoginInterceptor"/>  

    </mvc:interceptor>  

</mvc:interceptors>  
public class LogsInterceptor extends HandlerInterceptorAdapter {

    private static final Logger logger = LoggerFactory.getLogger(LogsInterceptor.class);

    private  NamedThreadLocal<String> logContext = new NamedThreadLocal<String>("log-id");

    @Autowired

    private TLogDao logDao;

    /**

     * preHandle方法是進行處理器攔截用的,顧名思義,該方法將在Controller處理之前進行呼叫,

     * SpringMVC中的Interceptor攔截器是鏈式的,可以同時存在多個Interceptor,

     * 然後SpringMVC會根據宣告的前後順序一個接一個的執行,

     * 而且所有的Interceptor中的preHandle方法都會在Controller方法呼叫之前呼叫。

     * SpringMVC的這種Interceptor鏈式結構也是可以進行中斷的,

     * 這種中斷方式是令preHandle的返回值為false,當preHandle的返回值為false的時候整個請求就結束了。

     */

    @Override

    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        String host = request.getRemoteHost();

        String url = request.getRequestURI();

        TLogEntity entity = new TLogEntity();

        entity.setCreateTime(new Timestamp(System.currentTimeMillis()));

        entity.setCreateUser("admin");

        entity.setIpAddress(host);

        entity.setLogUrl(url);

        entity.setIsSuccess("N");

        logDao.save(entity);

        logContext.set(entity.getLogId());

        logger.debug("IP為---->>> " + host + " <<<-----訪問了系統");

        return true;

    }

    /**

     * 這個方法只會在當前這個Interceptor的preHandle方法返回值為true的時候才會執行。

     * postHandle是進行處理器攔截用的,它的執行時間是在處理器進行處理之 後, 也就是在Controller的方法呼叫之後執行,

     * 但是它會在DispatcherServlet進行檢視的渲染之前執行,也就是說在這個方法中你可以對ModelAndView進行操作。

     * 這個方法的鏈式結構跟正常訪問的方向是相反的,也就是說先宣告的Interceptor攔截器該方法反而會後呼叫,

     * 這跟Struts2裡面的攔截器的執行過程有點像,

     * 只是Struts2裡面的intercept方法中要手動的呼叫ActionInvocation的invoke方法,

     * Struts2中呼叫ActionInvocation的invoke方法就是呼叫下一個Interceptor或者是呼叫action,

     * 然後要在Interceptor之前呼叫的內容都寫在呼叫invoke之前,要在Interceptor之後呼叫的內容都寫在呼叫invoke方法之後。

     */

    @Override

    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

    }

    /**

     * 該方法也是需要當前對應的Interceptor的preHandle方法的返回值為true時才會執行。

     * 該方法將在整個請求完成之後,也就是DispatcherServlet渲染了檢視執行, 這個方法的主要作用是用於清理資源的,

     */

    @Override

    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {

        String host = request.getRemoteHost();

        String logId = logContext.get();

        TLogEntity entity = logDao.findOne(logId);

        entity.setIsSuccess("Y");

        logDao.save(entity);



        logger.debug("IP為---->>> " + host + " <<<-----訪問成功");

    }

}

監聽器:

 按監聽的物件劃分,可以分為

ServletContext物件監聽器

HttpSession物件監聽器

ServletRequest物件監聽器

按監聽的事件劃分

物件自身的建立和銷燬的監聽器

物件中屬性的建立和消除的監聽器

session中的某個物件的狀態變化的監聽器

<listener> <listener-class>

com.mycompany.mvc.listener.myServletContextListener

</listener-class>

</listener>

<listener>

<listener-class>

com.mycompany.mvc.listener.myServletContextAttributeListener

</listener-class>

</listener>

public class myHttpSessionListener implements HttpSessionListener{

public static int peopleOnLine = 0;

@Override

public void sessionCreated(HttpSessionEvent arg0) {

System.out.println("myHttpSessionListener.sessionCreated():"+arg0);

peopleOnLine++;

arg0.getSession().setAttribute("peopleOnLine",peopleOnLine);

}

@Override

public void sessionDestroyed(HttpSessionEvent arg0) {

System.out.println("myHttpSessionListener.sessionDestroyed():"+arg0);

peopleOnLine--;

arg0.getSession().setAttribute("peopleOnLine",peopleOnLine);

}

}

攔截器例項:

public class AdminLoginHandlerInterceptor extends LoginHandlerInterceptor {

@Autowired

private BaseService baseService;



@Override

@SuppressWarnings("unchecked")

public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

if(request.getServletPath().matches(".*/((assets)|(js)|(images)|(common)|(public)).*") || request.getServletPath().contains("/api")){

super.postHandle(request, response, handler, modelAndView);

return;

}

Object hd = request.getSession().getAttribute(Constant.SESSION_MENU);

if(modelAndView != null && hd != null) {

Map<String,String> subsetMap = this.checkSubset();

modelAndView.addObject("hd", hd);



Map<String, Boolean> authMap = new HashMap<String, Boolean>();

Map<String, Object> headerInfo = (Map<String, Object>)hd;

Object obj = headerInfo.get("menuList");

if(obj != null) {

for(Menu menu : (List<Menu>)obj) {

menu.setActive(false);

if(request.getServletPath().endsWith(menu.getUrl()) || (subsetMap.containsKey(menu.getUrl()) && subsetMap.get(menu.getUrl()).contains(request.getServletPath()))) {

addAuthButton(authMap, menu);

menu.setActive(true);

break;

}

boolean isEnd = false;

if(menu.getSubMenu() != null && menu.getSubMenu().size() > 0) {

for(Menu subMenu : menu.getSubMenu()) {

if(StringUtils.isBlank(subMenu.getUrl())) {

continue;

}

if(request.getServletPath().endsWith(subMenu.getUrl())) {

addAuthButton(authMap, subMenu);

menu.setActive(true);

isEnd = true;

break;

}

}

}

if(isEnd) {

break;

}

}

}

modelAndView.addObject("auth", authMap);



List<SysSystemConfig> configList = baseService.getList(

SysSystemConfig.class,

Collections.singletonList(Where.in(SysSystemConfigDomain.NID, new String[]{"site_logo", "site_name", "site_keywords", "site_discription", "site_copyright"})),

Parameter.queryColumn(new String[] {SysSystemConfigDomain.NID,SysSystemConfigDomain.VALUE})

);

if(configList != null && configList.size() > 0) {

for(SysSystemConfig config : configList) {

if("site_logo".equals(config.getNid())) {

modelAndView.addObject(config.getNid(), PropertiesUtil.getImageHost() + config.getValue());

} else {

modelAndView.addObject(config.getNid(), config.getValue());

}

}

}

}



super.postHandle(request, response, handler, modelAndView);

}



private void addAuthButton(Map<String, Boolean> authMap, Menu menu) {

if(menu == null || menu.getSubMenu() == null) {

return;

}



for(Menu btn : menu.getSubMenu()) {

if(!btn.getUrl().startsWith("btn:") || !btn.isChecked() ) {

continue;

}



authMap.put(btn.getUrl().replace("btn:", ""), true);

}

}



private Map<String, String> checkSubset() {

Map<String, String> subsetMap = new HashMap<String, String>();

subsetMap.put("platform/manager/list", "/platform/manager/detail,");

subsetMap.put("project/loan/list", "/project/loan/detail,");

subsetMap.put("loan/loan/list", "/loan/loan/detail,");

return subsetMap;

}

}





public class LoginHandlerInterceptor extends HandlerInterceptorAdapter{



@Override

public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

String path = request.getServletPath();

if ("/".equals(path))

return true;



if (path.matches(".*/((assets)|(js)|(images)|(common)|(public)).*"))

return true;



for (String newPath : list) {

if (path.matches(newPath)) {

return true;

}

}



if (request.getSession().getAttribute(Constant.SESSION_USER) == null) {

System.out.println("---------------");

response.sendRedirect(request.getContextPath() + Constant.LOGIN_URL);

return false;

}



return true;

}



/**

 * 免攔截的url

 */

public static List<String> list = new ArrayList<String>();

static {

//備案平臺管理

list.add("/platform/list");

list.add("/platform/toList");

list.add("/platform/listpage");

list.add("/platform/detail");

list.add("/platform/detailpage");

list.add("/system/platform/checkNum");

list.add("/system/platform/info");

list.add("/system/platform/toIndex");

list.add("/platform/listDetail");

list.add("/platform/statistics/risk");



//使用者中心

list.add("/member/member/memberInfo");



list.add("/api/project") ;

list.add("/api/repay") ;

list.add("/phone/location/get") ;

}

}