Spring Boot實戰(四):Spring Boot配置攔截器及實現跨域訪問

攔截器功能強大,可以深刻方法先後,常應用於日誌記錄、權限檢查和性能檢測等,幾乎是項目中不可或缺的一部分,本文就來實現Spring Boot自定義攔截器的配置。javascript

理論指導

:Spring Boot怎麼配置攔截器?html

:配置一個攔截器須要兩步完成。前端

  1. 自定義攔截器,實現HandlerInterceptor這個接口。這個接口包括三個方法,preHandle是請求執行前執行的,postHandler是請求結束執行的,但只有preHandle方法返回true的時候纔會執行,afterCompletion是視圖渲染完成後才執行,一樣須要preHandle返回true,該方法一般用於清理資源等工做。java

  2. 註冊攔截器。 做用是肯定攔截器和攔截的URL。須要繼承WebMvcConfigurationSupport並重寫addInterceptor方法,WebMvcConfigureAdapter已通過時了!!git

代碼實現

目錄結構:github

image

TimeCostInterceptor是一個功能齊全的攔截器,須要用到util裏面的工具類,因爲代碼較多,感興趣的能夠到GitHub中查看源碼。spring

具體代碼:跨域

MyInterceptor.javacookie

public class MyInterceptor implements HandlerInterceptor {

    /** * preHandle在執行Controller以前執行,返回true,則繼續執行Contorller * 返回false則請求中斷。 */
    @Override
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
        //只有返回true纔會繼續向下執行,返回false取消當前請求 
        long startTime = System.currentTimeMillis();
        httpServletRequest.setAttribute("startTime", startTime);
        return true;
    }

    /** * postHandle是在請求執行完,但渲染ModelAndView返回以前執行 */
    @Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
        long startTime = (Long) httpServletRequest.getAttribute("startTime");
        long endTime = System.currentTimeMillis();
        long executeTime = endTime - startTime;
        StringBuilder sb = new StringBuilder(1000);
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String date = simpleDateFormat.format(new Date());
        sb.append("-----------------------").append(date).append("-------------------------------------\n");
        sb.append("URI : ").append(httpServletRequest.getRequestURI()).append("\n");
        sb.append("CostTime : ").append(executeTime).append("ms").append("\n");
        sb.append("-------------------------------------------------------------------------------");
        System.out.println(sb.toString());
    }

    /** * afterCompletion是在整個請求執行完畢後執行 */
    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
    }

}
複製代碼

RegisterInterceptor.javaapp

/** * 繼承WebMvcConfigurationSupport繼承並重寫addInterceptor方法用於註冊攔截器 * WebMvcConfigureAdapter已通過時了!! */
@Configuration
public class RegisterInterceptor extends WebMvcConfigurationSupport {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new MyInterceptor()).addPathPatterns("/**");
        super.addInterceptors(registry);
    }
}
複製代碼

攔截效果

image


更新

跨域訪問

因爲JavaScript同源策略,凡是發送請求url的協議、域名、端口三者之間任意一與當前頁面地址不一樣即爲跨域。具體的看下錶(來源於javascript跨域資源總結與解決辦法):

URL 說明 是否容許通訊
www.a.com/a.jswww.a.com/b.js 同一域名下 容許
www.a.com/lab/a.jswww.a.com/script/b.js 同一域名下不一樣文件夾 容許
www.a.com:8000/a.jswww.a.com/b.js 同一域名,不一樣端口 不容許
www.a.com/a.jswww.a.com/b.js 同一域名,不一樣協議 不容許
www.a.com/a.jshttp://70.32.92.74/b.js 域名和域名對應ip 不容許
www.a.com/a.jsscript.a.com/b.js 主域相同,子域不一樣 不容許
www.a.com/a.jsa.com/b.js 同一域名,不一樣二級域名(同上) 不容許(cookie這種狀況下也不容許訪問)
www.cnblogs.com/a.jswww.a.com/b.js 不一樣域名 不容許

上面代碼是能夠實現攔截器基本功能,可是這樣是不能夠跨域訪問的,前端請求接口會有報錯:XMLHttpRequest cannot loadhttp://xxx/. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'null' is therefore not allowed access.

解決方案是設置請求頭Access-Control-Allow-Origin爲「*」或者設置爲和request相同的Origin。

①在攔截器中添加一個設置請求頭的方法。

public void crossDomain(HttpServletRequest request, HttpServletResponse response) {
        response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
        response.setHeader("Access-Control-Allow-Credentials", "true");
    }
複製代碼

②在preHandle中調用這個方法。

  public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        crossDomain(request, response);
        long startTime = System.currentTimeMillis();
        request.setAttribute("startTime", startTime);
        return true;
    }
複製代碼

完整代碼:GItHub地址

相關文章
相關標籤/搜索