发表于: 2020-07-14 22:08:05
1 1488
今天完成的事情:
将项目部署到服务器。
这里打包的时候遇到了一点问题,对于自己手动导入的第三方jar包,需要在poml配置一下,具体如下:
1.首先在项目下新建一个lib文件夹,将需要引入的jar包放入:
2.然后加入依赖:
<dependency>
<groupId>com</groupId>
<artifactId>sdk</artifactId>
<version>1.2</version>
<scope>system</scope>
<systemPath>${project.basedir}/src/main/lib/com/sdk/1.2/sendcloud-sdk.jar</systemPath>
</dependency>
这样编译阶段不会报错,但是运行tomcat的时候会报错找不到这个jar包。
3.在WEB-INF文件夹下也建一个lib文件夹,将jar包放进去:
这样就可以完美运行了,部署到服务器也没问题。
不过总感觉这个方法有些累赘,不知道有没有更好的方法。
短信/邮箱防攻击策略:
本身阿里云短信接口是有一点的保护机制:一个手机号一小时只能发10条。
可以获取验证码前可以加入随机码。
或者将获取验证码按钮设为一分钟只能发送一条。
使用js加入一个计时器:
var counts = 60;
function settime(val) {
if(counts == 0) {
val.removeAttribute("disabled");
val.value = "获取验证码";
counts = 60;
return false;
} else {
val.setAttribute("disabled", true);
val.value = "重新发送(" + counts + ")";
counts--;
}
setTimeout(function() {
settime(val);
}, 1000);
}
效果如下:
任务总结:
任务耗时7天(7.7-7.14)
任务七主要是学会使用第三方API接口,主要是要看官方的API文档,里面都有详细的示例代码,依赖,SDK下载地址等等。
1.首先往表中添加新的几个字段:手机,邮箱,头像。
2.短信api:
任务推荐用容联云,虽然容联云注册就送8元测试经费,一条短信大概扣0.06元,不过容联云测试的时候只能给绑定的手机发送短信,最多可以绑定三个手机号。想给别的手机发短信必须实名认证而且买他的短信套餐,最低也要几百。。。
这里推荐使用阿里云的,注册之后送100条短信,使用支付宝实名认证之后,签名模板审核通过就可以给所有手机发送短信了。
主要思路:前端输入手机号请求验证码短信,后端收到手机号,生成随机码,调用短信接口将随机码发送到指定手机号,同时将随机码存入缓存,可以根据需要设置时限。前端输入验证码,后端接收到之后和缓存中的进行对比。
主要难点在于前端页面获取验证码和注册按钮,使用表单的话需要用到Ajax异步请求。
3.邮箱api:
直接使用sendcloud就可以,不过这个每天上限只有10条,测试的时候可能不太够用。这个和获取短信验证码大同小异,只需要将调用的接口换成发送邮件的即可。
主要思路:前端输入邮箱请求验证码短信,后端收到邮箱,生成随机码,调用邮件接口将随机码发送到指定邮箱,同时将随机码存入缓存,可以根据需要设置时限。前端输入验证码,后端接收到之后和缓存中的进行对比。
没什么难点,不过有个坑是sendcloud需要的依赖好像不能像阿里云一样直接在maven仓库找到,需要手动导入官网下载的第三方jar包,这样的话打包部署到服务器上时可能会打不上。解决方法前面写了。
4.图片上传:
这里可以直接使用阿里云OOS对象储存。注册之后送一个月免费时长。主要是审核方便,直接用支付宝登录即可,而且导入依赖也很方便。
使用方法也是差不多,直接导入依赖,然后修改官网的示例demo,写一个工具类,然后整合进自己的项目即可。
主要思路:前端上传图像文件,后端接收到文件,调用工具类将文件存到云端即可。
主要难点:这个难点可能有点多。
一个是前端使用input type=“file”上传文件的问题,后台使用MultipartFile接收文件时不要导错包了要用下面的:
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
不然时无法接收到文件的!!!
然后是如果这里也想用异步请求的话,不能像之前一样照葫芦画瓢了,要先var一个formData来保存文件:
function loadImg() {
var formData = new FormData();
formData.append("image",$("#image")[0].files[0]);
$.ajax({
type: 'POST',
url:"${pageContext.request.contextPath}/u/uploadImage",
data:formData,
processData: false,
contentType: false,
success: function (data) {
console.log(data);
console.log(status);
alert(data);
}
})
}
然后还有后端接收到的文件和上传接口所需要的文件类型是不一样的,也需要转换一下:
change是我在网上找的一个文件转换工具类。这一步可以直接整合到文件上传工具类中。
然后还有一个是上传图片的时候记得设置文件格式为image/jpg,不然默认会给你设置成jpeg,通过链接访问图片会直接下载,而不是预览。
其他的就没啥了。
最后再了解一下水印和防盗链,以及短信邮件防攻击,基本上任务就完成了。
深度思考:
1.什么是Annotation,怎么自定义Annotation,Annotation和XML的优缺点各是什么?
Annotation,就是注解。
Annotation 的优点
(1)保存在 class 文件中,降低维护成本。
(2)无需工具支持,无需解析。
(3)编译期即可验证正确性,查错变得容易。
(4)提升开发效率。
Annotation的缺点
(1)若要对配置项进行修改,不得不修改 Java 文件,重新编译打包应用。
(2)配置项编码在 Java 文件中,可扩展性差。
xml的优点
(1)xml 作为可扩展标记语言最大的优势在于开发者能够为软件量身【定制】适用的标记,使代码更加通俗易懂。
(2)利用 xml 配置能使软件更具扩展性。例如 Spring 将 class 间的依赖配置在 xml 中,最大限度地提升应用的可扩展性。
(3)具有成熟的验证机制确保程序正确性。利用 Schema 或 DTD 可以对 xml 的正确性进行验证,避免了非法的配置导致应用程序出错。
(4)修改配置而无需变动现有程序。
xml的缺点
(1)需要解析工具或类库的支持。
(2)解析 xml 势必会影响应用程序性能,占用系统资源。
(3)编译期无法对其配置项的正确性进行验证,或要查错只能在运行期。
(4)IDE 无法验证配置项的正确性无能为力。
(5)查错变得困难。往往配置的一个手误导致莫名其妙的错误。
(6)开发人员不得不同时维护代码和配置文件,开发效率变得低下。
(7)配置项与代码间存在潜规则。改变了任何一方都有可能影响另外一方。
(8)配置文件过多导致管理变得困难。
2.如何调用第三方API实现图片上传?
API(Application Programming Interface,应用程序编程接口),具体实现方法前面日报里有写。
3.怎么快速集成第三方服务组件,API和SDK的区别是什么?
SDK和API都是类似于公共服务的东西,都代表的是一种封装,只是封装的形式不一样:
SDK的封装是在客户端层面的一个library(也叫做“包”或者“库”),这个library提供一些客户端API接口,类似于已经写好了的函数,你只需要调用它就好了。SDK暴露出来的接口都是和语言相关的,如果SDK是用Java写的,就需要用Java去调用那个函数;如果是SDK是用Objective-C写的,就需要用Objective-C去调用那个函数。
API是封装在服务端层面的library,从网络服务的层面暴露出一些API接口,提供给使用这些服务的人去调用。因为封装在服务的层面,传输数据用的是网络协议(常用HTTP/TCP),就不需要管他是用什么语言实现的;
4.上传图片应该由前端或客户端直接上传到第三方存储服务,还是应该先上传到服务器,再由服务器上传到第三方?
两种方式都可以完成上传,但是后者还需占用服务端的带宽来上传文件,然后再由服务端上传;而前者仅占用客户端的资源,这样可以减轻服务端的压力。
5.怎么实现图片防盗链,缩略图,水印等功能?
前面日报有写。
6.为什么要使用第三方图片存储服务,好处是什么?
1,本地存储会有容量问题,存多了硬盘爆了
2,本地存储不利于扩展成集群,多台机器需要每台都存一份文件
3,本都存储会占用本机带宽,一个图片的大小抵得过好多个页面文本,不利于优化打开速度
4,本地存储单一目录文件过大会有效率问题
补充下其他优点:
1,直接符合动静分离设计,便于针对性优化加速。参考阿里云 OSS 自带 CDN 配置入口
2,不需要考虑扩容问题,一般都是第三方系统自动处理存储逻辑,自带物理目录优化方案,对外维持同一种访问路径
3,解耦后可扩展其他功能,例如加水印,裁剪,压缩等
7.怎么样将短信发送服务抽像成公共代码,可以在多个项目中复用?
public boolean getSms(String phone) {
logger.info("code:"+Rand_Code);
DefaultProfile profile = DefaultProfile.getProfile(regionId,accessKeyId,secret);
IAcsClient client = new DefaultAcsClient(profile);
CommonRequest request = new CommonRequest();
request.setSysMethod(MethodType.POST);
request.setSysDomain("dysmsapi.aliyuncs.com");
request.setSysVersion("2017-05-25");
request.setSysAction("SendSms");
request.putQueryParameter("RegionId", "cn-hangzhou");
request.putQueryParameter("PhoneNumbers", phone);
request.putQueryParameter("SignName", "任务七注册");
request.putQueryParameter("TemplateCode", "SMS_195872171");
request.putQueryParameter("TemplateParam", String.format("{\"code\":\"%s\"}", Rand_Code));
try {
CommonResponse response = client.getCommonResponse(request);
System.out.println(response.getData());
memCachedClient.set("code"+ phone,Rand_Code,new Date(1000*60));
logger.info("存入Memcached的code:"+ Rand_Code);
return true;
} catch (ServerException e) {
e.printStackTrace();
return false;
} catch (ClientException e) {
e.printStackTrace();
return false;
}
}
开始任务八:
任务八需要使用SpringRMI完成WEB端和Service端的分离。
什么是WEB端和Service端分离?
web端代表前端?service端代表后端?前后端分离?
前后端分离已成为互联网项目开发的业界标准使用方式,通过nginx+tomcat的方式(也可以中间加一个nodejs)有效的进行解耦,并且前后端分离会为以后的大型分布式架构、弹性计算架构、微服务架构、多端化服务(多种客户端,例如:浏览器,车载终端,安卓,IOS等等)打下坚实的基础
核心思想是前端html页面通过ajax调用后端的restuful api接口并使用json数据进行交互。
传统Javaweb项目:
大多使用jsp作为页面层展示数据给用户,因为流量不高,因此也没有那么苛刻的性能要求,但现在是大数据时代,对于互联网项目的性能要求是越来越高,因此原始的前后端耦合在一起的架构模式已经逐渐不能满足我们,因此我们需要需找一种解耦的方式,来大幅度提升我们的负载能力。
缺点:
1、动态资源和静态资源全部耦合在一起,服务器压力大,因为服务器会收到各种http请求,例如css的http请求,js的,图片的等等。一旦服务器出现状况,前后台一起玩完,用户体验极差。
2、UI出好设计图后,前端工程师只负责将设计图切成html,需要由java工程师来将html套成jsp页面,出错率较高(因为页面中经常会出现大量的js代码),修改问题时需要双方协同开发,效率低下。
3、jsp必须要在支持java的web服务器里运行(例如tomcat,jetty,resin等),无法使用nginx等(nginx据说单实例http并发高达5w,这个优势要用上),性能提不上来。
4、第一次请求jsp,必须要在web服务器中编译成servlet,第一次运行会较慢。
5、每次请求jsp都是访问servlet再用输出流输出的html页面,效率没有直接使用html高。
6、jsp内有较多标签和表达式,前端工程师在修改页面时会捉襟见肘,遇到很多痛点。
7、如果jsp中的内容很多,页面响应会很慢,因为是同步加载。
8、需要前端工程师使用java的ide(例如eclipse),以及需要配置各种后端的开发环境。
基于上述的一些痛点,我们应该把整个项目的开发权重往前移,实现前后端真正的解耦!
前后端分离之后的区别:
开发模式:
传统JavaWeb项目:
1、产品经历/领导/客户提出需求
2、UI做出设计图
3、前端工程师做html页面
4、后端工程师将html页面套成jsp页面(前后端强依赖,后端必须要等前端的html做好才能套jsp。如果html发生变更,就更痛了,开发效率低)
5、集成出现问题
6、前端返工
7、后端返工
8、二次集成
9、集成成功
10、交付
前后端分离之后:
1、产品经历/领导/客户提出需求
2、UI做出设计图
3、前后端约定接口&数据&参数
4、前后端并行开发(无强依赖,可前后端并行开发,如果需求变更,只要接口&参数不变,就不用两边都修改代码,开发效率高)
5、前后端集成
6、前端页面调整
7、集成成功
8、交付
请求方式:
传统JavaWeb项目:
1、客户端请求
2、服务端的servlet或controller接收请求(后端控制路由与渲染页面,整个项目开发的权重大部分在后端)
3、调用service,dao代码完成业务逻辑
4、返回jsp
5、jsp展现一些动态的代码
新的:
1、浏览器发送请求
2、直接到达html页面(前端控制路由与渲染页面,整个项目开发的权重前移)
3、html页面负责调用服务端接口产生数据(通过ajax等等,后台返回json格式数据,json数据格式因为简洁高效而取代xml)
4、填充html,展现动态效果,在页面上进行解析并操作DOM。
总结一下新的方式的请求步骤:
大量并发浏览器请求—>web服务器集群(nginx)—>应用服务器集群(tomcat)—>文件/数据库/缓存/消息队列服务器集群
同时又可以分模块,还可以按业务拆成一个个的小集群,为后面的架构升级做准备。
前后端分离的优势:
1、可以实现真正的前后端解耦,前端服务器使用nginx。前端/WEB服务器放的是css,js,图片等等一系列静态资源(甚至你还可以css,js,图片等资源放到特定的文件服务器,例如阿里云的oss,并使用cdn加速),前端服务器负责控制页面引用&跳转&路由,前端页面异步调用后端的接口,后端/应用服务器使用tomcat(把tomcat想象成一个数据提供者),加快整体响应速度。(这里需要使用一些前端工程化的框架比如nodejs,react,router,react,redux,webpack)
2、发现bug,可以快速定位是谁的问题,不会出现互相踢皮球的现象。页面逻辑,跳转错误,浏览器兼容性问题,脚本错误,页面样式等问题,全部由前端工程师来负责。接口数据出错,数据没有提交成功,应答超时等问题,全部由后端工程师来解决。
3、在大并发情况下,可以同时水平扩展前后端服务器。
4、减少后端服务器的并发/负载压力。除了接口以外的其他所有http请求全部转移到前端nginx上,接口的请求调用tomcat,参考nginx反向代理tomcat。且除了第一次页面请求外,浏览器会大量调用本地缓存。
5、即使后端服务暂时超时或者宕机了,前端页面也会正常访问,只不过数据刷不出来而已。
6、也许你也需要有微信相关的轻应用,那样你的接口完全可以共用,如果也有app相关的服务,那么只要通过一些代码重构,也可以大量复用接口,提升效率。(多端应用)
7、页面显示的东西再多也不怕,因为是异步加载。
8、nginx支持页面热部署,不用重启服务器,前端升级更无缝。
9、增加代码的维护性&易读性。
10、提升开发效率,因为可以前后端并行开发,而不是像以前的强依赖。
11、在nginx中部署证书,外网使用https访问,并且只开放443和80端口,其他端口一律关闭(防止黑客端口扫描),内网使用http,性能和安全都有保障。
12、前端大量的组件代码得以复用,组件化,提升开发效率。
SpringRMI:
什么是SpringRMI?
RMI全称是Remote Method Invocation-远程方法调用,是纯Java的网络分布式应用系统的核心解决方案之一。Java RMI 支持存储于不同地址空间的程序级对象之间彼此进行通信,实现远程对象之间的无缝远程调用。
RMI目前使用Java远程消息交换协议JRMP进行通信。由于JRMP是专为Java对象制定的,用Java RMI开发的应用系统可以部署在任何支持JRE的平台上。但由于JRMP是专为Java对象制定的,因此,RMI对于用非Java语言开发的应用系统的支持不足。不能与用非Java语言书写的对象进行通信。
收获:
了解了深度思考中的一些知识点,了解了前后端分离相关知识。
明天计划完成的事情:
继续学习SpringRMI。
评论