1. 程式人生 > >自定義註解,實現攔截器

自定義註解,實現攔截器

資訊網站專案
     存在登入和未登入兩種狀態的操作,呼叫後臺方法需要進行判定是否登入。 此時攔截器派上用場

//攔截器用處(來源:跟著開濤學SpringMVC)
1、日誌記錄:記錄請求資訊的日誌,以便進行資訊監控、資訊統計、計算PV(Page View)等。
2、許可權檢查:如登入檢測,進入處理器檢測檢測是否登入,如果沒有直接返回到登入頁面;
3、效能監控:有時候系統在某段時間莫名其妙的慢,可以通過攔截器在進入處理器之前記錄開始時間,在處理完後記錄結束時間,從而得到該請求的處理時間(如果有反向代理,如apache可以自動記錄);
4、通用行為:讀取cookie得到使用者資訊並將使用者物件放入請求,從而方便後續流程使用,還有如提取Locale、Theme資訊等,只要是多個處理器都需要的即可使用攔截器實現。
5、OpenSessionInView:如Hibernate,在進入處理器開啟Session,在完成後關閉Session。
…………本質也是AOP(面向切面程式設計),也就是說符合橫切關注點的所有功能都可以放入攔截器實現。

HandlerInterceptorAdapter

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

        return true;    
    }    
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 { }

分別實現預處理、後處理(呼叫了Service並返回ModelAndView,但未進行頁面渲染)、返回處理(已經渲染了頁面)
在preHandle中,可以進行編碼、安全控制等處理;
在postHandle中,有機會修改ModelAndView;
在afterCompletion中,可以根據ex是否為null判斷是否發生了異常,進行日誌記錄。

//自定義註解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface NeedLogin {
    String value() default "";
}

//攔截器,繼承HandlerInterceptorAdapter介面
public class LoginInterceptor extends HandlerInterceptorAdapter{
    public boolean preHandle(HttpServletRequest request,HttpServletResponse response, Object handler) throws Exception {
        if(handler.getClass().isAssignableFrom(HandlerMethod.class)){//如果是spring mvc 方法
            NeedLogin needLogin = ((HandlerMethod)handler).getMethodAnnotation(NeedLogin.class);
            if(needLogin!=null){
                NewsUser u = (NewsUser) request.getSession().getAttribute("user");
                if(u==null){
                    String rt = request.getHeader("X-Requested-With");
                    if(rt!=null && "XMLHttpRequest".equals(rt)){
                        JSONObject json = new JSONObject();
                        json.put("isLogin", false);
                        response.getWriter().print(json.toString());
                        return false;
                    }else{
                        response.sendRedirect(request.getContextPath()+"/news/index");
                        return false;
                    }
                }else{
                    return true;
                }
            }
        }
        return true;
    }
}

根據以上寫法:
    1.如果寫了@NeedLogin註解,則呼叫方法之前會進行是否登入校驗
    2.未寫,則不校驗

@NeedLogin
@ResponseBody
@RequestMapping(value="addOrUpdate")
public String addHistory(Long roomId, Long userId) {
    JSONObject obj = new JSONObject();
    boolean flag = false;
    ZhiboWatchRecord zhiboWatchRecord = zhiboWatchRecordService
        .addOrUpdateToHistory(roomId, userId);

    if (zhiboWatchRecord != null) {
        flag = true;
    }

    obj.put("status", flag? 1:0);

    return obj.toString();
}