华软项目总结

张喜硕

引言

上课,上实验,写文档,终于有时间写博客了。

我觉得这学期的Android实验上的还是很有意义的,课上,与我的舍友张一帆(自学Android及相关框架,有过Android比赛项目经验)一起讨论了Android的架构分层设计,以及对RetrofitRxAndroid框架的封装。

经过在实验中的学习,以及请教了一些在Android界算是有小有经验的人之后,发现自己年初对Android实验设计的有些问题:

clipboard.png

年初计划使用Data-BindingFragmentation实现单Activity架构,后来发现这样并不好。

  1. Data-Binding学习成本太高,且对原项目结构破坏性较大,对新人学习并理解Android无益。
  2. Activity架构虽然很优秀,但实际项目中仍然是多Activity+多Fragment架构,去追求单Activity意义不大,手动管理Fragment会十分麻烦。

发现错误,就改吧。目前已经在实验中引入并应用了ButterKnifeLitepalRetrofitRxAndroid等框架,感觉技术上应该不会有太大变化。以后再一起和大家分享一下我在Android方面的学习收获。

同时,华软虚拟化管理系统1.0版本正式完成,本周花费整三天完成了项目发布及部署文档的撰写(感谢潘佳琦,为了尽快交付,MySQL的安装与配置文档是他帮我写的,写得非常好)。

现在再回想华软项目,还是存在很多细节当时没有考虑到,在此进行反思与总结。

反思

笨拙的异常处理

后台设计得没什么问题:当发生错误时,后台会抛出异常,全局异常处理处理掉该异常,并将错误信息返回给前台。

笨拙在前台的拦截器这里:

clipboard.png

起初设计的是拦截器处理掉所有异常,并给予用户友好的提示,这样订阅时就不用处理error了。

当需要的时候,再去写error方法,比如登录时要在error里提示用户名或密码错误的提示信息。

拦截器处理异常,为了拦截器能准确地提示错误信息,所以扩展了HTTP状态码,对512等状态码扩展了新的含义。

switch (error.status) {
    case 401:
        if (this.router.url !== '/passport/login') {
            this.msg.error('用户认证发生错误');
            // noinspection JSIgnoredPromiseFromCall
            this.router.navigateByUrl('/passport/login');
        }
        break;
    case 403:
        this.msg.error('访问被拒绝, ' + error.error);
        break;
    case 404:
        this.msg.error('资源不存在, ' + error.error);
        break;
    case 502:
        this.msg.error('服务器网关错误,请联系系统管理员');
        break;
    case 504:
        this.msg.error('服务器网关请求超时,请联系系统管理员');
        break;
    case 512:
        this.msg.error('数据同步异常,' + error.error);
        break;
    case 513:
        this.msg.error('主机操作异常,' + error.error);
        break;
    case 514:
        this.msg.error('访问被拒绝异常,' + error.error);
        break;
}

当时写完这个拦截器的时候心里还是挺爽的,心想,以后可再也不用管理error了,多省事。现在再看看这个拦截器,说不上来什么原因,就是感觉怪怪的。

因为拦截器中是一个通用的提示信息,所以就出现了有时候需要在拦截器里加提示,有时候需要在error里提示,不想拦截器提示信息。

后来反思了一下,自定义状态码应该是合理的,也就是后台返回512513之类的,前台能直接通过状态码准确地判断当前后台到底哪错了。

但是这个拦截器这样写,就变成了,后台一个状态码对应一个提示信息,相当于我这个拦截器和后台抛出的异常绑定了,所以有时候虽然也是那个错,但是在这个界面提示出来就显得格格不入。

奇怪就奇怪在前台误解了自定义状态码的本质,自定义的状态码其实不是我后台有什么,前台就要拦截什么,新加一个状态码,就是为了前台可以更准确地提示信息,而不是一个500服务器错误

clipboard.png

改正:以后拦截器只处理通用的状态码,如:401跳转到登录,403提示访问被拒绝。而一些涉及到具体业务的状态码,还是应该放到onError方法中处理。

不完善的Loading

这是上次开会的时候晨澍提出来的,友好起见,当网络请求的时候应该显示Loading的动画。

想起来NG-ALAIN其实是为我们封装好了的,只是没有启用。

其实自己实现原理也简单,就是装饰器模式:

clipboard.png

对原生的HttpClient进行装饰一下,组合一个带LoadingYunzhiHttpClient

以后Service请求就使用YunzhiHttpClient,发起时,将Loading置为true,数据回来的时候,将Loading置为false

组件中如果想用怎么办呢?直接注YunzhiHttpClient,因为在同一个模块中是单例的,所以直接使用注入的YunzhiHttpClientLoading来控制加载动画是否显示。

改正:使用此方式添加Loading动画。

字段名与数据结构分离

@Entity
public class HostGroup {

    ...

    // 和电脑多对多
    @ManyToMany
    @JsonView({NoneJsonView.class,
            HostGroupJsonView.getAllGroups.class,
            HostGroupJsonView.getGroupById.class,
            UserJsonView.getCurrentLoginUser.class
    })
    private List<Host> hostList = new ArrayList<>();

    ...
    
}

HostGroup中有字段是hostList,存储计算机列表。

具体的场景忘了,好像是潘佳琦在写功能的时候,我给提了点思路,突然一想,如果这个计算机存的是个Set,那就不用这样费事了。

假设我们这样改:

private Set<Host> hostSet = new HashSet<>();

后台是简单了,前台表示很无辜。

ListSet,都是Json里的[],前台绑定的都是Array,我不管你后台怎么存,但是请你改数据结构的时候不要牵连前台。

既然ListSet在前台看起来一样,那为什么不改成hosts呢?后台数据结构随便改,对前台无影响。

改正:以后再有新实体,字段名与数据结构分离。

使用HTTPS

使用BASIC认证方式进行登录,前台将用户名和密码进行Base64加密传给后台。

HTTP请求,在网络传输过程中黑客可以直接拦截数据,并查看headerBase64解密很容易。

clipboard.png

既然大势所趋,那以后要求安全的项目还是使用HTTPS吧。

简单学习了一下,SpringBoot配置SSL需要证书,证书可以买也可以自己生成。既然能自己生成,为什么还要买呢?HTTPS证书好像还挺贵呢?

clipboard.png

无意间点开天猫的cookie,发现里面只认识XSRF-TOKEN,其他的都不知道。仔细想了一下,应该是天猫对安全的要求很高,不光是HTTPS保证数据传输的安全,更重要的是要保证发起请求的一定是客户本人,可能有好多算法的验证,保证用户不受损失。

想想我写的,用户的token如果被窃取了,谁访问都行。

看来在数据安全的道路上,我们还有很多路要走。

团队文档仓库

写华软部署文档的时候发现,写一个软件如何安装的教程真的是太困难了,并且如何再有项目,再写文档,还需要再写一遍。

可以直接建一个软件安装的文档仓库,再写部署文档,直接说我需要mysql,需要nginx

clipboard.png

直接在adoc中使用文件包含,将网上的这个adoc文件包含到我的文档中,就好像是自己写的一样,其实是外部引进来的。

Angular架构

clipboard.png

大家看图,这是我的前台设计思路。

多模块主要是在NG-ALAIN那里学习的,此架构设计适用于权限分配系统,因为采用loadChildren动态加载模块,也就是说,只有当用户访问/student这个路由时,才会加载学生管理Module,而不是不管有没有这个模块的权限,直接都交给浏览器去加载。

Core Module,被学生管理等实际的业务Module引用,该模块引入外部第三方组件。

包含基础实体,即与后台对应的实体,拓展实体,实际项目中发现不仅需要基础实体,还需要根据组件要的数据结构自己构建实体并传过去。

基础组件、基础过滤器、Service,都放在这里,这样在业务组件里想用就用,很方便。

设计出来了,感觉付诸实践时应该还是有所困难,毕竟目前用的是NG-ALAIN现成的,以后需要自己搭。

点赞Angular

最后为Angular点个赞,经过一个项目的洗礼,发现技术选型是正确的,选择Angular是多么的明智。

我们追随的一直是国外的脚步,VAR三者,肯定不用Vue,毕竟TypeScript都不支持。

所以国外的主流技术一直是AngularReact,两者都支持TypeScript,只是在设计思想上有所不同。

GoogleFacebook都是互联网巨头,我们中国的互联网企业与之相比根据不算什么。(去年Facebook的股票跌了6个京东)

Angular是框架,完善,直接把Angular一安装,什么网络请求,什么路由都有了,直接拿来用。

React是库,小巧灵活,需要整合其他库才能开发应用,在Facebook改协议之前,React当之无愧的前端第一框架。

Facebook改了开源协议,就被Apache基金会封杀,同时国内全面弃用React,所以国内涌现了无数类React框架。

即在不修改原React项目的前提下,只修改依赖的框架,框架对外提供的api相同,即可实现无缝切换。

clipboard.png

最优秀的类React框架要数京东的Nerv,性能非常好。京东主页采用该框架构建。

之前看到过经过前端的性能优化博客,采用自己设计的链表优化性能,现在也算是明白了面试官的真意。能当上面试官的,肯定都是通读开源项目源码或自己写框架级别的人物,人太多,基础的框架使用是个人学习学习官方文档都会,怎么筛选呢?然后面试官写框架的技术功底就用上了。

所以,你进不去阿里,不是你不够优秀,是你不适合写框架。

总结

总有一天,我们也要写一款属于自己的框架。

阅读 1.4k

Tomorrow
明天,你好

浅梦辄止,书墨未浓。

2k 声望
417 粉丝
0 条评论

浅梦辄止,书墨未浓。

2k 声望
417 粉丝
文章目录
宣传栏