开发日记——跨域访问

开发背景:

        一个hibernate+JPA的系统功能拓展,要求与另一个部门的同种系统进行交互,而两个系统开发时都没有做外部扩展的接口设计。

        虽说是两个同样的系统,但由于部门不同地域不同等因素,要求得有数据权限。而这个系统当初设计开发时就没有预留外部扩展的计划,所以不能共用同一个数据库,而是直接分成两个系统对需要的数据进行交互即可。

设计思路

        要做两个系统的数据交互,一般来说会使用WebSocket做接口,而既然是部门内部使用,不需要考虑接口安全等因素(这里是为了偷懒,大家实际开发中还是要考虑周全!!),直接使用httpservlet做就简单多了。更或者,直接做一个Controller用于返回数据,然后前端带着数据去请求另一个系统,另一个系统再写一个Controller用于接收。。(最简单的方式了吧?)

        OK,既然方案有了,那就开始实施吧!

开发过程

分别写发送和接收

  • 系统A发送数据

        首先在原有的系统A上添加了 发送 按钮,在选择好要传输的数据单后点击发送,Controller将数据返回给前端,前端Ajax获取成功后在done()中嵌套Ajax方法用于请求系统B的接收地址。

  • 系统B接收数据

        在系统B中写了一个Controller用于接收请求,然后调用相应的service来保存数据。

问题及解决

        通过理论后设计并开发发送和接收方法,启动两个系统进行测试时发现一下问题:

  1. No ‘Access-Control-Allow-Origin’ header is present on the requested resource.

        出现这个异常的原因是前端Ajax访问的地址不在项目包下,属于跨域访问。而Spring没有做访问配置,浏览器出于安全考虑,限制访问本站点以外的资源。

跨域访问

        解决办法主要是跨域访问时在Head中加上Access-Control-Allow的配置信息,方式有很多,这个要根据自己的项目环境来选择。

        我的做法是写了一个CrossAccessFilter用于拦截访问请求,并全部加上允许跨域的头信息(再次强调我能这么做是因为系统只是内部使用,实际开发要根据需要做安全考虑!!):

public class CrossAccessFilter extends OncePerRequestFilter {

    protected final Logger logger = LoggerFactory.getLogger(getClass());

    public void crossAllows(HttpServletRequest request, HttpServletResponse response) {

        String o = request.getHeader("Origin");
        /* 允许跨域 */
        response.setHeader("Access-Control-Allow-Origin", o);
        /* 允许带cookie */
        response.setHeader("Access-Control-Allow-Credentials", "true");
        /* 允许请求的方式 */
        response.addHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS");
        /* 支持带头 */
        response.addHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, backToken, tgVersion, platform");
        /* 预检有效期 */
        response.addHeader("Access-Control-Max-Age", "172800");
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException {
        crossAllows(request, response);
        chain.doFilter(request, response);
    }
}

        然后再web.xml中配置filter,这样就可以跨域访问了:

<filter>
	<filter-name>crossFilter</filter-name>
	<filter-class>com.goertek.base.common.CrossAccessFilter</filter-class>
</filter>
<filter-mapping>
	<filter-name>crossFilter</filter-name>
	<url-pattern>/*</url-pattern>
</filter-mapping>
  1. NET::ERR_INCOMPLETE_CHUNKED_ENCODING 200 (OK)

        后台没有报错信息,查看前端NETWORK中发现代码200访问成功,但是数据传输失败。出现这个错误的原因是我没有把发送的数据转化为JSONObject,接收也没做相应的转换。

解决办法:
        首先引入JSONObject依赖:

这里要注意net.sf.json-lib是要求jdk版本的,这里选择jdk15

<dependency>
      <groupId>net.sf.json-lib</groupId>
      <artifactId>json-lib</artifactId>
      <version>2.2.3</version>
      <classifier>jdk15</classifier>
    </dependency>

        将发送的数据由Map转化为JSON

@RequestMapping(value = "/send/{id}")
@ResponseBody
public Object send(@PathVariable Integer id){
	Map<String, Object> send = outdepotService.send(id);
	Map<String, Object> row = (Map) send.get("row");
	JSONObject json = JSONObject.fromObject(row);
	return json.toString();
}

        接收端将JSON转换回来:

@RequestMapping("/accept")
public void accept(@RequestBody String json) {
	JSONObject jasonObject = JSONObject.fromObject(json);
    Map<String,Object> req = (Map<String,Object>)jasonObject;
    indepotService.accept(req);
}

有关jsonMaplist之间的转换。

        之后问题就解决了,成功实现两个系统的交互!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值