【Java从0到架构师】个人简历项目实战
项目实战
- 功能性
- 登陆流程
- 验证码
- JavaWeb
- Service、Dao 方法名规范
- form 文件上传 - 前端、后台、实时预览
- 页面可见性
- Service 层
- 面向接口编程
- 后端技巧
- 利用 Jackson 将 Java 对象转成 Json 字符串
- 利用反射获取泛型的类型
- 前端技巧
- 利用 reset 清空 form 表单
- 图片的 MIMEType
- 验证码功能发送不同的参数防止缓存
- 登陆/修改密码功能,利用隐藏域发送加密后的密码
Java 从 0 到架构师目录:【Java从0到架构师】学习记录
项目 Gitee 地址:https://gitee.com/szluyu99/xmg-resume
功能性
登陆流程
JS 的 MD5 库:https://blueimp.github.io/JavaScript-MD5/
MD5 在线生成:https://www.cmd5.com/
验证码
验证码 (CAPTCHA),可以用于防止大规模注册、暴力破解密码、刷票、论坛灌水等
- Completely Automated Public Turing test to tell Computers and Humans Apart 的缩写
- 全自动区分计算机和人类的图灵测试
传统的验证码:由扭曲倾斜的文字、干扰线组成
- 由服务器端生成验证码图片,返回给客户端展示
在 Java 中,可以使用 Kaptcha 库生成验证码
Kaptcha 产自 Google
常用的配置有:字体、内容的范围、尺寸、边框、干扰线、样式等
<dependency><groupId>com.github.penggle</groupId><artificatId>kaptcha</artificatId><version>2.3.2</version>
</dependency>
JavaWeb
Service、Dao 方法名规范
- 获取单个对象的方法用 get 做前缀
- 获取多个对象的方法用 list 做前缀
- 获取统计值的方法用 count 做前缀
- 插入的方法用 save(推荐)或 insert 做前缀
- 删除的方法用 remove(推荐)或 delete 做前缀
- 修改的方法用 update 做前缀
form 文件上传 - 前端、后台、实时预览
form 如果要支持文件上传,必须设置 2 个属性:
method="post"
enctype="multipart/form-data"
一旦 form 设置了这一项,Java 后台就无法通过request.getParameter
获取参数
Java 后台中常用 commons-fileupload 来接收客户端上传的文件
- 解析 request 为
List<FilteItem>
:
ServletFileUpload upload = new ServletFileUpload(new DiskFileItemFactory());
List<FileItem> items = upload.parseRequest(request);
for (FilteItem item : items) {if (item.isFormField()) { // 非文件} else { // 文件}
}
- 解决中文文件名乱码问题
upload.setHeaderEncoding("UTF-8");
刚上传完毕的图片,有可能会出现无法实时预览的问题(要等一会才能预览成功)
想要实现实时预览,把 Tomcat 的缓存资源功能关掉即可,在 %TOMCAT_HOME%/conf/context.xml
中增加 Resources
标签:
<?xml version="1.0" encoding="UTF-8"?>
<Context><WatchedResource>WEB-INF/web.xml</WatchedResource><WatchedResource>WEB-INF/tomcat-web.xml</WatchedResource><WatchedResource>${catalina.base}/conf/web.xml</WatchedResource><Resources cachingAllowed="false" cacheMaxSize="0" />
</Context>
页面可见性
正常不应该可以直接访问 xx.jsp
页面,因为这是静态页面,必须通过 Servlet 转发访问才能访问到有数据的页面。
为了防止 .jsp
文件被访问到,可以将其放置到 WEB-INF
文件夹下
网页中的静态资源(.css、img 等)一般是可以直接访问到的,因此可以不用放到 WEB-INF 中
Service 层
- Servlet:控制器层
- Service:业务层,用来完成具体的业务
- Dao:数据访问层
Service 层存在的原因是:有时候某个业务可能会多次调用数据库相关的操作,在项目很简单的情况下(Service 层所做的事情就是直接调用 Dao 层),Service 存在的意义不明显,但是当项目变大以后,Service 所处理的一些业务操作就需要抽取出来比较清晰。
面向接口编程
为什么需要面向接口编程?
- 接口只是定义了一种规范,比如 Dao 接口规定了访问数据库有哪些操作,具体具体如何实现这些操作是不固定的,例如使用 Hibernate、Mybatis、Spring-JDBC 等,如果没有接口的约束,当切换了数据库的实现方案后需要改变大量的代码;但是如果有接口的约束,只需要去实现各个方案对数据库的具体操作即可。
后端技巧
利用 Jackson 将 Java 对象转成 Json 字符串
Person person = new Person(1, "张三", 12);
ObjectMapper mapper = new ObjectMapper();
String jsonString = mapper.writeValueAsString(person);
// {"id":"1", "name":"张三", "age":"12"}
利用反射获取泛型的类型
使用场景是自动生成表名,根据泛型的类型获取类名,然后转为数据库的表名
public class Student extends Person<String, Integer>
implements Test1<Integer, Double>, Test2<Double, Long, StringBuilder> {// 获取泛型的类型public void printGenericType() {// 父类ParameterizedType superClassType = (ParameterizedType) getClass().getGenericSuperclass();Type[] args = superClassType.getActualTypeArguments();for (Type arg : args) {System.out.println(arg);}System.out.println("-----------------------------");// 接口Type[] interfaceTypes = (Type[]) getClass().getGenericInterfaces();for (Type type : interfaceTypes) {ParameterizedType interfaceType = (ParameterizedType) type;Type[] interfaceArgs = interfaceType.getActualTypeArguments();for (Type arg : interfaceArgs) {System.out.println(arg);}}}
}
java.lang.String
java.lang.Integer
-----------------------------
java.lang.Integer
java.lang.Double
java.lang.Double
java.lang.Long
java.lang.StringBuilder
大驼峰 (MyAge)、小驼峰 (myAge) 转为 下划线(my_age):
/*** 将大驼峰(MyAge)、小驼峰(myAge) 转为 下划线(my_age)**/
public static String underlineCased(String str) {if (str == null) return null;int len = str.length();if (len == 0) return str;StringBuilder sb = new StringBuilder();sb.append(Character.toLowerCase(str.charAt(0)));for (int i = 1; i < len; i++) {char c = str.charAt(i);if (Character.isUpperCase(c)) {sb.append("_");sb.append(Character.toLowerCase(c));} else {sb.append(c);}}return sb.toString();
}
前端技巧
利用 reset 清空 form 表单
jQuery 获取的并不是原生的 DOM 对象,通过 jQuery 拿到表单无法调用 reset,需要转成原生 DOM:
document.querySelector('#add-form-box form').reset() // 原生的表单DOM对象有reset方法
// $('#add-form-box form').reset() // 报错,jQuery获取的不是原生DOM,没有reset方法
$('#add-form-box form')[0].reset()
注意:调用 reset 方法不会重置 type="hidden"
的 input 输入框,需要使用 js 单独处理
图片的 MIMEType
选择文件的 input 可以通过 accept 来控制接收的文件类型,image/*
即所有图片类型
<input type="file" name="image" accept="image/*" />
验证码功能发送不同的参数防止缓存
点击验证码应当会刷新图片,但是如果每次请求的地址是相同的,那么浏览器会从缓存中取而不会实现刷新,通过在后面拼接一些不同的参数使得每次发送的请求不同。
$("#captcha").click(function() {$(this).attr('src', '${ctx}/user/catcha?time=' + new Date().getTime())
})
登陆/修改密码功能,利用隐藏域发送加密后的密码
一般不会给输入的新密码的 input 添加 name 使得用户输入的密码直接发送到服务器,而是在前端对用户输入的密码进行一个加密,将加密后的值设置到隐藏域<input type="hidden" name="newPassword" />"
,通过隐藏域发送加密后的密码。
<!-- 隐藏域用于发送加密后的密码 -->
<input type="hidden" name="password" />
<!-- 用户输入的ipnut不设置name则不会发送 -->
请输入密码:<input type="password" id='password' />
$('[name=password]').val(md5($('#password').val()))
有些网址在输入完密码点击登陆后,密码栏的字符会突然变多,实际上这就是进行了加密再发送,采用上面的方法可以避免点击登陆后密码栏字符变多的情况
【Java从0到架构师】个人简历项目实战相关推荐
- 【Java从0到架构师(1),Java中高级面试题总结(全面)
JSP 九大内置对象 MySQL 基础 + 多表查询 [Java从0到架构师]MySQL 基础 MySQL MySQL 的使用步骤 数据库的内部存储细节 GUI 工具 SQL 语句 DDL 语句 DD ...
- 【Java从0到架构师】项目实战 - 驾考(旧)- Freemarker、MyBatis-Plus
项目实战 - 驾考(旧)- Freemarker.MyBatis-Plus 各种 Object Freemarker 简单使用 常用功能 集成到 SpringBoot MyBatis-Plus 简单使 ...
- 【Java从0到架构师】SpringCloud - Sleuth、Zipkin、Config
SpringCloud 链路追踪组件 Sleuth Zipkin 分布式配置中心 - Config Git + Config 分布式配置中心 Java 从 0 到架构师目录:[Java从0到架构师]学 ...
- 【Java从0到架构师】SpringCloud - Hystrix、Zuul
SpringCloud 基本概念 熔断和降级 服务雪崩效应 服务熔断与降级 - Hystrix SpringBoot 集成 Hystrix 熔断降级服务异常报警通知 重点属性 - 熔断隔离策略.超时时 ...
- 【Java从0到架构师】SpringCloud - Eureka、Ribbon、Feign
SpringCloud 分布式.微服务相关概念 微服务框架构选型 SpringCloud 概述 服务注册与发现 - Eureka 案例项目 Eureka 自我保护机制 微服务调用方式 - Ribbon ...
- 【Java从0到架构师】RocketMQ 使用 - 集成 SpringBoot
RocketMQ 消息中间件 集成 SpringBoot 入门案例 生产消息类型 - 同步.异步.一次性 消费模式 - 集群.广播 延时消息 设置消息标签 设置消息的 Key 自定义属性设置 消息过滤 ...
- 【Java从0到架构师】RocketMQ 使用 - 发送消息、接收消息、特殊消息
RocketMQ 消息中间件 入门案例 NameServer 地址 发送消息 同步发送消息 异步发送消息 一次性发送消息 生产者组.消息封装 接收消息 消费方式:推式消费.拉式消费 消息方式:集群模式 ...
- 【Java从0到架构师】RocketMQ 基础 - 应用、核心组件、安装
RocketMQ 消息中间件 基础知识 消息中间件的应用 异步解耦 削峰填谷 消息分发 RocketMQ 核心组件 RocketMQ 安装 源码安装 修改配置参数 启动 管理控制台安装 测试项目 Ja ...
- 【Java从0到架构师】Dubbo 基础 - 设置启动时检查、直接提供者、线程模型、负载均衡、集群容错、服务降级
Dubbo 分布式 RPC 分布式核心基础 分布式概述 RPC Dubbo Dubbo 入门程序 - XML.注解 部署管理控制台 Dubbo Admin 修改绑定的注册 IP 地址 设置启动时检查 ...
最新文章
- LED液晶与OLED:电视显示技术比较
- 图解 Git 工作原理
- 利用gearman实现redis缓存mysql
- 永远不要在Linux执行的10个最危险的命令
- “你不明白欣德利 - 米尔纳的哪一部分?”
- 汇编 CALL和RET指令
- [转载]C#流,字节数组,字符串
- oracle 把逗号分隔符,将逗号分隔为Oracle中的列
- 前端框架:执行流程分析之路由与菜单
- 去大厂也就图一乐,真人上人还得是外包
- 传统的主从复制的概念和要点
- dom元素滚动条高度 js_javascript 设置元素滚动大小
- python 多线程笔记(2)-- 锁
- C++基础——非类型模板参数
- phpPgAdmin-5.1安装配置
- ARM64移动处理器解惑
- 管理工作时间的软件有哪些?
- 第四篇--关于device
- Update Strategy小记
- C#中{0}表示什么意思?
热门文章
- 监视器(monitor)
- Facts have proved that this is more popular than his article
- 改进后的新String类
- 索引sql server_维护SQL Server索引
- sql limit 子句_SQL Order by子句概述
- sql用于字符串的聚合函数_SQL字符串函数用于数据整理(争用)
- sql安装弹出sqlcmd_SQL Server中SQLCMD实用工具概述
- as5 samba 图形配置
- eclipse工具中使用Data Source Explorer连接数据库(MySQL)
- [源码和文档分享]基于C++的一元多项式的计算