在B站上跟着做一个客户管理系统(更新中)

有的内容是刚接触,还不太了解,只是按照我目前的的理解来写的,等到后面会根据自己的进度进行修改。
项目地址:https://github.com/pzyruo/CRM

今天主要学的是搭建一下项目需要的环境。
这个客户管理系统使用的是MyBatis+Servlet,使用maven来搭建项目。前端页面已经写好了,直接用就行。

一、目录结构

在这里插入图片描述
1. 使用maven默认的目录只有src下的mainwebapp。剩下的需要手动创建,我的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今天主要做的是登陆页面

这个是页面显示图:在这里插入图片描述

用户信息表结构以及需要验证的信息如下:
在这里插入图片描述
今天主要做的是前端页面的修改

  1. 首先将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 &nbsp;<span style="font-size: 12px;">&copy;2017&nbsp;动力节点</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/

今天并没有学到太多,出现的问题太多了,而且我找问题的能力太弱了,不过也锻炼了自己的能力,继续加油。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值