zoukankan      html  css  js  c++  java
  • ajax跨域解决

    因WEB安全原因,Ajax默认情况下是不能进行跨域请求的,遇到这种问题,自然难不倒可以改变世界的程序猿们,于是JSONP(JSON with Padding)被发明了,其就是对JSON的一种特殊,简单来说就是在原有的JSON数据上做了点手脚,从而达到可以让网页可以跨域请求。在现在互联网技术对“前后分离”大规模应用的时期,JSONP可谓意义重大啊。

    假设我们原来的JSON数据为 {“hello”:”你好”,”veryGood”:”很好”} 
    那么对应的JSONP的格式就是 functionName({“hello”:”你好”,”veryGood”:”很好”}) ,其中“functionName”不是固定值,自己定义。

    在SpringMVC中实现支持JSONP总结为如下几点: 
    1. response 响应类型为 application/javascript 
    2. 进行json请求的URL中需要携带参数 jsonp 或 callback,并指定值。 
    如 http://mydomain/index.jsonp?callback=myfun 
    或 http://mydomain/index.jsonp?jsonp=myfun 
    其中 myfun 就为最终包裹在原有JSON外的函数名 
    3. 如果你在配置文件中配置过 MappingJacksonJsonView 那么请修改使用 MappingJackson2JsonView 
    4. Controller 中的方法需要返回 ModelAndView 或者未使用 @ResponseBody 注解的返回 String 页面。也就是说最终怎么呈现结果,交由SpringMVC来给我们完成。 
    5. 针对显式注解 @ResponseBody 的方法 (我们本来就是直接响应JSON的),我们需要做特殊处理,使用 MappingJacksonValue 进行封装处理。

    说的有点抽象,下面看实际怎么做。 
    当然我们的原则就是“不对原有已经实现的代码进行任何修改”。

    本文代码以SpringBoot为例。

    使用 WebMvcConfigurerAdapter 配置 ContentNegotiatingViewResolver ,代码如下:

    @Configuration
    public class MyWebAppConfigurer 
            extends WebMvcConfigurerAdapter {
    
        private static final Logger logger = LoggerFactory.getLogger(MyWebAppConfigurer.class);
    
        @Override
        public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
            configurer.defaultContentType(MediaType.TEXT_HTML)
            .ignoreAcceptHeader(true);
        }
    
        /*
         * Configure ContentNegotiatingViewResolver
         */
        @Bean
        public ViewResolver contentNegotiatingViewResolver(ContentNegotiationManager manager) {
            ContentNegotiatingViewResolver resolver = new ContentNegotiatingViewResolver();
            resolver.setContentNegotiationManager(manager);
    
            // Define all possible view resolvers
            List<ViewResolver> resolvers = new ArrayList<ViewResolver>();
    
            resolvers.add(new JsonViewResolver());
    
            resolver.setViewResolvers(resolvers);
            return resolver;
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    JsonViewResolver.java

    public class JsonViewResolver implements ViewResolver{
    
        private MappingJackson2JsonView view;
    
        public JsonViewResolver() {
            super();
            view = new MMappingJackson2JsonView();
            view.setPrettyPrint(true);
        }
    
        public View resolveViewName(String viewName, Locale locale) throws Exception {
            return view;
        }
    
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    MMappingJackson2JsonView.java 
    这个类并不是必须的,我写出来也是为了说明如果遇到和我一样的问题时怎么解决,注意看代码中的注释说明

    public class MMappingJackson2JsonView extends MappingJackson2JsonView {
    
        /**
         * 排除JSON转换的时候 model 中自动加入的对象<br/>
         * 如果你在项目中使用了 @ControllerAdvice , 要特别注意了,我们在这里就是要排除掉因为@ControllerAdvice自动加入的值
         *
         */
        @Override
        protected Object filterModel(Map<String, Object> model) {
            Map<String, Object> result = new HashMap<String, Object>(model.size());
            if (model != null) {
                for (Map.Entry<String, Object> entry : model.entrySet()) {
                    if (!"urls".equals(entry.getKey())) {// 对我在项目中使用 @ControllerAdvice 统一加的值,进行排除。 
                        result.put(entry.getKey(), entry.getValue());
                    }
                }
            }
            return super.filterModel(result);
        }
    
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    上面提到的 MappingJackson2JsonView 我们已经在代码中使用了。 
    至于我还说到的 MappingJacksonValue 并不需要我们在哪里直接使用,其实 MappingJackson2JsonView 的源码中已经使用它做好了处理。我们只需要按上面说的在请求json的后面增加 jsonp 或 callback 参数即可。

    那么如果我们对于使用 @ResponseBody 注解直接响应JSON的该如何处理呢? 
    Follow Me ……

    原理: 
    ResponseBody 是通过 RequestResponseBodyMethodProcessor 来处理的,那我们就对这个类做一下包装处理。 
    RequestResponseBodyMethodProcessor 实现自接口 HandlerMethodReturnValueHandler,又因为Spring内部,同一个类型只能用一个的原则,我们实现自己的 HandlerMethodReturnValueHandler 实现类后,其中将原来的 RequestResponseBodyMethodProcessor 的原有对象包装进去,当我们完成自己的处理后,再讲处理权交给包装的 RequestResponseBodyMethodProcessor 对象。

    对 ResponseBody 还需要处理响应类型 (application/javascript) 
    在Spring内部,先从 ContentNegotiationStrategy 的方法 resolveMediaTypes 中读取 requestMediaTypes ,然后再去匹配 MappingJackson2HttpMessageConverter 中所有支持的 MediaTypes ,从而确定最终响应的 contentType。代码层面的处理也就是 ContentNegotiationStrategy 的 resolveMediaTypes 与 MappingJackson2HttpMessageConverter 的 getSupportedMediaTypes 结果对比处理。 
    为了满足我们JSONP的要求,requestMediaTypes 和 getSupportedMediaTypes 中都要包含 application/javascript

    所以我们还要做如下2步处理: 
    1、为 MappingJackson2HttpMessageConverter 添加 application/javascript 响应类型支持。 
    2、包装 ServletPathExtensionContentNegotiationStrategy ,重写 resolveMediaTypes 方法,根据JSONP特性 (callback参数),自动确定 application/javascript 请求类型。

    下面是代码: 
    其中 ResponseBodyWrapHandler 和 ContentNegotiationStrategyWrap 为包装类,ResponseBodyProcessor 为统一处理类。

    package org.springboot.sample.config.jsonp;
    
    import java.util.ArrayList;
    import java.util.List;
    
    import org.springframework.beans.factory.InitializingBean;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.http.MediaType;
    import org.springframework.http.converter.HttpMessageConverter;
    import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
    import org.springframework.web.accept.ContentNegotiationManager;
    import org.springframework.web.accept.ContentNegotiationStrategy;
    import org.springframework.web.accept.ServletPathExtensionContentNegotiationStrategy;
    import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
    import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
    import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;
    import org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor;
    
    /**
     * 处理Spring默认加载好的类,在原有类上使用自定义类进行包装处理。
     *
     * @author 单红宇(365384722)
     * @myblog http://blog.csdn.net/catoop/
     * @create 2016年2月29日
     */
    @Configuration
    public class ResponseBodyProcessor extends WebMvcConfigurerAdapter implements InitializingBean {
    
        @Autowired
        private RequestMappingHandlerAdapter adapter;
    
        @Autowired
        private ContentNegotiationManager manager;
    
        @Override
        public void afterPropertiesSet() throws Exception {
            List<HandlerMethodReturnValueHandler> returnValueHandlers = adapter.getReturnValueHandlers();
            List<HandlerMethodReturnValueHandler> handlers = new ArrayList<>(returnValueHandlers);
            decorateHandlers(handlers);
            adapter.setReturnValueHandlers(handlers);
    
            processContentNegotiationManager();
        }
    
        private void processContentNegotiationManager() {
            // 处理JSONP的响应ContentType
            List<ContentNegotiationStrategy> strategies = manager.getStrategies();
            for (int i = 0; i < manager.getStrategies().size(); i++) {
                if (manager.getStrategies().get(i) instanceof ServletPathExtensionContentNegotiationStrategy) {
                    strategies.set(i, new ContentNegotiationStrategyWrap(manager.getStrategies().get(i)));
                    manager = new ContentNegotiationManager(strategies);
                    break;
                }
            }
        }
    
        private void decorateHandlers(List<HandlerMethodReturnValueHandler> handlers) {
            for (HandlerMethodReturnValueHandler handler : handlers) {
                if (handler instanceof RequestResponseBodyMethodProcessor) {
                    // 用自己的ResponseBody包装类替换掉框架的,达到返回Result的效果
                    ResponseBodyWrapHandler decorator = new ResponseBodyWrapHandler(handler);
                    int index = handlers.indexOf(handler);
                    handlers.set(index, decorator);
                    break;
                }
            }
        }
    
        @Override
        public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
            for (HttpMessageConverter<?> httpMessageConverter : converters) {
                // 为 MappingJackson2HttpMessageConverter 添加 "application/javascript"
                // 支持,用于响应JSONP的Content-Type
                if (httpMessageConverter instanceof MappingJackson2HttpMessageConverter) {
                    MappingJackson2HttpMessageConverter convert = (MappingJackson2HttpMessageConverter) httpMessageConverter;
                    List<MediaType> medisTypeList = new ArrayList<>(convert.getSupportedMediaTypes());
                    medisTypeList.add(MediaType.valueOf("application/javascript;charset=UTF-8"));
                    convert.setSupportedMediaTypes(medisTypeList);
                    break;
                }
            }
            super.extendMessageConverters(converters);
        }
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    package org.springboot.sample.config.jsonp;
    
    import java.util.Arrays;
    import java.util.LinkedHashSet;
    import java.util.Set;
    import java.util.regex.Pattern;
    
    import org.apache.commons.logging.Log;
    import org.apache.commons.logging.LogFactory;
    import org.springframework.core.MethodParameter;
    import org.springframework.http.converter.json.MappingJacksonValue;
    import org.springframework.util.StringUtils;
    import org.springframework.web.context.request.NativeWebRequest;
    import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
    import org.springframework.web.method.support.ModelAndViewContainer;
    
    /**
     * ResponseBody 处理类
     *
     * @author   单红宇(365384722)
     * @myblog  http://blog.csdn.net/catoop/
     * @create    2016年2月29日
     */
    public class ResponseBodyWrapHandler implements HandlerMethodReturnValueHandler{  
    
        protected final Log logger = LogFactory.getLog(getClass());
    
        private final HandlerMethodReturnValueHandler delegate;  
    
        private Set<String> jsonpParameterNames = new LinkedHashSet<String>(Arrays.asList("jsonp", "callback"));
    
        /**
         * Pattern for validating jsonp callback parameter values.
         */
        private static final Pattern CALLBACK_PARAM_PATTERN = Pattern.compile("[0-9A-Za-z_\.]*");
    
    
        private String getJsonpParameterValue(NativeWebRequest request) {
            if (this.jsonpParameterNames != null) {
                for (String name : this.jsonpParameterNames) {
                    String value = request.getParameter(name);
                    if (StringUtils.isEmpty(value)) {
                        continue;
                    }
                    if (!isValidJsonpQueryParam(value)) {
                        if (logger.isDebugEnabled()) {
                            logger.debug("Ignoring invalid jsonp parameter value: " + value);
                        }
                        continue;
                    }
                    return value;
                }
            }
            return null;
        }
    
        protected boolean isValidJsonpQueryParam(String value) {
            return CALLBACK_PARAM_PATTERN.matcher(value).matches();
        }
    
        public ResponseBodyWrapHandler(HandlerMethodReturnValueHandler delegate){  
          this.delegate=delegate;  
        }  
    
        @Override  
        public boolean supportsReturnType(MethodParameter returnType) {  
            return delegate.supportsReturnType(returnType);  
        }  
    
        @Override  
        public void handleReturnValue(Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception {  
    
            String jsonpParameterValue = getJsonpParameterValue(webRequest);
            if (jsonpParameterValue != null) {
                if (!(returnValue instanceof MappingJacksonValue)) {
                    MappingJacksonValue container = new MappingJacksonValue(returnValue);
                    container.setJsonpFunction(jsonpParameterValue);
                    returnValue = container;
                }
            }
    
            delegate.handleReturnValue(returnValue,returnType,mavContainer,webRequest);  
        }  
    }  
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    package org.springboot.sample.config.jsonp;
    
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.LinkedHashSet;
    import java.util.List;
    import java.util.Set;
    import java.util.regex.Pattern;
    
    import org.apache.commons.logging.Log;
    import org.apache.commons.logging.LogFactory;
    import org.springframework.http.MediaType;
    import org.springframework.util.StringUtils;
    import org.springframework.web.HttpMediaTypeNotAcceptableException;
    import org.springframework.web.accept.ContentNegotiationStrategy;
    import org.springframework.web.context.request.NativeWebRequest;
    
    /**
     * 对 ServletPathExtensionContentNegotiationStrategy 进行包装
     *
     * @author   单红宇(365384722)
     * @myblog  http://blog.csdn.net/catoop/
     * @create    2016年2月29日
     */
    public class ContentNegotiationStrategyWrap implements ContentNegotiationStrategy {
    
        protected final Log logger = LogFactory.getLog(getClass());
    
        private final ContentNegotiationStrategy strategy;
    
        private Set<String> jsonpParameterNames = new LinkedHashSet<String>(Arrays.asList("jsonp", "callback"));
    
        /**
         * Pattern for validating jsonp callback parameter values.
         */
        private static final Pattern CALLBACK_PARAM_PATTERN = Pattern.compile("[0-9A-Za-z_\.]*");
    
        private String getJsonpParameterValue(NativeWebRequest request) {
            if (this.jsonpParameterNames != null) {
                for (String name : this.jsonpParameterNames) {
                    String value = request.getParameter(name);
                    if (StringUtils.isEmpty(value)) {
                        continue;
                    }
                    if (!isValidJsonpQueryParam(value)) {
                        if (logger.isDebugEnabled()) {
                            logger.debug("Ignoring invalid jsonp parameter value: " + value);
                        }
                        continue;
                    }
                    return value;
                }
            }
            return null;
        }
    
        protected boolean isValidJsonpQueryParam(String value) {
            return CALLBACK_PARAM_PATTERN.matcher(value).matches();
        }
    
        public ContentNegotiationStrategyWrap(ContentNegotiationStrategy strategy) {
            super();
            this.strategy = strategy;
        }
    
        @Override
        public List<MediaType> resolveMediaTypes(NativeWebRequest request) throws HttpMediaTypeNotAcceptableException {
    
            // JSONP 响应类型处理 ---- BEGIN
            String jsonpParameterValue = getJsonpParameterValue(request);
            if (jsonpParameterValue != null) {
                List<MediaType> mediaTypes = new ArrayList<>(1);
                mediaTypes.add(MediaType.valueOf("application/javascript"));
                return mediaTypes;
            }
            // JSONP 响应类型处理 ---- END
    
            return this.strategy.resolveMediaTypes(request);
        }
    
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81

    然后新建一个PageController来测试下效果:

    @Controller
    public class PageController {
    
        private static final Logger log = LoggerFactory.getLogger(PageController.class);
    
        /**
         * 默认页<br/>
         * @RequestMapping("/") 和 @RequestMapping 是有区别的
         * 如果不写参数,则为全局默认页,加入输入404页面,也会自动访问到这个页面。
         * 如果加了参数“/”,则只认为是根页面。
         *
         * @return
         * @author SHANHY
         * @create  2016年1月5日
         */
        @RequestMapping(value = {"/","/index"})
        public String index(Map<String, Object> model){
            model.put("time", new Date());
            model.put("message", "小单,你好!");
    
            return "index";
        }
    
        /**
         * 响应到JSP页面page1
         *
         * @return
         * @author SHANHY
         * @create  2016年1月5日
         */
        @RequestMapping("/page1")
        public ModelAndView page1(){
            log.info(">>>>>>>> PageController.page1");
            // 页面位置 /WEB-INF/jsp/page/page.jsp
            ModelAndView mav = new ModelAndView("page/page1");
            mav.addObject("content", hello);
            return mav;
        }
    
        @RequestMapping("/testJson")
        @ResponseBody
        public Map<String, String> getInfo(@RequestParam(required=false) String name,
                @RequestParam(required=false) String name1) {
            Map<String, String> map = new HashMap<>();
            map.put("name", name);
            map.put("name1", name1);
            return map;
        }   
    
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50

    测试结果截图如下: 
    请求JSONP数据 
    这里写图片描述


    正常请求JSON数据 
    这里写图片描述


    直接请求显示页面 
    这里写图片描述


    至此,我们的服务端代码改造完毕,我们在 “不对原有业务代码进行任何修改的前提下” 完成了处理,接下来是在HTML页面中使用jQuery来请求JSONP实现跨域访问。

    将下面的代码存储为一个普通的HTML页面,然后用浏览器打开就可以测试了,当然别忘了启动你的web服务:

    <!DOCTYPE html> 
    <html> 
    <head> 
    <meta charset="utf-8"> 
    <script src="http://code.jquery.com/jquery-2.1.3.min.js"></script> 
    <script type="text/javascript"> 
    $(document).ready(function(){ 
    
        $("#b1").click(function(){ 
             $.ajax({ 
                url:'http://localhost:8080/myspringboot/testJson.json?name=Shanhy&name1=Lily', 
                type: "get", 
                async: false, 
                dataType: "jsonp", 
                jsonp: "callback", //服务端用于接收callback调用的function名的参数(请使用callback或jsonp)
                jsonpCallback: "fun_jsonpCallback", //callback的function名称
                success: function(json) { 
                    alert(json.name); 
                },
                error: function(){
                    alert('Request Error');
                } 
            }); 
        });        
    
        $("#b2").click(function(){ 
             $.ajax({ 
                url:'http://localhost:8080/myspringboot/testJson.json?name=Shanhy&name1=Lily', 
                type: "get", 
                async: false, 
                //dataType: "jsonp", 
                //jsonp: "callback", //服务端用于接收callback调用的function名的参数(请使用callback或jsonp)
                //jsonpCallback: "fun_jsonpCallback", //callback的function名称 
                success: function(json) { 
                    alert(json.name1); 
                },
                error: function(){
                    alert('Request Error');
                } 
            }); 
        });   
    
    }); 
    </script> 
    </head> 
    <body> 
    
        <div id="div1"><h2>jQuery AJAX 的跨域请求</h2></div> 
        <button id="b1">JSONP请求 (预期结果为成功)</button> <br/> 
        <button id="b2">JSON请求 (预期结果为失败)</button> 
    
    </body> 
    </html>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53

    至此,相信已经满足应用的需求,对部署容器不需要做任何修改。 
    不过还有另一种很简单的方法来支持Ajax的跨域请求,那就是在响应头中添加支持,如下:

    // 指定允许其他域名访问(必须)
    response.addHeader("Access-Control-Allow-Origin", "*");
    // 响应类型(非必须)
    response.addHeader("Access-Control-Allow-Methods", "POST");
    // 响应头设置(非必须)
    response.addHeader("Access-Control-Allow-Headers", "x-requested-with,content-type");
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    如果你前端使用到 ApacheServer、Nginx 那么也可以在他们的配置文件中直接配置,具体查一下资料即可。 
    这里有一点要注意:Access-Control-Allow-Origin 的 * 是允许所有,如果要针对域名设置,直接指定域名即可,但是请注意这里你不可以用逗号分割的方式同时配置多个域名。 
    如果你真的需要,可以参考如下代码:

            List<String> domainList = new ArrayList<>();
            domainList.add("http://www.domain1.com");
            domainList.add("http://www.domain2.com");
            domainList.add("http://localhost:8088");
            String requestDomain = request.getHeader("origin");
            log.info("requestDomain = " + requestDomain);
            if(domainList.contains(requestDomain)){
                response.addHeader("Access-Control-Allow-Origin", requestDomain);
                response.addHeader("Access-Control-Allow-Methods", "GET");
                response.addHeader("Access-Control-Allow-Headers", "x-requested-with,content-type");
            }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    实际应用中,根据自己的需要选择合适的方法。

    我喜欢开发者,程序猿。他们单纯、固执、容易体会到成就感;面对压力,能够挑灯夜战不眠不休;面对困难,能够迎难而上挑战自我。他们也会感到困惑与傍徨,但每个程序员的心中都有一个比尔盖茨或是乔布斯的梦想“用智慧开创属于自己的事业”。我想说的是,其实我是一个猿。
  • 相关阅读:
    POJ 3468 A Simple Problem with Integers
    BZOJ 4430 Guessing Camels
    POJ 2309 BST
    POJ 1990 MooFest
    cf 822B Crossword solving
    cf B. Black Square
    cf 828 A. Restaurant Tables
    Codefroces 822C Hacker, pack your bags!
    [HDU 2255] 奔小康赚大钱
    [BZOJ 1735] Muddy Fields
  • 原文地址:https://www.cnblogs.com/Garolli/p/5231111.html
Copyright © 2011-2022 走看看