spring boot + dubbo小實戰(七):實現登陸攔截器
在上一章已經完成了登陸服務,那麼在本章中主要是實現登陸攔截。
如何實現登陸攔截器?
在登陸方法中,將使用者資訊儲存在session中,所以在攔截器中把session中的user資訊拿出來,判斷是否為空即可判斷是否登陸。
如何編寫攔截器
編寫攔截器,可實現HandlerInterceptor介面,重寫HandlerInterceptor介面中的preHandle(),postHandle()和afterCompletion()三個方法。
preHandle():在執行controller之前執行,返回true代表可以執行controller,返回false代表不執行controller。一般用在登陸驗證、記錄日誌等等操作。
postHandle():在執行controller之後執行,但在渲染試圖之前執行。在這個可以對ModelAndView進行處理,比如每次執行完都需要返回固定的引數到request中,就可在本方法中編寫。
afterCompletion():在返回ModelAndView後執行,也就是dispatcherServlet 渲染了對應的檢視之後執行。比如效能監控,即可以輸出本次請求的耗時和結束時間
程式碼實現
首先編寫一個LoginInterceptor類實現HandlerInterceptor方法,具體程式碼如下
@Component public class LoginInterceptor implements HandlerInterceptor { private final Logger logger = LoggerFactory.getLogger(this.getClass()); @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 { } }
登陸攔截的具體實現邏輯,在preHandle中寫。具體邏輯程式碼如下,同時實現了日記記錄本次請求。
@Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { //記錄請求資訊 StringBuffer buf = new StringBuffer(); String parameter = request.getParameterMap() == null ? "" : JSON.toJSONString(request.getParameterMap()); buf.append("|").append("X-Real-IP=").append(request.getHeader("X-Real-IP")); buf.append("|").append("RequestURI=").append(request.getRequestURI()); buf.append("|").append("RequestURL=").append(request.getRequestURL()); buf.append("|").append("parameter=").append(parameter); buf.append("|").append("SessionId=").append(request.getSession().getId()); logger.info(buf.toString()); //是否登陸 Employee user = (Employee) request.getSession().getAttribute("sessionUser"); if (user == null) { //沒登陸,轉發到/unauthorized錯誤頁面 response.sendRedirect("/unauthorized"); return false; } return true; }
這樣就完成了登陸攔截的邏輯,是不是很簡單?
之後我需要記錄請求到渲染完頁面的時間,這個時候需要在preHandle中新增一下程式碼,START_TIME是定義在該類的一個常量
//記錄請求開始時間
request.setAttribute(START_TIME, System.currentTimeMillis());
在afterCompletion()中的邏輯程式碼如下
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
//獲取開始時間
long start = (long) request.getAttribute(START_TIME);
//獲得結束時間
long end = System.currentTimeMillis();
StringBuffer buf = new StringBuffer();
//構造日誌
buf.append("|").append("SessionId=").append(request.getSession().getId());
buf.append("|").append("RequestURI=").append(request.getRequestURI());
buf.append("|").append("serviceTime=").append(end - start).append("ms");
logger.info(buf.toString());
}
攔截器的程式碼寫完後,需要在config中註冊才能實現攔截。所以,需要寫一個簡單的config類,繼承WebMvcConfigurationSupport類,重寫addInterceptors()和addResourceHandlers()即可
具體程式碼如下
@Configuration
public class WebMvcConfig extends WebMvcConfigurationSupport {
@Override
protected void addInterceptors(InterceptorRegistry registry) {
//配置攔截器,對所有url進行攔截,排除"/static/**", "/login", "/logout", "/"這幾個url的攔截
registry.addInterceptor(new LoginInterceptor()).addPathPatterns("/**").excludePathPatterns("/static/**", "/login", "/logout", "/unauthorized", "/", "/thy/**");
super.addInterceptors(registry);
}
@Override
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
//靜態資源路徑配置
registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");
super.addResourceHandlers(registry);
}
}
addInterceptor是新增的攔截器類,addPathPatterns()是需要攔截的地址,/**是攔截所有地址,excludePathPatterns()是忽略攔截的地址。
addResourceHandlers()方法是配置一些靜態資源的方法,方法裡的邏輯是標識/static下的所有地址放行
啟動測試
啟動dubbo-user-web專案,進行測試。
未登入之前請求/index,會報401頁面
當你正確登陸後,進入首頁,控制檯中的資訊輸出如下
21:56:23 [http-nio-8180-exec-4] INFO c.j.d.u.c.i.LoginInterceptor - |X-Real-IP=null|RequestURI=/index|RequestURL=http://127.0.0.1:8180/index|parameter={}|SessionId=239FBB265E0B721A92483E3AA2C112EE|RemoteAddr=127.0.0.1|RemoteHost=127.0.0.1|RemotePort=53728
21:56:23 [http-nio-8180-exec-4] INFO c.j.d.u.c.i.LoginInterceptor - |SessionId=239FBB265E0B721A92483E3AA2C112EE|RequestURI=/index|serviceTime=147ms
21:56:23 [http-nio-8180-exec-8] INFO c.j.d.u.c.i.LoginInterceptor - |X-Real-IP=null|RequestURI=/main|RequestURL=http://127.0.0.1:8180/main|parameter={}|SessionId=239FBB265E0B721A92483E3AA2C112EE|RemoteAddr=127.0.0.1|RemoteHost=127.0.0.1|RemotePort=53728
21:56:23 [http-nio-8180-exec-8] INFO c.j.d.u.c.i.LoginInterceptor - |SessionId=239FBB265E0B721A92483E3AA2C112EE|RequestURI=/main|serviceTime=13ms
第二記錄準確的輸出了登陸成功後進入/index頁面並渲染頁面的請求相應的時間是147毫秒。(為什麼/login的登陸介面沒有輸出日誌呢?因為在WebMvcConfig中,忽略了/login路徑,所以請求的時候不經過攔截器)
到此,這樣就實現了一個簡單的登陸攔截器。。。