在这一次的大作业中,我做的工作总的来说包括了服务端的部署,服务端框架的搭建,api的设计,还有安卓前端的编码。不仅接触使用了之前不了解的技术,对之前学过的技术也有了进一步的加深。
PSP阶段 | 耗时(%) | |
---|---|---|
计划 | 20 | |
确定项目范围 | 10 | |
预估工作量和时间 | 5 | |
任务分工 | 5 | |
开发 | 70 | |
分析需求 | 5 | |
生成设计文档 | 5 | |
设计复审 | 5 | |
代码规范 | 5 | |
具体设计 | 5 | |
具体编码 | 30 | |
代码复审 | 5 | |
测试 | 10 | |
报告 | 10 | |
测试报告 | 3 | |
计算工作量 | 2 | |
事后总结,提出过程改进计划 | 5 | |
合计 | 100 |
在这一次的大作业中,我做的工作总的来说包括了服务端的部署,服务端框架的搭建,api的设计,还有安卓前端的编码。不仅接触使用了之前不了解的技术,对之前学过的技术也有了进一步的加深。
我们的api设计用到的是restful风格的api。进行交互展示用到的是swagger。
https://blog.csdn.net/canot/article/details/55051346
主要是采用swagger Editor来编写我们设计的restful api,定义不同url对应的行为,发送和接收的model,状态码等不同的情况,主要用的是json和yaml,具体的语法可参考上述链接中的例子
主要采用的是springboot,主要是对spring的一些原有框架进行了整合,减少了繁琐的配置,同时又有相对成熟的体系,很多功能无需自己实现。
https://blog.csdn.net/qq_35571554/article/details/82184122
Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程。该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置。
简单的来说就是,只需几个jar和一些简单的配置,就可以快速开发项目。
2、点击next,填写项目包的一些信息
4、由上图可知,java是存放业务代码,现在com.xz.blog包下除了启动类,其余都是空的,需要我们来添加controller、mapper、model、service等包;resources是存放项目资源,templates放置模板(页面)。推荐使用thymeleaf,也可以集成Jsp,static放置静态资源。js,images等。
由于我此时实现的服务端主要是rest风格的api,所以不需要处理前端的网页静态文件的请求和渲染。
简单的说一下总体的结构,我们通过上述步骤创建成功项目以后,并创建上述对应的文件夹,基本的项目结构就已经成型了。
(1)pom.xml中主要是依赖文件,maven构建项目的时候就要从这个文件中读取项目相关的依赖。在创建项目时勾选的已经默认帮我们把依赖写好在了这里,如果我们在项目编码过程中发现还需要一些第三方的依赖,则可以添加在这里。
(2)appllication.properties:这个文件中主要填写的是一些配置信息,比如说mybaties连接的数据库名,密码,model类存放的包名;redis连接的用户名和密码等都是在这里设置的。
(3)源代码:
• Controller:控制层,处理HTTP请求,收集参数,检查参数类型和合法性,并调用相应的Service
• Service:服务层,处理业务逻辑
• mapper:处理数据库的交互
• Model:数据层,数据模型
简单的说,我们可以认为,controller中是处理不同的url的,对于restful的api来说,我们可以在controller中为每个资源定义一个类处理相关的CRUD请求,而Service则是处理业务逻辑,和Controller并没有必然的对应关系,可以在一个controller中调用多个service,主要取决与业务的模块划分,mapper中主要是数据库的交互mysql语句,对不同的model有不同的mysql语句。而model则对应着数据库中的表。
具体的代码可参考上述链接或我们的github地址
https://github.com/sysuz4/AppServer
http://www.ruanyifeng.com/blog/2018/07/json_web_token-tutorial.html
JWT可以说是一种token的规范,由于session在集群服务器时使用不太方便,所以就有了token的产生。
(1)header:Header 部分是一个 JSON 对象,描述 JWT 的元数据,包括像签名部分所用的算法和token的类型
{
"alg": "HS256",
"typ": "JWT"
}
上面代码中,alg属性表示签名的算法(algorithm),默认是 HMAC SHA256(写成 HS256);typ属性表示这个令牌(token)的类型(type),JWT 令牌统一写为JWT。
最后,将上面的 JSON 对象使用 Base64URL 算法(详见后文)转成字符串。
(2)payload:Payload 部分也是一个 JSON 对象,用来存放实际需要传递的数据。JWT 规定了7个官方字段,供选用
iss (issuer):签发人
exp (expiration time):过期时间
sub (subject):主题
aud (audience):受众
nbf (Not Before):生效时间
iat (Issued At):签发时间
jti (JWT ID):编号
当然,也可以自己定义一些字段来发送信息,注意,JWT 默认是不加密的,任何人都可以读到,所以不要把秘密信息放在这个部分。
最后,这个 JSON 对象也要使用 Base64URL 算法转成字符串。
(3)signature:Signature 部分是对前两部分的签名,防止数据篡改。
首先,需要指定一个密钥(secret)。这个密钥只有服务器才知道,不能泄露给用户。然后,使用 Header 里面指定的签名算法(默认是 HMAC SHA256),按照下面的公式产生签名。
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)
算出签名以后,把 Header、Payload、Signature 三个部分拼成一个字符串,每个部分之间用"点"(.)分隔,就可以返回给用户。
客户端收到服务器返回的 JWT,可以储存在 Cookie 里面,也可以储存在 localStorage。
此后,客户端每次与服务器通信,都要带上这个 JWT。你可以把它放在 Cookie 里面自动发送,但是这样不能跨域,所以更好的做法是放在 HTTP 请求的头信息Authorization字段里面。然后服务端收到token以后首先用相同的算法进行签名,检测有无篡改,然后用base64进行解码,取出payload中的信息进行授权验证,得到用户信息和判断是否token已经过期。
这样最大的好处就是在服务端无需对token进行存储,只需要用相同的签名算法则可以进行验证,这样在多个集群服务器上时就避免了同步的问题。
部署主要用到了docker,jenkins,nginx等技术
自动构建github并部署到服务器上可以参考我的这篇文章
https://blog.csdn.net/Artemis16340304/article/details/90679931
至于nginx,当然也可以用docker来进行容器化的安装,然后就是对nginx进行配置,达到静态服务器,分布式集群,反向代理等的目的
以下是nginx的一个docker安装教程
https://blog.csdn.net/wugenqiang/article/details/86513257
然后主要的工作是在与nginx配置文件的编写,简单的功能说明与配置如下
https://www.cnblogs.com/jimmy-muyuan/p/5424329.html
1、静态HTTP服务器
首先,Nginx是一个HTTP服务器,可以将服务器上的静态文件(如HTML、图片)通过HTTP协议展现给客户端。
配置:
server {
listen 80; # 端口号
location / {
root /usr/share/nginx/html; # 静态文件路径
}
}
2、反向代理服务器
客户端本来可以直接通过HTTP协议访问某网站应用服务器,网站管理员可以在中间加上一个Nginx,客户端请求Nginx,Nginx请求应用服务器,然后将结果返回给客户端,此时Nginx就是反向代理服务器。
server {
listen 80;
location / {
proxy_pass http://192.168.20.1:8080; # 应用服务器HTTP地址
}
}
既然服务器可以直接HTTP访问,为什么要在中间加上一个反向代理,不是多此一举吗?反向代理有什么作用?继续往下看,下面的负载均衡、虚拟主机等,都基于反向代理实现,当然反向代理的功能也不仅仅是这些。
3、负载均衡
当网站访问量非常大,网站站长开心赚钱的同时,也摊上事儿了。因为网站越来越慢,一台服务器已经不够用了。于是将同一个应用部署在多台服务器上,将大量用户的请求分配给多台机器处理。同时带来的好处是,其中一台服务器万一挂了,只要还有其他服务器正常运行,就不会影响用户使用。
Nginx可以通过反向代理来实现负载均衡。
upstream myapp {
server 192.168.20.1:8080; # 应用服务器1
server 192.168.20.2:8080; # 应用服务器2
}
server {
listen 80;
location / {
proxy_pass http://myapp;
}
}
以上配置会将请求轮询分配到应用服务器,也就是一个客户端的多次请求,有可能会由多台不同的服务器处理。可以通过ip-hash的方式,根据客户端ip地址的hash值将请求分配给固定的某一个服务器处理。
upstream myapp {
ip_hash; # 根据客户端IP地址Hash值将请求分配给固定的一个服务器处理
server 192.168.20.1:8080;
server 192.168.20.2:8080;
}
server {
listen 80;
location / {
proxy_pass http://myapp;
}
}
另外,服务器的硬件配置可能有好有差,想把大部分请求分配给好的服务器,把少量请求分配给差的服务器,可以通过weight来控制。
upstream myapp {
server 192.168.20.1:8080 weight=3; # 该服务器处理3/4请求
server 192.168.20.2:8080; # weight默认为1,该服务器处理1/4请求
}
server {
listen 80;
location / {
proxy_pass http://myapp;
}
}
4、虚拟主机
有的网站访问量大,需要负载均衡。然而并不是所有网站都如此出色,有的网站,由于访问量太小,需要节省成本,将多个网站部署在同一台服务器上。
例如将www.jim.com和www.tim.com两个网站部署在同一台服务器上,两个域名解析到同一个IP地址,但是用户通过两个域名却可以打开两个完全不同的网站,互相不影响,就像访问两个服务器一样,所以叫两个虚拟主机。
配置:
server {
listen 80 default_server;
server_name _;
return 444; # 过滤其他域名的请求,返回444状态码
}
server {
listen 80;
server_name www.jim.com; # www.jim.com域名
location / {
proxy_pass http://localhost:8080; # 对应端口号8080
}
}
server {
listen 80;
server_name www.tim.com; # www.tim.com域名
location / {
proxy_pass http://localhost:8081; # 对应端口号8081
}
}
在服务器8080和8081分别开了一个应用,客户端通过不同的域名访问,根据server_name可以反向代理到对应的应用服务器。
虚拟主机的原理是通过HTTP请求头中的Host是否匹配server_name来实现的,有兴趣的同学可以研究一下HTTP协议。
另外,server_name配置还可以过滤有人恶意将某些域名指向你的主机服务器。
除此之外,nginx中loaction的编写与匹配也是一门学问
https://www.cnblogs.com/lidabo/p/4169396.html
https://www.jianshu.com/p/d3fb148cb5eb
安卓前端的话,这次作业主要的收获就是学会了用别人的写好的控件,作为依赖添加到我们的页面中,不用自己从头从官方的基本控件开始实现
https://github.com/wasabeef/awesome-android-ui
同时也回顾了当初学安卓的时候的知识,以下是当时不同功能作业的报告地址
https://gitee.com/Artemis_lin/projects