1. 程式人生 > >跨域那點事~

跨域那點事~

自從做了前後端分離專案以後,就遇到了跨域問題.一直也沒有深入自己去測試,反正能解決就行了,今天自己寫了一系列測試,得到了java解決跨域問題的多種方法;

1.首先是基本沒用過的jsonp方式:(缺點:麻煩,只支援GET請求)

     $("#btn3").click(function () {
            $.ajax({
                url: "http://localhost:9090/test3",
                type: "get",
                dataType: "jsonp",            //這裡指定請求後臺伺服器返回型別jsonp
            //    jsonpCallback: "gao",       //指定請求地址後面callback的值
            //    jsonp:"callback",           //指定jsonp請求地址的引數名,預設callback
                success: function (data) {
                    alert(data);
                }
            });
        });

如果上面不指定jsonpCallback的請求值時,會預設生成隨機的請求值;如下:

http://localhost:9090/test3?callback=jsonp1536806347498

後臺處理的話,就要在引數返回時,使用jsonp請求值包裹返回值,如 jsonp1536806347498(...);

    @GetMapping("/test3")
    public void tt3e(HttpServletRequest request, HttpServletResponse response) throws IOException {
        String callback = request.getParameter("callback");
        String result = new ObjectMapper().writeValueAsString(Arrays.asList(1, 1, 1, 1));
        String now = callback + "(" + result + ")";
        response.getWriter().write(now);
    }

2.後臺返回引數header新增跨域引數;(全是優點)

這種前臺不用做任何操作,只要後臺進行一些新增引數即可;方式有以下幾種;

第一種,新增過濾器,攔截器方式:

public class MyFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        response.setCharacterEncoding("utf-8");
        response.setHeader("Access-Control-Allow-Origin", "*"); // 解決跨域訪問報錯
        response.setHeader("Access-Control-Allow-Methods", "POST, PUT, GET, OPTIONS, DELETE");
        response.setHeader("Access-Control-Max-Age", "3600"); // 設定過期時間
        response.setHeader("Access-Control-Allow-Headers",
                "Origin, X-Requested-With, Content-Type, Accept, client_id, uuid, Authorization");
        response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // 支援HTTP 1.1.
        response.setHeader("Pragma", "no-cache"); // 支援HTTP 1.0. response.setHeader("Expires", "0");
        filterChain.doFilter(servletRequest, servletResponse);
    }

    @Override
    public void destroy() {

    }
}
public class MyConfig implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            response.setHeader("Access-Control-Allow-Origin", "*");  
            response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS,             DELETE");  
            response.setHeader("Access-Control-Max-Age", "3600");  
            response.setHeader("Access-Control-Allow-Headers", "x-requested-with"); 
        return true;
    }
}

這種方式不管你已何種方式請求,跨域或者不跨域,在返回引數header引數中,都可以看到以下引數:

Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, client_id, uuid, Authorization
Access-Control-Allow-Methods: POST, PUT, GET, OPTIONS, DELETE
Access-Control-Allow-Origin: *
Access-Control-Max-Age: 3600
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json;charset=UTF-8
Date: Thu, 13 Sep 2018 02:50:53 GMT
Pragma: no-cache
Transfer-Encoding: chunked

因為用下面的方式跨域時,本地用postman測試時候,因為沒有這些引數,一直以為沒有生效,所以一直採用這種方式,沒有敢用其他方式.......其實下面方式也是生效的,只有跨域請求的時候會在返回引數中帶有這些跨域引數;

第二種,springboot直接重寫跨域配置,這種方式比較簡單,推薦:

public class MyCros implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**").allowedOrigins("*");
    }
}

第三種:在類或者方法上新增@CrossOrigin註解;看到網上有在ssm專案中遇到不生效的問題,看到解決辦法有的因為@RequestMapping註解中沒有指定method請求方式造成的,只要新增get或post等引數就可以了.我在springboot中沒有出現這種問題;