前言

第一次正儿八经的写博客实在有点不知道怎么开头好,所学的东西也不够系统,我相信我写的东西瞄准了一个点去写,无论从哪里开始,都会让人觉得有点突然,但是,我也没办法从所谈主题的起源开始谈,所以不纠结这个次序关系了,有关主题的前后我就稍微介绍一些,主要围绕我所遇到的问题和如何去解决来谈吧。

我使用的框架是springboot+angularjs ,内容主要包括:
- 为什么需要跨域
- js跨域请求
- 使用localStorage替代本地Cookies
- 使用token替代跨域发送Cookies

下面主要针对以上几点来分别说说

为什么需要跨域

我们这个俄项目是使用springboot+angularjs开发的,web端顺利开发结束,接下来是手机端,手机端直接使用html在电脑端运行也开发的比较顺利,因为是直接使用的PC端浏览器,所以和web端开发是没有区别的,当然,手机端的浏览器也同样不会有什么问题。但是我们公司项目能打包成android和ios的app,android和ios都支持webview,按理直接把url告诉webview然后去请求服务器访问也没什么问题,毕竟通过webview的形式,理论上就相当于使用了android和ios提供的一个浏览器而已,只是它隐藏了url。
考虑到手机上的切换效果,app开发的同事会使用多个webview来切换渲染数据,像详情之类的页面,需要开启新的webview,这样问题就来了,体验就非常的差了,非常的卡!非常的慢!为什么?

我简单的做了个比较.

Web端打开新页面过程

App端打开新页面过程

过程比较:

过程 web app
第一次加载
切换页面

由此可见,使用android或ios嵌套webview来达到一般原生的切换效果和访问服务器的速度,是很难的!

此时我们想到三个方案:

  1. app端只开启一个webview。

    • 优点:可以减少切换页面时重新开启(特定的导航页面在切换时没有被关闭掉,但不刷新)webview的时间。
    • 缺点:b)页面效果可能较差,并且ios打包后有可能影响appstore审核。
  2. 服务器端后台文件和前端文件分开部署。

    • 优点:稍微加快静态页面访问速度。
    • 缺点:提升速度不明显。
  3. html文件本地化,打包进app文件中。

    • 优点:不需要从服务器端请求html再返回到webview中加载,节省了加载html的时间,速度将有较大提升。
    • 缺点:需要对当前项目做很多修改(文件访问路径方面,后续webview对接也给我们带来了许多困难)

虽然是想到了三个可行方案,但第一种方案直接被pass,第二种方案速度提升非常不明显,那只能考虑采用第三种了,将原先html文件与java文件共同打包成一个war包,然后现在需要将html文件直接打包进app文件,必然就需要js进行跨域请求了。

JS跨域请求

s跨域请求需要在js和服务器端都有申明跨域,具体如下:

  • 原生ajax 请求可以这样写:
$.ajax({
            type: 'POST',url: "/user",data: {
                'phone': 'xxxxxxxx','password':'xxxxxxx'
            },withCredentials: true,// 跨域
            dataType: 'json'
        }).success(function(){

        });
  • angularjs
$http.get(url,{ 
            withCredentials : true    //跨域
});
  • java过滤器代码
@Component
public class CorsFilter extends OncePerRequestFilter {

@Override
protected void doFilterInternal(HttpServletRequest request,HttpServletResponse response,FilterChain filterChain) throws servletexception,IOException {
        response.setHeader("Access-Control-Allow-Origin",request.getHeader("origin"));   //允许跨域
        response.setHeader("Access-Control-Allow-Credentials","true");
        if ("OPTIONS".equals(request.getmethod())) {
            response.setHeader("Access-Control-Allow-Methods","POST,GET,PUT,OPTIONS,DELETE");
            response.setHeader("Access-Control-Max-Age","3600");
            response.setHeader("Access-Control-Allow-Headers","Origin,X-Requested-With,Content-Type,Accept,Authorization");
        }
        filterChain.doFilter(request,response);
    }
}
response.setHeader("Access-Control-Allow-Origin",request.getHeader("origin"));

这行代码是有点意思的,我这里没有将值直接设为“*”号,将值设为星号无法跨域发送cookies,需要发送cookies的可以设置成

request.getHeader("origin");

这样跨域发送请求就没有问题了。

使用localStorage替代本地Cookies

跨域后有个问题真的让我头疼了很久,虽然成功跨域了,数据也都已经成功返回并渲染页面了。但依然有几个问题。

  • 登录问题

比如,登录成功后session在后台保存了用户会话信息,再次发送请求获取数据时,再次读取session验证用户身份时,始终无法取到登录时存储的会话信息,因为没有获取到cookies,而服务器与浏览器之间的会话sessionID是保存在cookies中的,为什么没有获取到cookies,是因为服务器端允许跨域是这样设置的:

response.setHeader("Access-Control-Allow-Origin","*");   //允许跨域

origin设置成“*”,是不支持文件形式的访问所发送cookies的,需要怎么改呢?改成与本地文件一样的路径形式就成,比如,在我的机器上如果html路径是 file:///D:test.html,我在java端允许跨域就必须设置成

response.setHeader("Access-Control-Allow-Origin","file://");   //允许跨域 

才能获取到cookies,考虑到html打包进ios或android app中的路径可能不同,则将路径设为:

response.setHeader("Access-Control-Allow-Origin",request.getHeader("origin"));

这点可让我找了很久,“*”居然不行,我到现在也没想通。

  • 本地cookies保存

登录的问题解决了,发送cookies也没有问题了,但是本地文件的cookies保存又出了问题,无法保存!也许有办法只是我没找到。

考虑到不同浏览器之间的差别和ios对cookies的可能支持不太好的问题,决定打算使用用localStorage在本地文件保存一些信息,因为localStorage是html5自带的,不存在不同浏览器之间的差别。
localStorage的使用也比较简单,我在这个项目中也只使用了几个方法。

首先申明一个全局的storage,因为本身用他的目的就是替代cookies保存用户状态,当然是全局的啦

var storage = window.localStorage;

然后保存值

storage.setItem('userid','深蓝浅蓝的天')

取值

storage.getItem('userid');

退出清空storage

storage.clear();

so easy,我很快就搜索全部代码将cookies的使用全部替换掉了(注意搜索路径哦),但是问题到了这里还是没有结束,在电脑上测试完了本地文件的访问都没有了问题,但是用android或ios打包html文件又出现问题了。

post方法可正常跨域,因为它的headers中的origin是有指的,而get方法origin却是是null,而服务器端对于null是不接收跨域发送cookies,所以cookies还是要忍痛替换掉。++

使用token替代跨域发送Cookies

cookies既然有那么多的问题,而且可能在某些地方支持不太好,之后若是需要对app进行功能扩展,第三方授权之类的,也还是要走token,所以索性直接换掉cookies,当然,我在js中是有区分web/ios/android的,所以手机浏览器端仍然延续使用cookies,ios和android打包文件形式则用token。

虽然在服务器代码中session几乎无处不在,但要替换成token也不会特别麻烦,将原先保存在session中的数据,使用token作为一个键保存在redis中,然后在用户请求服务器时,拦截请求并取出token,再从redis中取出数据手动赋值到session中就可以了,只是我把原先服务器接收请求并取出cookies中sessionID,从而取出对应session的动作替换了下而已。

简单图示就是:
- 服务器处理cookies

第一次请求服务器

第二次请求服务器

大致过程如上图,用markdown不会画图,下次画个好点的~~

  • token替换cookie
    第一次请求服务器

    第二次请求服务器

过程几乎是一样的,只是我在拦截中做了一步处理,以便我不需要大幅度改变原有代码,如下:

@Override
public boolean preHandle(HttpServletRequest request,Object handler) throws Exception {
        HttpSession session = request.getSession();
        if (session.getAttribute("userId") == null) {
            String token = request.getHeader("Authorization");
            if (token != null && !token.equals("null")) {
                String jsonToken = (String) redistemplate.opsForValue().get(token);
                UserToken userToken = JSON.parSEObject(jsonToken,UserToken.class);
                if (userToken != null) {
                    session.setAttribute("userId",userToken.getUserId());
                }
            }
        }
        return true;
    }

过程大致如此。

第一次写这么长的博文,欢迎指正。

angularjs跨域请求,html5封装进android与ios的更多相关文章

  1. 使用HTML5做的导航条详细步骤

    这篇文章主要介绍了用HTML5做的导航条详细步骤,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  2. 详解HTML5中的picture元素响应式处理图片

    这篇文章主要介绍了详解HTML5中的picture元素响应式处理图片,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  3. html5利用canvas实现颜色容差抠图功能

    这篇文章主要介绍了html5利用canvas实现颜色容差抠图功能,非常不错,具有一定的参考借鉴价值,需要的朋友可以参考下

  4. HTML5拖拽功能实现的拼图游戏

    本文通过实例代码给大家介绍了HTML5拖拽功能实现的拼图游戏,代码简单易懂,非常不错,具有一定的参考借鉴价值,需要的朋友参考下吧

  5. HTML5实现直播间评论滚动效果的代码

    这篇文章主要介绍了HTML5实现直播间评论滚动效果的代码,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  6. 使用Html5多媒体实现微信语音功能

    这篇文章主要介绍了使用Html5多媒体实现微信语音功能,需要的朋友可以参考下

  7. HTML5 播放 RTSP 视频的实例代码

    目前大多数网络摄像头都是通过 RTSP 协议传输视频流的,但是 HTML 并不标准支持 RTSP 流。本文重点给大家介绍HTML5 播放 RTSP 视频的实例代码,需要的朋友参考下吧

  8. html5 拖拽及用 js 实现拖拽功能的示例代码

    这篇文章主要介绍了html5 拖拽及用 js 实现拖拽,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  9. HTML5自定义视频播放器源码

    这篇文章主要介绍了HTML5自定义视频播放器源码,非常不错,具有一定的参考借鉴价值,需要的朋友可以参考下

  10. HTML5新增form控件和表单属性实例代码详解

    这篇文章主要介绍了HTML5新增form控件和表单属性实例代码详解,需要的朋友可以参考下

随机推荐

  1. Angular2 innerHtml删除样式

    我正在使用innerHtml并在我的cms中设置html,响应似乎没问题,如果我这样打印:{{poi.content}}它给了我正确的内容:``但是当我使用[innerHtml]=“poi.content”时,它会给我这个html:当我使用[innerHtml]时,有谁知道为什么它会剥离我的样式Angular2清理动态添加的HTML,样式,……

  2. 为Angular根组件/模块指定@Input()参数

    我有3个根组件,由根AppModule引导.你如何为其中一个组件指定@input()参数?也不由AppModalComponent获取:它是未定义的.据我所知,你不能将@input()传递给bootstraped组件.但您可以使用其他方法来做到这一点–将值作为属性传递.index.html:app.component.ts:

  3. angular-ui-bootstrap – 如何为angular ui-bootstrap tabs指令指定href参数

    我正在使用角度ui-bootstrap库,但我不知道如何为每个选项卡指定自定义href.在角度ui-bootstrap文档中,指定了一个可选参数select(),但我不知道如何使用它来自定义每个选项卡的链接另一种重新定义问题的方法是如何使用带有角度ui-bootstrap选项卡的路由我希望现在还不算太晚,但我今天遇到了同样的问题.你可以通过以下方式实现:1)在控制器中定义选项卡href:2)声明一个函数来改变控制器中的散列:3)使用以下标记:我不确定这是否是最好的方法,我很乐意听取别人的意见.

  4. 离子框架 – 标签内部的ng-click不起作用

    >为什么标签标签内的按钮不起作用?>但是标签外的按钮(登陆)工作正常,为什么?>请帮我解决这个问题.我需要在点击时做出回复按钮workingdemo解决方案就是不要为物品使用标签.而只是使用divHTML

  5. Angular 2:将值传递给路由数据解析

    我正在尝试编写一个DataResolver服务,允许Angular2路由器在初始化组件之前预加载数据.解析器需要调用不同的API端点来获取适合于正在加载的路由的数据.我正在构建一个通用解析器,而不是为我的许多组件中的每个组件设置一个解析器.因此,我想在路由定义中传递指向正确端点的自定义输入.例如,考虑以下路线:app.routes.ts在第一个实例中,解析器需要调用/path/to/resourc

  6. angularjs – 解释ngModel管道,解析器,格式化程序,viewChangeListeners和$watchers的顺序

    换句话说:如果在模型更新之前触发了“ng-change”,我可以理解,但是我很难理解在更新模型之后以及在完成填充更改之前触发函数绑定属性.如果您读到这里:祝贺并感谢您的耐心等待!

  7. 角度5模板形式检测形式有效性状态的变化

    为了拥有一个可以监听其包含的表单的有效性状态的变化的组件并执行某些组件的方法,是reactiveforms的方法吗?

  8. Angular 2 CSV文件下载

    我在springboot应用程序中有我的后端,从那里我返回一个.csv文件WheniamhittingtheURLinbrowsercsvfileisgettingdownloaded.现在我试图从我的角度2应用程序中点击此URL,代码是这样的:零件:服务:我正在下载文件,但它像ActuallyitshouldbeBook.csv请指导我缺少的东西.有一种解决方法,但您需要创建一个页面上的元

  9. angularjs – Angular UI-Grid:过滤后如何获取总项数

    提前致谢:)你应该避免使用jQuery并与API进行交互.首先需要在网格创建事件中保存对API的引用.您应该已经知道总行数.您可以使用以下命令获取可见/已过滤行数:要么您可以使用以下命令获取所选行的数量:

  10. angularjs – 迁移gulp进程以包含typescript

    或者我应该使用tsc作为我的主要构建工具,让它解决依赖关系,创建映射文件并制作捆绑包?

返回
顶部