标签:登录 代码 req html js 添加 信息管理系统 列表 out
涉及到的技术点:
【前端】:H5、CSS3、jQuery、Vue、laydate日期控件、Font Awesome图标
【交互】:Axios、Ajax、JSON
【后端】:普通JavaWeb项目、Tomcat、Servlet、三层架构模式、Druid连接池、MySQL
【开发工具】:VS Code、IDEA、SQLyog、浏览器
补充:
- 了解MVC与三层架构可以参考这篇文章 MVC与三层架构
- VSCode中无需手动刷新,代码自动生效需要安装Live Server扩展插件
- 界面布局未使用UI框架,采用Flex响应式布局和浮动布局(登录界面支持完全响应式,首页和添加学生页面未完全实现响应式布局)
- 此文主要用于练习,代码规范程度有限,如果有童鞋对代码有疑问,欢迎探讨
实现的目标:
- 支持学生登录
- 支持查看学生列表
- 支持添加学生
详细功能包括:
- 用户登录相关
(1)用户注册入口
(2)账号校验(账号是否符合规则、账号是否重复校验)
(3)账号密码校验(密码是否符合规则)- 学生列表界面/首页
(1)数据即时更新
(2)支持手动刷新
(3)首页布局设计
(4)header和footer展示关键信息和入口- 添加学生相关
(1)账号是否重复校验
(2)账号格式校验
(3)密码格式校验
(4)评分数值校验
(5)必填项校验
(6)关闭添加窗口
完整代码下载:
正文目录
一、界面开发(VS Code)
- 用户登录界面,
- 用户列表页/系统首页,
- 添加用户页/用户注册页
- 草图原型如下
- 注意:
- 在绘制草图或界面过程中,或者开始画原型之前,需要考虑用户需要保存哪些信息,比如像界面中展示的:账号、姓名、昵称、出生日期、性别等,因为是学生信息管理系统,还可以补充:入学年份、所在学院、所选专业、综合评分等信息
- 另外,这里没有考虑修改密码的界面和实现,只是作为练习Demo,真正的企业系统肯定是需要的。
- 开发结果如下:
-
登录界面
-
系统首页
-
添加学生界面
-
二、后端结构搭建(IDEA)
-
创建Java web项目
-
根据三层架构思想创建包目录
-
编写视图层框架 ,处理前端请求
-
web下创建LoginServlet、RegisterServlet、CommonServlet
@WebServlet("/loginServlet") public class LoginServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String result = "false"; String userId = req.getParameter("userid"); String password = req.getParameter("password"); if(userId.equals("admin") && password.equals("1")){ result = "true"; } System.out.println("【登录服务】/loginServlet result = " + result); resp.getWriter().write(result); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("--------登录请求进入post方法--------"); doGet(req,resp); } }
@WebServlet("/registerServlet") public class RegisterServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String result = "true"; String userId = req.getParameter("userid"); String password = req.getParameter("password"); String userName = req.getParameter("username"); String nickName = req.getParameter("nickname"); String birth = req.getParameter("birth"); String gender = req.getParameter("gender"); String grade = req.getParameter("grade"); System.out.println("userId = " + userId); System.out.println("password = " + password); System.out.println("userName = " + userName); System.out.println("nickName = " + nickName); System.out.println("birth = " + birth); System.out.println("gender = " + gender); System.out.println("grade = " + grade); System.out.println("【注册服务】/registerServlet result = " + result); resp.getWriter().write(result); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("--------注册请求进入post方法--------"); doGet(req,resp); } }
@WebServlet("/commonServlet") public class CommonServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String result = "false"; String userId = req.getParameter("userid"); if(userId.equals("admin")){ result = "true"; } System.out.println("【公共服务】/commonServlet result = " + result); resp.getWriter().write(result); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("--------公用请求进入post方法--------"); doGet(req,resp); } }
-
将前端页面代码拷贝到项目的web目录下
-
配置WEB-INF下的web.xml文件,添加启动项配置
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" version="4.0"> <!-- 设置默认启动的首页 --> <welcome-file-list> <welcome-file>homework/login.html</welcome-file> </welcome-file-list> </web-app>
-
三、添加前端校验(VS Code)
为元素添加事件有俩种方式:事件绑定、事件派发
- 事件绑定
<input type="button" value="点我试试" id="btn1" onclick="fn()">
function fn(){
alert("事件绑定!");
}
- 事件派发
<head>
<script>
$(function(){
$("#btn2").click(function(){
alert("事件派发");
})
})
</script>
</head>
<input type="button" value="点我试试" id="btn2">
我主要使用的事件派发,也就意味着基本所有的校验都是在js文件中实现,很少改动之前写好的HTML代码
-
登录页面校验 login.js(代码从完整代码中获取)
- 账号输入框失去焦点事件:发送ajax请求CommonServlet,判断账号是否存在
- 账号输入框获取焦点事件:隐藏账号警告信息
- 密码输入框获取焦点事件:隐藏密码警告信息
- 登录按钮点击事件:发送ajax请求,判断账号密码是否错误
- 注册链接点击事件:展示添加用户界面
-
系统首页校验 welcome.js(代码从完整代码中获取)
- 退出按钮点击事件:跳转到登录页面
- 添加按钮点击事件:展示添加用户界面
- 刷新按钮点击事件:刷新列表页数据
-
添加用户界面校验 add-stu.js(代码从完整代码中获取)
- 账号输入框失焦事件:判断是否为空;是否格式正确;账号是否重复
- 账号输入框聚焦事件:隐藏账号警告信息
- 密码输入框失焦事件:判断是否为空;是否格式正确
- 密码输入框聚焦事件:隐藏占位符;隐藏密码警告信息
- 姓名输入框失焦事件:判断是否为空
- 姓名输入框聚焦事件:隐藏姓名警告信息
- 出生日期失焦事件:判断是否为空
- 出生日期聚焦事件:隐藏日期警告信息
- 评分输入框失焦事件:判断评分是否格式正确
- 评分输入框聚焦事件:隐藏评分警告信息
- 提交按钮点击事件:ajax请求RegisterServlet,判断是否注册成功;刷新列表页
- 关闭按钮点击事件:隐藏添加用户界面
踩坑1:
添加用户界面是登录和首页的公共页面,所以单独拎出来一个add-stu.html,但是嵌套公共HTML的时候,加载公共html自己的js代码存在不生效问题。如下代码:
<body>
</body>
<script>
window.onload = function(){
console.log("----页面资源已经全部加载完毕----")
$("#addStu").load("add-stu.html")
}
</script>
<script src="js/add-stu.js"></script>
经过分析,是因为login.html或welcome.html中通过jquery的load函数加载公共html的方式属于动态加载,浏览器解析的时候会先加载静态资源,包括add-stu.js,然后才加载add-stu.html,也就导致出现了js代码中打印出来的公共页面的DOM元素不存在的情况
解决方式是:js文件也采用动态加载,在加载add-stu.html之后动态加载add-stu.js,代码如下:
<body>
</body>
<script>
window.onload = function(){
console.log("----页面资源已经全部加载完毕----")
$("#addStu").load("add-stu.html")
// jQuery.getScript()该函数用于动态加载JS文件,并在全局作用域下执行文件中的JS代码。
// 该函数可以加载跨域的JS文件。请注意,该函数是通过异步方式加载数据的。
// 该函数属于全局jQuery对象。
$.getScript("js/login.js",function(){
console.log("公用页面js加载完毕")
})
}
</script>
踩坑2:
随着引入的外部js、css等外部资源变多,导致添加界面add-stu.html的性别单选框莫名其妙失效,排查和测试一段时间后,仍然未找到具体原因,原先代码如下:
<div class="option-div">
<label>
<input type="radio" name="r-gender" checked=true value="1">
<div class="r-gender-div" >男</div>
</label>
<label>
<input type="radio" name="r-gender" value="0">
<div class="r-gender-div" >女</div>
</label>
</div>
最后采用jquery监听事件解决,修改后代码如下:
<div class="option-div">
<label>
<input type="radio" name="r-gender" checked=true class="r-gender-input" value="1">
<div class="r-gender-div" index="0">男</div>
</label>
<label>
<input type="radio" name="r-gender" class="r-gender-input" value="0">
<div class="r-gender-div" index="1">女</div>
</label>
</div>
//20210123 解决性别单选框交互失效问题
$(".r-gender-div").on("click",function(){
// console.log($(this).prop("index")) //prop获取自定义属性失败,提示undefined
//console.log($(this).attr("index"))
//获取单选项的序号
var index = $(this).attr("index")
var gender_checked_dom = $(".r-gender-input")[index] //获取的是DOM元素
//console.log(gender_checked_dom)
//$(gender_checked_dom).prop("checked",true);
$(gender_checked_dom).attr("checked",true);
})
四、后端功能实现(IDEA)
数据库准备工作(SQLyog)
- 创建数据库webdb
- 创建用户表tuser
Java代码开发(IDEA)
因为第二部分已经搭好了架子,这部分相对容易一些
- domain包
- 创建用户/学生的bean对象User
- 创建一个响应统一返回的Java对象ResultData
- 其中涉及到code字段,创建一个枚举类CodeEnum
- 其中涉及到的status字段,创建一个枚举类StatusEnum
- util包
- 创建Druid连接池工具类DruidUtils,方便dao层进行操作数据库
- 在项目根目录下创建一个resources目录,右键该目录,设置Mark Directory As 属性为Resources Root
- 在resources目录下创建一个数据库连接信息配置文件druid.properties(名字及后缀可以自定义,DruidUtils工具类中匹配上就行,建议用druid.properties命名,见名知意)
- dao包
- 创建用户信息持久化层接口UserDao,定义4个方法
- 根据账号查询用户数量 findUserCountByUserId
- 根据账号和密码查询用户 findUserByUserIdAndPwd
- 添加用户 insertUserByUser
- 查询所有用户 findAllUsers
- 创建一个子包impl
- impl包下创建UserDao接口的实现类UserDaoImpl,调用DruidUtils操作数据库,实现上述4个方法
- 创建用户信息持久化层接口UserDao,定义4个方法
- service包
- 用户服务层接口UserService,定义4个方法
- 查询该账号是否存在 isExistStudentOfUserId
- 验证账号密码是否正确 isCorrectOfUserIdAndPwd
- 添加用户 addUser
- 查询所有用户 findAllUsers
- 创建一个子包impl
- impl包下创建UserService实现类UserServiceImpl,重写UserService接口的4个方法
- isExistStudentOfUserId,调用dao层的实现类UserDaoImpl方法 findUserCountByUserId
- isCorrectOfUserIdAndPwd,调用dao层的实现类UserDaoImpl方法findUserByUserIdAndPwd
- addUser,调用dao层的实现类UserDaoImpl方法insertUserByUser
- findAllUsers,调用dao层的实现类UserDaoImpl方法findAllUsers
- 用户服务层接口UserService,定义4个方法
- web包
- 创建查询账号处理器CommonServlet,调用UserService的方法 isExistStudentOfUserId
- 创建用户登录请求处理器LoginServlet,调用UserService的方法 isCorrectOfUserIdAndPwd
- 创建添加用户处理器RegisterServlet,调用UserService的方法 addUser
- 创建查询用户列表处理器UserListServlet,调用UserService的方法 findAllUsers
- 创建一个子包filter
- filter包下创建编码过滤器 EncodeFilter,重写doFilter方法,统一设置请求和响应的编码格式
- 配置WEB-INF的web.xml,添加过滤器拦截路径
五、前后端联调(IDEA)
- 调整前端代码中的ajax请求,axios请求的回调函数中对响应数据的获取和判断
- 后端Java代码中根据联调情况,添加相应的日志打印或者服务器采用debug方式运行,打断点调试后端代码
六、相关参考资料(浏览器)
- 关于登录界面,80%的代码都是参考该文章进行实现的
html+css实现漂亮的透明登录页面,HTML实现炫酷登录页面
- 关于响应式布局的学习,参考此文章
HTML+CSS十分钟实现响应式布局页面,响应式布局实战教程
- 嵌套HTML后内部HTML的js失效问题参考(坑)
使用jquery的load方法加载公共html页面,但是引入的公共html的js却不生效
- Ajax的回调函数中使用return返回内容,但是外部函数接收到的确实undefined(坑)
Ajax回调函数中return不生效问题
- jar依赖包在idea中添加依赖后,启动tomcat报错问题(注意必须要放到tomcat的lib目录下)
java.lang.ClassNotFoundException: com.alibaba.druid.support.http.WebStatFilter异常解决
- com.alibaba.druid.pool.DruidDataSource.error {dataSource-1} init error
java.sql.SQLException: com.mysql.cj.jdbc.Driver 问题- 我这里是因为没有添加mysql 8.0连接驱动的jar包到tomcat目录下,添加上即可。
- 如果之前可以连接和访问,之后出现报错的话,可以参考下方文章
(已解决)解决问题:dataSource init error java.sql.SQLException: com.mysql.cj.jdbc.Driver和一些mysql连接jar包的问题
- idea中在dao层写sql语句时。表名和字段名报红,但是不影响程序运行,可以正常访问
- 如果看着不舒服,想解决idea报红问题,可以在idea中打开database选项(打开方法咨询度娘),连接到本地的数据库,这样idea就可以识别表和字段名是否正确,只有在不正确的情况下才会报红
- jdbc插入mysql的date类型字段时会报错
Data truncation: Incorrect datetime value: ‘Fri Jan 22 17:53:31 CST 2021’ for column ‘create_time’ at row 1
参考解决方案:java插入数据到mysql的datetime类型字段
- ajax通过post方式访问servlet时,发现浏览器控制台总会多一个get请求,地址栏也会变化
http://localhost:8080/homework/welcome.html?r-userid=test7&r-password=777777&r-username=%E6%B5%8B%E8%AF%957&r-nickname=&r-birth=2021-01-26&r-gender=1&r-grade=
- 因为form默认的提交方式是get,需要禁止默认提交操作
$("form").on("click",function(){ event.preventDefault(); })
- IDEA中写js函数时,提示错误,版本过低,解决方法如下
method definition shorthands are not supported by current JavaScript version
- tomcat的web目录下新添加的js文件在浏览器一直没有生效,不管怎么清缓存刷新都不行
删除tomcat输出资源的目录,我这里是out目录,然后重启tomcat,便会全部加载
- 登录之后在首页获取到登录成功后存入cookie的值,报错$.cookie is not a function
参考解决方法
- 在一个页面中,body下面是2个平级的div,那么如何在俩个div中都挂载上vue对象(body不允许作为vue的挂载点)
解决方法
- 在俩个平级的div外面加一层div,新的div作为挂载点(缺点是:添加div后,可能要重新调整界面样式)
- 只用一个div作为挂载点,然后在vue的方法内,使用jquery或js给另一个div的元素传参或赋值(我采用)
- 取消使用vue,全部使用jquey或js实现(缺点:渲染表格比较麻烦,还得拼接标签)
标签:登录,代码,req,html,js,添加,信息管理系统,列表,out 来源: https://blog.csdn.net/qq_19314763/article/details/112846790
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。