1. 程式人生 > 程式設計 >Spring Boot實戰(四):Spring Boot配置攔截器及實現跨域訪問

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

攔截器功能強大,能夠深入方法前後,常應用於日誌記錄、許可權檢查和效能檢測等,幾乎是專案中不可或缺的一部分,本文就來實現Spring Boot自定義攔截器的配置。

理論指導

:Spring Boot怎麼配置攔截器?

:配置一個攔截器需要兩步完成。

  1. 自定義攔截器,實現HandlerInterceptor這個介面。這個介面包括三個方法,preHandle是請求執行前執行的,postHandler是請求結束執行的,但只有preHandle方法返回true的時候才會執行,afterCompletion是檢視渲染完成後才執行,同樣需要preHandle返回true,該方法通常用於清理資源等工作。

  2. 註冊攔截器。 作用是確定攔截器和攔截的URL。需要繼承WebMvcConfigurationSupport並重寫addInterceptor方法,WebMvcConfigureAdapter已經過時了!!

程式碼實現

目錄結構:

image

TimeCostInterceptor是一個功能齊全的攔截器,需要用到util裡面的工具類,由於程式碼較多,感興趣的可以到GitHub中檢視原始碼。

具體程式碼:

MyInterceptor.java

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,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,Exception e) throws Exception { } } 複製程式碼

RegisterInterceptor.java

/**
 * 繼承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地址