有的内容是刚接触,还不太了解,只是按照我目前的的理解来写的,等到后面会根据自己的进度进行修改。
项目地址:https://github.com/pzyruo/CRM
今天主要学的是搭建一下项目需要的环境。
这个客户管理系统使用的是MyBatis+Servlet,使用maven来搭建项目。前端页面已经写好了,直接用就行。
一、目录结构
1. 使用maven默认的目录只有src
下的main
和webapp
。剩下的需要手动创建,我的idea版本是2020.02的,创建目录的时候会提示java
目录和resource
目录,如果没有提示需要右键来进行手动设置。
。
2. 和main同级的是test目录,主要是做测试的,使用的是Junit来做测试。这里需要注意的是main目录里面的java是蓝色的,而test里面的是绿色的,不能弄错,而且名字也不能有差别。
3.在webapp目录下放置前端需要的HTML文件,js文件和JQuery文件还有图片等文件。
4.将pom.xml文件中不需要的内容删除,截止今天为止只留下Junit、Servlet、jsp、MyBatis、Jackson、mysql、log4j
等依赖。注意需要加入resource依赖。
<build>
<resources>
<!-- resources文件 -->
<resource>
<directory>src/main/java</directory>
<!-- 引入映射文件 -->
<includes>
<include>**/*.xml</include>
<include>**/*.properties</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
</build>
5.java目录下包含exception、settings和utils三个package。
- exception:自定义异常包
- settings:后端代码所在
- utils:工具类
6.和java同级的是resource,存放jdbc.properties和log4j.properties和MyBatis的主配置文件。
2020-08-14今天主要做的是登陆页面
这个是页面显示图:
用户信息表结构以及需要验证的信息如下:
今天主要做的是前端页面的修改
- 首先将login.html文件修改为jsp文件,加入
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
2.代码如下:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + request.getContextPath() + "/";
%>
<!DOCTYPE html>
<html>
<head>
<base href="<%=basePath%>">
<meta charset="UTF-8">
<link href="jquery/bootstrap_3.3.0/css/bootstrap.min.css" type="text/css" rel="stylesheet" />
<script type="text/javascript" src="jquery/jquery-1.11.1-min.js"></script>
<script type="text/javascript" src="jquery/bootstrap_3.3.0/js/bootstrap.min.js"></script>
<script>
$(function (){
//代码允许重复,代码结构不允许重复
//页面加载完毕后,将用户文本框中的内容清空
$("#loginAct").val("")
//页面加载完毕后,用户的文本框自动获得焦点
$("#loginAct").focus()
//为登陆按钮绑定事件,执行登陆操作
$("#submitBtn").click(function (){
longin()
})
//为当前登陆窗口绑定敲键盘事件
//event:取得我们敲击的是哪个键
$(window).keydown(function (event){
//alert(event.keyCode)
if (event.keyCode ==13){
longin()
}
})
})
///一定写在$(function () 外面,以后有框架。否则会难以辨认
function longin() {
//alert("登陆验证")
//验证账号密码不能为空
//取得账号密码
//将文本中的左右空格去掉
var loginAct = $.trim($("#loginAct").val())
var loginPwd = $.trim($("#loginPwd").val())
if (loginAct=="" || loginPwd==""){
$("#msg").html("账号密码不能为空")
//如果账号密码为空,则需要强制终止该方法
return false
}
// 去后台验证登陆相关操作
$.ajax({
url:"settings/user/login.do",
data:{
"loginAct":loginAct,
"loginPwd":loginPwd
},
type:"",
dataType:"json",
success:function (data){
/*
data
{"success":true/false,"msg":"错误原因"}
* */
//如果登陆成功
if (data.success){
//跳转到工作台的初始页
window.location.href="workbench/index.html";
}else {
$("#msg").html(data.msg)
}
}
})
}
</script>
</head>
<body>
<div style="position: absolute; top: 0px; left: 0px; width: 60%;">
<img src="image/IMG_7114.JPG" style="width: 100%; height: 90%; position: relative; top: 50px;">
</div>
<div id="top" style="height: 50px; background-color: #3C3C3C; width: 100%;">
<div style="position: absolute; top: 5px; left: 0px; font-size: 30px; font-weight: 400; color: white; font-family: 'times new roman'">CRM <span style="font-size: 12px;">©2017 动力节点</span></div>
</div>
<div style="position: absolute; top: 120px; right: 100px;width:450px;height:400px;border:1px solid #D5D5D5">
<div style="position: absolute; top: 0px; right: 60px;">
<div class="page-header">
<h1>登录</h1>
</div>
<form action="workbench/index.html" class="form-horizontal" role="form">
<div class="form-group form-group-lg">
<div style="width: 350px;">
<input class="form-control" type="text" placeholder="用户名" id="loginAct">
</div>
<div style="width: 350px; position: relative;top: 20px;">
<input class="form-control" type="password" placeholder="密码" id="loginPwd">
</div>
<div class="checkbox" style="position: relative;top: 30px; left: 10px;">
<span id="msg" style="color: red"></span>
</div>
<%--
按钮写在form表单中,默认的行为是提交表单
一定要将按钮的类型设置为button
按钮所触发的行为应该是程序员自己手动写js代码决定
--%>
<button type="button" id="submitBtn" class="btn btn-primary btn-lg btn-block" style="width: 350px; position: relative;top: 45px;">登录</button>
</div>
</form>
</div>
</div>
</body>
</html>
2020-08-20 登陆验证
因为种种原因,这几天都没有继续学这个项目,今天终于有时间了。。。
今天遇到了各种各样的问题,按照视频教程来做,结果发现总是出现问题,不过这样也挺好的,原本迷迷糊糊的,不知道流程是什么,经过三个小时的修改对目前的程序流程算是有了大概的掌握了。
今天主要做的是登陆验证,流程大概如下:
① 用户在页面输入账号和密码并点击登陆或者回车键
② jsp使用ajax的方式将参数通过post的方式传递给后台UserController.servlet
③ UserController首先判断请求地址是否是这个uer-patter
地址,如果是继续执行
④获取前端传递过来的账号和密码,并将密码的明文转化为MD5的密文形式
⑤获取请求主机的ip地址是否符合要求
⑥使用代理类的形式创建一个UserService的接口对象us,并为其生成一个实现类
UserService us =(UserService) ServiceFactory.getService(new UserServiceImpl());
⑦进行登陆验证,使用User类的形式来进行验证,
Usercontroller类
User user = us.login(loginAct,loginPwd,ip);
UserServiceImpl类实现login方法
使用SQlSessionUtil来创建SQlsession
package com.pzyruo.crm.utils;
import java.io.IOException;
import java.io.InputStream;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
public class SqlSessionUtil {
private SqlSessionUtil(){}
private static SqlSessionFactory factory;
static{
String resource = "mybatis-config.xml";
InputStream inputStream = null;
try {
inputStream = Resources.getResourceAsStream(resource);
} catch (IOException e) {
e.printStackTrace();
}
factory =
new SqlSessionFactoryBuilder().build(inputStream);
}
private static ThreadLocal<SqlSession> t = new ThreadLocal<SqlSession>();
public static SqlSession getSqlSession(){
SqlSession session = t.get();
if(session==null){
session = factory.openSession();
t.set(session);
}
return session;
}
public static void myClose(SqlSession session){
if(session!=null){
session.close();
t.remove();
}
}
}
UserServiceImpl类
package com.pzyruo.crm.settings.service;
import com.pzyruo.crm.exception.LoginException;
import com.pzyruo.crm.settings.dao.UserDao;
import com.pzyruo.crm.settings.domain.User;
import com.pzyruo.crm.utils.DateTimeUtil;
import com.pzyruo.crm.utils.SqlSessionUtil;
import java.util.HashMap;
import java.util.Map;
public class UserServiceImpl implements UserService {
@Override
public User login(String loginAct, String loginPwd, String ip) throws LoginException {
UserDao userDao = SqlSessionUtil.getSqlSession().getMapper(UserDao.class);
Map<String,String> map = new HashMap<>();
map.put("loginAct",loginAct);
map.put("loginPwd",loginPwd);
User user = userDao.login(map);
if (user == null) {
throw new LoginException("账号密码错误");
}
//如果程序能够成功执行到这里,说明账号密码正确
//需要继续向下验证
// 验证失效时间
String expireTime = user.getExpireTime();
String currentTime = DateTimeUtil.getSysTime();
if (expireTime.compareTo(currentTime)<0){
throw new LoginException("账号已失效,请重新输入");
}
// 验证锁定状态
String lockState = user.getLockState();
if ("0".equals(lockState)){
throw new LoginException("账号已锁定");
}
// 验证ip地址
String Ips = user.getAllowIps();
if (!Ips.contains(ip)) {
throw new LoginException("ip地址受限,请联系管理员");
}
return user;
}
}
如果以上情况都没有发生,说明用户的账号、密码、ip地址、有效日期和锁定状态都符合要求。
⑧使用Jackson将数据成功信息拼接成json数组发给前端,前端收到成功信息后跳转到指定页面完成登录。
⑨如果用户输入的信息获取其他信息有误,使用自定义异常类LoginException来捕获,并将异常信息发送给前端页面并打印输出给用户。
UserController类
package com.pzyruo.crm.settings.web.controller;
import com.pzyruo.crm.settings.domain.User;
import com.pzyruo.crm.settings.service.UserService;
import com.pzyruo.crm.settings.service.UserServiceImpl;
import com.pzyruo.crm.utils.MD5Util;
import com.pzyruo.crm.utils.PrintJson;
import com.pzyruo.crm.utils.ServiceFactory;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
public class UserController extends HttpServlet {
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("进入用户控制器");
String path = request.getServletPath();
if ("/settings/user/login.do".equals(path)){
login(request,response);
}else if ("/settings/user/xxx.do".equals(path)){
}
}
private void login(HttpServletRequest request, HttpServletResponse response) {
System.out.println("进入到验证登陆");
String loginAct = request.getParameter("loginAct");
String loginPwd = request.getParameter("loginPwd");
//将密码的明文转换为MD5的密文形式
loginPwd = MD5Util.getMD5(loginPwd);
//接受ip地址
String ip = request.getRemoteAddr();
System.out.println("ip--------:"+ip);
//未来的业务层开发,统一使用代理类形态的接口对象
UserService us =(UserService) ServiceFactory.getService(new UserServiceImpl());
try {
User user = us.login(loginAct,loginPwd,ip);
request.getSession().setAttribute("user",user);
//如果程序执行到此处,说明业务层没有为controller抛出任何异常
//表示登陆成功
PrintJson.printJsonFlag(response,true);
}catch (Exception e){
e.printStackTrace();
//执行到此,说明业务层为我们验证登陆失败,为controller抛出了异常
// {"success":true,"msg":?}
String msg = e.getMessage();
/*
* 我们现在作为controller,需要为ajax请求提供对象信息
* 1.将多项信息打包成map,将map解析为json串
* 2.创建一个Vo
* private boolean success;
* private String msg;
* 若果对于展现的信息将来还会大量使用,我们创建一个vo类,使用方便。
* 如果对于展现的信息只有在这个需求中能够使用,我们使用map就可以了
*
* */
Map<String,Object> map = new HashMap<>();
map.put("success",false);
map.put("msg",msg);
PrintJson.printJsonObj(response,map);
}
}
}
遇到的问题:
1.在静态的上下文中使用了非静态的方法调用
实际上并没有,重新写了下方法后好了,可能是idea的问题
2.获取数据库中的实效时间时一直返回的是null,并不停的给我报空指针因此,我又获取了id试下,还是null。这时我就考虑是不是IDEA的问题,因为我使用的get方法啊。
果然重启IDEA后问题得到了解决
3.ibatis处理器异常(executor.ExecutorException
这个应该是我的Session是全局变量,由于session每次得到dao接口都必须先提交再关闭,共享service对象导致下一个不可用。
具体解决办法:https://blog.csdn.net/haleyliu123/article/details/65644383/
今天并没有学到太多,出现的问题太多了,而且我找问题的能力太弱了,不过也锻炼了自己的能力,继续加油。