SPRING BOOT跨域访问处理
尊重原创:http://blog.csdn.net/ruiguang21/article/details/77878933
- 问题场景:由于项目中使用到跨域访问,今天也得到高人指点,所以写出来分享给大家可能是考虑到前后端分离,前端后端服务器不在一台机器上,出现这种跨域访问的情况。正常情况下本地访问是没有问题,但是遇到这种非同一台服务器的情况下,就会报错Access-Control-Allow-Origin。具体报错内容不记得了。
- 问题解决方案一:采用添加拦截器的方式对请求添加跨域访问的头,允许跨域访问。
-
包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; 公共 类 CommonInterceptor 扩展HandlerInterceptorAdapter { 私人 最终 静态 记录器记录器= Logger.getLogger(CommonInterceptor。类); @覆盖 公共 布尔 preHandle(HttpServletRequest请求,HttpServletResponse响应,对象处理程序)抛出异常{ 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” ); 返回 true ; } @覆盖 公共 无效postHandle(HttpServletRequest请求, HttpServletResponse响应,对象处理程序, ModelAndView modelAndView)抛出Exception {logger.debug ( “================================== postHandle” ); } @覆盖 public void afterCompletion(HttpServletRequest request, HttpServletResponse响应,对象处理程序,Exception ex) 抛出Exception { logger.debug( “================================== afterCompletion” ); } }
- 上面是拦截器内容,下面是对拦截器的配置。
包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 @组态 公共 类 WebMvcConfig 扩展WebMvcConfigurerAdapter { @覆盖 public void addInterceptors(InterceptorRegistry registry){ // TODO自动生成的方法存根 registry.addInterceptor(new CommonInterceptor())。addPathPatterns(“/ getDOC” ); } }
然后就可以在控制器中使用他了,下面是我的控制器
我们可以通过调用 这个方法来实现一个简单的方法来实现这个方法,这个方法可以 用来实现一个简单的方法来实现这个方法 。 BaseReturn baseReturn = new BaseReturn(); 字符串名称= mailEntity.getName(); String company = mailEntity.getCompany(); 字符串部门= mailEntity.getDepartments(); String job = mailEntity.getJob(); String email = mailEntity.getEmail(); String phone = mailEntity.getPhone(); String doc = mailEntity.getDoc(); 尝试{ 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(“文档不能为空!”); } }赶上(例外E1){ baseReturn.setCode(ReturnType.FAIL); baseReturn.setMsg(e1.getMessage()); log.error(e1.getMessage()); 返回基地返回; } 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 = { 名称:名称, 公司:公司, 部门:部门, 工作:工作, 电子邮件:电子邮件, 电话:电话, doc: '/ doc/ api.doc' }; var type ='POST' ; var url = Config.host + url; $就({ url:url, 数据:JSON.stringify(params), 键入:type, contentType: “application / json” , async:false , 成功:函数(数据){ // TODO成功 }, 错误:函数(数据){ // TODO失败 } });
问题解决方案二:使用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; $就({ url:url, 键入: 'get' , async:false , dataType: “jsonp” , jsonpCallback: “回调” , 成功:功能(数据){ // TODO成功 }, 错误:函数(数据){ // TODO失败 } });
限制调用方式为get,数据类型为jsonp。后端也必须响应JSONPObject对象。
@ResponseBody @RequestMapping(value =“/ getDOC”,method = RequestMethod.GET) 公共JSONPObject getDOC(HttpServletRequest请求,字符串回调){ 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” ); 尝试{ 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(“文档不能为空!” ); } } 捕获(例外E1){ baseReturn.setCode(ReturnType.FAIL); baseReturn.setMsg(e1.getMessage()); log.error(e1.getMessage()); 返回 新的JSONPObject(callback,baseReturn); } MailEntity mailEntity = new MailEntity(); mailEntity.setCompany(公司); mailEntity.setDepartments(部门); mailEntity.setDoc(DOC); mailEntity.setEmail(电子邮件); mailEntity.setJob(工作); mailEntity.setName(名称); mailEntity.setPhone(电话); 尝试{ iMailClent.sendHtmlMail(mailEntity); baseReturn.setCode(ReturnType.SUCCESS); } 捕获(例外五){ e.printStackTrace(); baseReturn.setCode(ReturnType.FAIL); baseReturn.setMsg( “发送邮件失败!” ); log.error(e.getMessage()); } 返回 新的JSONPObject(callback,baseReturn); }
今天得到高人指点,原来有一种更加简便的方法,可以实现。不过原理肯定都是一样的,通过给请求添加消息头来设置跨域访问,这点是无疑的。新的解决办法就是给控制器或方法添加@CrossOrigin注解,具体详情请参考:http://spring.io/blog/2015/06/08/cors-support-in-spring-framework
@ResponseBody @RequestMapping(value =“/ getDOC”,method = RequestMethod.POST)公共BaseReturn getDOC(@RequestBody MailEntity mailEntity,HttpServletRequest请求,HttpServletResponse响应,HttpSession httpSession){ @CrossOrigin // 使用注解方式添加跨域访问消息头 log.info( “执行控制器HomeController.getDOC”);