SPRING BOOT 跨域访问处理

来源:互联网 发布:mac能下载wps吗 编辑:程序博客网 时间:2024/06/14 18:36
  1. 问题场景:由于项目中使用到跨域访问,今天也得到高人指点,所以写出来分享给大家。可能是考虑到前后端分离,前端后端服务器不在一台机器上,出现这种跨域访问的情况。正常情况下本地访问是没有问题,但是遇到这种非同一台服务器的情况下,就会报错 Access-Control-Allow-Origin 。具体报错内容不记得了。
  2. 问题解决方案一:采用添加拦截器的方式对请求添加跨域访问的头,允许跨域访问。
    复制代码
    package com.meicloud.interceptor;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.apache.log4j.Logger;import org.springframework.web.servlet.ModelAndView;import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;public class CommonInterceptor extends HandlerInterceptorAdapter  {    private final static  Logger logger = Logger.getLogger(CommonInterceptor.class);        @Override    public boolean preHandle(HttpServletRequest request,HttpServletResponse response, Object handler) throws Exception {        logger.info("添加跨域访问头配置,Access-Control-Allow-Origin:*");        //跨域访问CORS        response.addHeader("Access-Control-Allow-Origin", "*");        response.addHeader("Access-Control-Allow-Methods", "POST,GET,OPTIONS,PUT,DELETE,HEAD");        response.addHeader("Access-Control-Allow-Headers", "S_ID,content-type");        response.addHeader("Access-Control-Max-Age", "3600000");        response.addHeader("Access-Control-Allow-Credentials", "true");                //让请求,不被缓存,        response.setHeader("Cache-Control", "no-cache");          response.setHeader("Cache-Control", "no-store");          response.setHeader("Pragma", "no-cache");          response.setDateHeader("Expires", 0);                 logger.debug("==================================preHandle");        return true;    }        @Override    public void postHandle(HttpServletRequest request,            HttpServletResponse response, Object handler,            ModelAndView modelAndView) throws Exception {        logger.debug("==================================postHandle");    }            @Override    public void afterCompletion(HttpServletRequest request,            HttpServletResponse response, Object handler, Exception ex)            throws Exception {        logger.debug("==================================afterCompletion");    }}
    复制代码

    上面是拦截器内容,下面是对拦截器的配置。

    复制代码
    package com.meicloud.config;import org.springframework.context.annotation.ComponentScan;import org.springframework.context.annotation.Configuration;import org.springframework.web.servlet.config.annotation.InterceptorRegistry;import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;import com.meicloud.interceptor.CommonInterceptor;@ComponentScan@Configurationpublic class WebMvcConfig extends WebMvcConfigurerAdapter {        @Override    public void addInterceptors(InterceptorRegistry registry) {        // TODO Auto-generated method stub        registry.addInterceptor(new CommonInterceptor()).addPathPatterns("/getDOC");    }  }
    复制代码

    然后就可以在controller中使用他了,下面是我的controller

    复制代码

    @ResponseBody
    @RequestMapping(value="/getDOC",method=RequestMethod.POST)
    public BaseReturn getDOC(@RequestBody MailEntity mailEntity, HttpServletRequest request, HttpServletResponse response, HttpSession httpSession){
    log.info("excute controllor HomeController.getDOC");
    BaseReturn baseReturn = new BaseReturn();

    String name = mailEntity.getName();
    String company = mailEntity.getCompany();
    String departments = mailEntity.getDepartments();
    String job = mailEntity.getJob();
    String email = mailEntity.getEmail();
    String phone = mailEntity.getPhone();
    String doc = mailEntity.getDoc();

    try {
    if(name==null||name.equals("")){
    throw new CommenException("姓名不能为空!");
    }
    if(email==null||email.equals("")){
    throw new CommenException("Email不能为空!");
    }
    if(phone==null||phone.equals("")){
    throw new CommenException("电话号码不能为空!");
    }
    if(doc==null||doc.equals("")){
    throw new CommenException("文档不能为空!");
    }
    } catch (Exception e1) {
    baseReturn.setCode(ReturnType.FAIL);
    baseReturn.setMsg(e1.getMessage());
    log.error(e1.getMessage());
    return baseReturn;
    }

    try {
    // iMailClent.sendMail(mailEntity);
    iMailClent.sendHtmlMail(mailEntity);
    baseReturn.setCode(ReturnType.SUCCESS);
    } catch (Exception e) {
    e.printStackTrace();
    baseReturn.setCode(ReturnType.FAIL);
    baseReturn.setMsg("发送邮件失败!");
    log.error(e.getMessage());
    }

    return baseReturn;
    }

    复制代码

    接下来是前端的调用,前端采用ajax post 请求

    复制代码
    var params = {                          name:name,                          company:company,                          departments:departments,                          job:job,                          email:email,                          phone:phone,                          doc:'/doc/api.doc'                  };var type = 'POST';var url = Config.host + url;$.ajax({        url : url,        data : JSON.stringify(params),        type : type,        contentType : "application/json",        async : false,        success : function(data) {            //TODO 成功        },        error : function(data) {            //TODO 失败        }    });
    复制代码

     

  3. 问题解决方案二:使用 JSONP 来实现跨域访问。直接上代码,前端代码为:
    复制代码
    url = 'http://localhost:9999/getDOC' + '?name=' + params.name             + '&company=' + params.company            + '&departments=' + params.departments + '&job=' + params.job            + '&email=' + params.email + '&phone=' + params.phone + '&doc='            + params.doc;$.ajax({        url : url,        type : 'get',        async : false,        dataType : "jsonp",        jsonpCallback : "callback",        success : function(data) {            //TODO 成功        },        error : function(data) {            //TODO 失败        }    });
    复制代码

    限制调用方式为 get ,数据类型为 jsonp。后端也必须响应 JSONPObject 对象。

    复制代码
    @ResponseBody    @RequestMapping(value="/getDOC",method=RequestMethod.GET)    public JSONPObject getDOC(HttpServletRequest request,String callback){                BaseReturn baseReturn = new BaseReturn();                String name = request.getParameter("name");        String company = request.getParameter("company");        String departments = request.getParameter("departments");        String job = request.getParameter("job");        String email = request.getParameter("email");        String phone = request.getParameter("phone");        String doc = request.getParameter("doc");                try {            if(name==null||name.equals("")){                throw new CommenException("姓名不能为空!");            }            if(email==null||email.equals("")){                throw new CommenException("Email不能为空!");            }            if(phone==null||phone.equals("")){                throw new CommenException("电话号码不能为空!");            }            if(doc==null||doc.equals("")){                throw new CommenException("文档不能为空!");            }        } catch (Exception e1) {            baseReturn.setCode(ReturnType.FAIL);            baseReturn.setMsg(e1.getMessage());            log.error(e1.getMessage());            return new JSONPObject(callback, baseReturn);        }                MailEntity mailEntity = new MailEntity();        mailEntity.setCompany(company);        mailEntity.setDepartments(departments);        mailEntity.setDoc(doc);        mailEntity.setEmail(email);        mailEntity.setJob(job);        mailEntity.setName(name);        mailEntity.setPhone(phone);                        try {             iMailClent.sendHtmlMail(mailEntity);            baseReturn.setCode(ReturnType.SUCCESS);        } catch (Exception e) {            e.printStackTrace();            baseReturn.setCode(ReturnType.FAIL);            baseReturn.setMsg("发送邮件失败!");            log.error(e.getMessage());        }                return new JSONPObject(callback, baseReturn);    }    
    复制代码

     

  4. 今天得到高人指点,原来有一种更加简便的方法,可以实现。不过原理肯定都是一样的,通过给请求添加消息头来设置跨域访问,这点是无疑的。新的解决办法就是给controller或方法添加 @CrossOrigin 注解,具体详情请参考:http://spring.io/blog/2015/06/08/cors-support-in-spring-framework
    @ResponseBody    @RequestMapping(value="/getDOC",method=RequestMethod.POST)    @CrossOrigin //使用注解方式添加跨域访问消息头    public BaseReturn getDOC(@RequestBody MailEntity mailEntity, HttpServletRequest request, HttpServletResponse response, HttpSession httpSession){        log.info("excute controllor HomeController.getDOC");

    就这么多了吧,在网上看到还有添加过滤器的,当然都是差不多的做法。

原创粉丝点击