一 登录流程
将服务器资源给有权限的人访问,只有登录的管理员可以访问员工信息进行 CRUD
二 三层架构
Web 开发中的最佳实践:分层开发模式将整个业务应用划分为:表现层、业务逻辑层、数据访问层。区分层次的目的即为了“高内聚低耦合”的思想。
表现层(Predentation Layer):MVC,负责处理与界面交互的相关操作。
业务层(Business Layer):Service,负责复杂的业务逻辑计算和判断。
持久层(Persistent Layer):DAO,负责将业务逻辑数据进行持久化存储。
三 代码实现
1 数据库表
管理员表
CREATE TABLE `users` (`id` bigint(20) NOT NULL AUTO_INCREMENT,`username` varchar(255) DEFAULT NULL,`password` varchar(255) DEFAULT NULL,`headImg` varchar(255) DEFAULT NULL,PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
INSERT INTO user(username, password,headImg) VALUES('yellow', '111111','null');
员工信息表
CREATE TABLE `employee` (`id` bigint(11) NOT NULL AUTO_INCREMENT,`name` varchar(50) DEFAULT NULL,`salary` double(10,2) DEFAULT NULL,PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8;
INSERT INTO employee(name, salary) VALUES('kai', '6379');
2 创建实体类
Users
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Users {private Long id;private String username;private String password;private String headImg;
}
Employee
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Employee {private Long id;private String name;private Double salary;
}
3 创建对应的mapper文件
UserMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.tj.mapper.UserMapper"><!--根据账号查询--><select id="queryByUsername" resultType="Users">SELECT * from users WHERE username=#{username}</select><!--修改头像--><update id="updateImg">update users set headImg =#{headImg} WHERE id=#{id}</update>
</mapper>
EmployeeMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.tj.mapper.EmployeeMapper"><!--增加商品--><insert id="add">insert into employee (name,salary)values(#{name},#{salary})</insert><!--修改--><update id="update">update employee set name=#{name},salary=#{salary}WHERE id=#{id}</update><!--删除--><delete id="delete">delete from employee WHERE id=#{id}</delete><!--根据id查询--><select id="selectOne" resultType="Employee">SELECT * from employee WHERE id=#{id}</select><!--查询所有--><select id="list" resultType="Employee">SELECT * from employee</select><!--查询总条数--><select id="queryCount" resultType="int">SELECT count(*) from employee</select><!--分页查询--><select id="queryPage" resultType="Employee">SELECT * from employee limit #{start},#{pageSize}</select>
</mapper>
4 创建resources文件
db.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql:///play_web
jdbc.user=root
jdbc.password=root
log4j.properties
# Global logging configuration
log4j.rootLogger=ERROR, stdout
# MyBatis logging configuration...
log4j.logger.cn.tj=TRACE
# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
mybatis-config.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration><properties resource="db.properties"></properties><typeAliases><package name="cn.tj.domain"/></typeAliases><environments default="dev"><environment id="dev"><transactionManager type="JDBC"></transactionManager><dataSource type="POOLED"><property name="driver" value="${jdbc.driver}"/><property name="url" value="${jdbc.url}"/><property name="username" value="${jdbc.user}"/><property name="password" value="${jdbc.password}"/></dataSource></environment></environments><mappers><mapper resource="mappers/EmployeeMapper.xml"></mapper><mapper resource="mappers/UserMapper.xml"></mapper></mappers>
</configuration>
5 创建Dao层接口
UserDao
public interface UserDao {//根据账号查询Users queryByUsername(String username);//修改头像int updateImg(Users users);
}
EmployeeDao
public interface EmployeeDao {/*增加*/int add(Employee employee);/*修改*/int update(Employee employee);/*删除*/int delete(Long id);/*查询所有*/List<Employee> list();/*根据id查询*/Employee selectOne(Long id);/*查询总条数*/int queryCount(QueryObject qo);/*分页查询*/List<Employee> queryPage(QueryObject qo);
}
6 创建Dao层实现类
UserDaoImpl
public class UserDaoImpl implements UserDao {private SqlSession sqlSession= MybatisUtil.getSqlSession();@Overridepublic Users queryByUsername(String username) {return sqlSession.selectOne("cn.tj.mapper.UserMapper.queryByUsername", username);}@Overridepublic int updateImg(Users users) {return sqlSession.update("cn.tj.mapper.UserMapper.updateImg",users);}
}
EmployeeDaoImpl
public class EmployeeDaoImpl implements EmployeeDao {/*定义成员变量*/private SqlSession sqlSession= MybatisUtil.getSqlSession();@Overridepublic int add(Employee employee) {int row = sqlSession.insert("cn.tj.mapper.EmployeeMapper.add", employee);return row;}@Overridepublic int update(Employee employee) {int row= sqlSession.update("cn.tj.mapper.EmployeeMapper.update",employee);return row;}@Overridepublic int delete(Long id) {int row= sqlSession.delete("cn.tj.mapper.EmployeeMapper.delete",id);return row;}@Overridepublic List<Employee> list() {List<Employee> list = sqlSession.selectList("cn.tj.mapper.EmployeeMapper.list");return list;}@Overridepublic Employee selectOne(Long id) {Employee employee= sqlSession.selectOne("cn.tj.mapper.EmployeeMapper.selectOne", id);return employee;}@Overridepublic int queryCount(QueryObject qo) {return sqlSession.selectOne("cn.tj.mapper.EmployeeMapper.queryCount",qo);}@Overridepublic List<Employee> queryPage(QueryObject qo) {return sqlSession.selectList("cn.tj.mapper.EmployeeMapper.queryPage",qo);}
}
7 编写登录 Servlet
UserServlet
@WebServlet("/user")
@MultipartConfig
public class UserServlet extends HttpServlet {private UserService userService =new UserServiceImpl();@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {req.setCharacterEncoding("utf-8");resp.setContentType("text/html;charset=utf-8");String cmd = req.getParameter("cmd");if ("login".equals(cmd)){login(req,resp);//登录}else if("logout".equals(cmd)){logout(req,resp);//退出登录}else if("updateImg".equals(cmd)){updateImg(req,resp);}}/*修改头像*/private void updateImg(HttpServletRequest req, HttpServletResponse resp) {try {//上传新图片Part part = req.getPart("headImg");String path=getServletContext().getRealPath("/upload") +"/";String headImg = UploadUtil.uploadImg(req, resp, part,path);//获取登录账号对象HttpSession session = req.getSession();Users user= (Users) session.getAttribute("USER_IN_SESSION");//修改头像user.setHeadImg(headImg);//保存新头像名称userService.updateImg(user);//把session中的对象更新一下session.setAttribute("USER_IN_SESSION",user);//修改完毕跳转查询商品resp.sendRedirect("/employee");} catch (Exception e) {e.printStackTrace();}}/*退出登录*/private void logout(HttpServletRequest req, HttpServletResponse resp) {try {//获取sessionHttpSession session = req.getSession();
// session.invalidate();//销毁sessionsession.removeAttribute("username");//跳转到登录页面resp.sendRedirect("login.jsp");} catch (IOException e) {e.printStackTrace();}}/*用户登录*/private void login(HttpServletRequest req, HttpServletResponse resp) {try {//获取表单的参数String username = req.getParameter("username");String password = req.getParameter("password");//调用业务层登录方法Users users = userService.login(username, password);//账号密码正确:登录成功,将登录账号显示到商品的列表页面HttpSession session = req.getSession();session.setAttribute("USER_IN_SESSION",users);resp.sendRedirect("/employee");} catch (Exception e) {try {req.setAttribute("msg",e.getMessage());req.getRequestDispatcher("/login.jsp").forward(req,resp);} catch (Exception ex) {ex.printStackTrace();}}}
}
8 编写登录页面
login.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>登录</title>
</head>
<body>
<h3>用户登录</h3>
<form action="/user?cmd=login" method="post"><%--登录错误提示--%><span style="color: red">${msg}</span><p>账号:<input type="text" name="username"></p><p>密码:<input type="password" name="password"></p><p><input type="submit" value="登录"></p>
</form>
</body>
</html>
9 登录后跳转操作员工信息
EmployeeServlet
@WebServlet("/employee")
public class EmployeeServlet extends HttpServlet {private EmployeeService employeeService=new ProductServiceImpl();@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//设置编码格式req.setCharacterEncoding("utf-8");resp.setContentType("text/html;charset=utf-8");// 登录权限判断 操作员工需要先登录HttpSession session = req.getSession();Users users = (Users) session.getAttribute("USER_IN_SESSION");if (users==null){//如果没有登录,跳转登录页面,给出提示req.setAttribute("msg","请先登录再操作!");req.getRequestDispatcher("/login.jsp").forward(req,resp);return;}//获取请求分发的参数String cmd = req.getParameter("cmd");if ("delete".equals(cmd)){//调用删除delete(req,resp);}else if("input".equals(cmd)){//跳转到增加或修改页面input(req,resp);} else if("saveOrUpdate".equals(cmd)){//保存增加或修改商品saveOrUpdate(req,resp);}else{//查询所有list(req,resp);}}/*增加修改保存*/private void saveOrUpdate(HttpServletRequest req, HttpServletResponse resp) {//封装员工对象Employee employee=new Employee();/*将参数的获取及封装对象过程抽取成一个方法*/req2product(req,employee);/*根据请求中是否携带id判断执行增加或者修改操作*/String id = req.getParameter("id");if (StringUtil.hasLength(id)){employee.setId(Long.valueOf(id));//执行修改employeeService.update(employee);}else{//调用dao方法执行增加保存操作employeeService.add(employee);}try {//跳转到查询resp.sendRedirect("/employee");} catch (IOException e) {e.printStackTrace();}}/*封装的获取请求参数的方法*/private void req2product(HttpServletRequest req, Employee employee) {//获取请求中表单参数String name = req.getParameter("name");//验证输入的表单参数不能为空if (StringUtil.hasLength(name)){//编辑员工姓名employee.setName(name);}String salary = req.getParameter("salary");if (StringUtil.hasLength(salary)){employee.setSalary(Double.valueOf(salary));}}/*跳转到编辑页面*/private void input(HttpServletRequest req, HttpServletResponse resp) {//根据请求中是否携带id判断是增加或者修改操作String id = req.getParameter("id");if (StringUtil.hasLength(id)){//请求中携带了id执行修改//根据id查询员工Employee employee = employeeService.selectOne(Long.valueOf(id));//将查询的员工存储到作用域req.setAttribute("employee",employee);}try {//跳转到WEB-INF下面的页面:input.jspreq.getRequestDispatcher("/WEB-INF/views/employee/input.jsp").forward(req,resp);} catch (Exception e) {e.printStackTrace();}}/*分页查询所有*/private void list(HttpServletRequest req, HttpServletResponse resp) {try {/*客户端如果传入了当前页码和每页显示条数则设置给qo对象,如果没有传入则使用默认值*/String currentPage = req.getParameter("currentPage");String pageSize = req.getParameter("pageSize");QueryObject qo=new QueryObject();if (StringUtil.hasLength(currentPage)){qo.setCurrentPage(Integer.valueOf(currentPage));}if (StringUtil.hasLength(pageSize)){qo.setPageSize(Integer.valueOf(pageSize));}//调用service分页查询的方法PageResult<Employee> pageResult = employeeService.queryByPage(qo);//将查询的结果存储到请求作用域req.setAttribute("pageResult",pageResult);//转发到列表页面req.getRequestDispatcher("/WEB-INF/views/employee/list.jsp").forward(req,resp);} catch (Exception e) {e.printStackTrace();}}/*删除*/private void delete(HttpServletRequest req, HttpServletResponse resp) {try {//获取目标idString id = req.getParameter("id");//调用删除方法int row = employeeService.delete(Long.valueOf(id));//删除完毕跳转到查询resp.sendRedirect("/employee");} catch (IOException e) {e.printStackTrace();}}
}
10 展示与编辑员工页
input.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head><title>员工编辑页面</title>
</head>
<body>
<h3>员工编辑</h3>
<form action="/employee?cmd=saveOrUpdate" method="post"><input type="hidden" name="id" value="${employee.id}"><p>姓名:<input type="text" name="name" value="${employee.name}"></p><p>工资:<input type="number" name="salary" step="0.01" value="${employee.salary}"></p><p><input type="submit" value="保存"></p>
</form>
</body>
</html>
list.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%--引入核心标签库--%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head><title>员工信息页面</title>
</head>
<body>
<center><h3>员工列表</h3><p>当前登录账号:${sessionScope.USER_IN_SESSION.username}</p><p><%--点击跳转到上传头像的表单页面--%><a href="/headImg.jsp"><%--头像--%><img src="/upload/${sessionScope.USER_IN_SESSION.headImg}" width="100px" height="100px"><p>${sessionScope.USER_IN_SESSION.headImg}</p></a></p><p><a href="/employee?cmd=input">增加员工</a></p><p><a href="/user?cmd=logout">退出登录</a></p><%--分页跳转的表单--%><form action="/employee" method="post"><table border="1px" cellpadding="0" cellspacing="0"width="800px"><thead><tr><th>序号</th><th>姓名</th><th>工资</th><th>操作</th></tr></thead><tbody><%--动态展示员工列表数据--%><c:forEach items="${pageResult.list}" varStatus="vs" var="employee"><tr class="trClass"><td>${vs.count}</td><td>${employee.name}</td><td>${employee.salary}</td><td><a href="/employee?cmd=input&id=${employee.id}">修改员工信息</a> <%-- <a href="/employee?cmd=delete&id=${employee.id}">删除员工信息</a>--%><a href="#" onclick="deleteTr(${employee.id})">删除员工信息</a></td></tr></c:forEach></tbody><tfoot><tr align="center"><td colspan="9"><a href="/employee?currentPage=1&pageSize=${pageResult.pageSize}">首页</a> <a href="/employee?currentPage=${pageResult.prevPage}&pageSize=${pageResult.pageSize}">上一页</a> <a href="/employee?currentPage=${pageResult.nextPage}&pageSize=${pageResult.pageSize}">下一页</a> <a href="/employee?currentPage=${pageResult.totalPage}&pageSize=${pageResult.pageSize}">末页</a> 当前是第 ${pageResult.currentPage}/${pageResult.totalPage}页 一共${pageResult.totalCount}条数据 跳转到第<input type="text" name="currentPage" value="${pageResult.currentPage}"onchange="changePagesize()" style="width: 50px">页 每页<select name="pageSize" onchange="changePagesize()"><option value="3" ${pageResult.pageSize==3?'selected':''}>3</option><option value="6" ${pageResult.pageSize==6?'selected':''}>6</option><option value="9" ${pageResult.pageSize==9?'selected':''}>9</option></select>条数据 </td></tr></tfoot></table></form>
</center><%--鼠标移动到当前行,实现背景颜色高亮显示--%>
<script>//获取所有的行元素:不包含表头var trs = document.getElementsByClassName("trClass");//遍历行元素集合for(var i=0;i<trs.length;i++){//鼠标移入:当前行高亮,背景变成灰色trs[i].onmouseover=function (){this.style.backgroundColor="gray";}//鼠标移出:恢复原来背景颜色trs[i].onmouseout=function (){this.style.backgroundColor="";}}
</script><%--删除确认表--%>
<script>function deleteTr(id){//确认删除var b= window.confirm("确定要删除选中的员工信息吗?");if(b){//确定删除,执行后台删除操作window.location="/employee?cmd=delete&id="+id;}}
</script><%--分页表单提交函数--%>
<script>function changePagesize(){document.forms[0].submit();}
</script>
</body>
</html>
headImg.jsp – 修改头像
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>头像上传</title>
</head>
<body>
<h3>修改头像</h3>
<form action="/user?cmd=updateImg" method="post" enctype="multipart/form-data"><p>头像:<input type="file" name="headImg"></p><p><input type="submit" value="提交"></p>
</form>
</body>
</html>
11 service层接口
UserService
public interface UserService {//登录方法public Users login(String username, String password);//修改头像public int updateImg(Users users);
}
EmployeeService
public interface EmployeeService {/*增加*/int add(Employee employee);/*修改*/int update(Employee employee);/*删除*/int delete(Long id);/*查询所有*/List<Employee> list();/*根据id查询*/Employee selectOne(Long id);/*分页查询*/PageResult<Employee> queryByPage(QueryObject qo);
}
12 service实现类
UserServiceImpl
public class UserServiceImpl implements UserService {private UserDao userDao=new UserDaoImpl();@Overridepublic Users login(String username, String password) {Users users = userDao.queryByUsername(username);//判断账号if(users==null){//账号错误throw new RuntimeException("账号错误");}//判断密码if(!users.getPassword().equals(password)){//密码错误throw new RuntimeException("密码错误");}return users;}@Overridepublic int updateImg(Users users) {int row = userDao.updateImg(users);return row;}
}
ProductServiceImpl
public class ProductServiceImpl implements EmployeeService {private EmployeeDao employeeDao=new EmployeeDaoImpl();@Overridepublic int add(Employee employee) {return employeeDao.add(employee);}@Overridepublic int update(Employee employee) {return employeeDao.update(employee);}@Overridepublic int delete(Long id) {return employeeDao.delete(id);}@Overridepublic List<Employee> list() {return employeeDao.list();}@Overridepublic Employee selectOne(Long id) {return employeeDao.selectOne(id);}/*分页查询*/@Overridepublic PageResult<Employee> queryByPage(QueryObject qo) {//查询总条数int totalCount = employeeDao.queryCount(qo);if(totalCount==0){return new PageResult<>(qo.getCurrentPage(),qo.getPageSize(),0, Collections.emptyList());}//查询分页商品集合List<Employee> list = employeeDao.queryPage(qo);//创建分页对象PageResult<Employee> pageResult=new PageResult<>(qo.getCurrentPage(),qo.getPageSize(),totalCount,list);return pageResult;}
}
13 分页QO
QueryObject
@Setter
@Getter
public class QueryObject {private Integer currentPage=1;private Integer pageSize=3;public int getStart(){return (currentPage-1)*pageSize;//计算查询的起始索引}
}
14 所需的工具类
MybatisUtil
public class MybatisUtil {private static SqlSessionFactory factory=null;static {try {InputStream rs = Resources.getResourceAsStream("mybatis-config.xml");factory = new SqlSessionFactoryBuilder().build(rs);} catch (IOException e) {e.printStackTrace();}}public static SqlSession getSqlSession(){return factory.openSession(true);}
}
PageResult
@Setter
@Getter
public class PageResult<T> {//上一页private Integer prevPage;//下一页private Integer nextPage;//总条数private Integer totalCount;//总页数private Integer totalPage;//当前页码private Integer currentPage;//每页显示条数private Integer pageSize;//查询的集合private List<T> list;/*初始化分页对象有参构造*/public PageResult(Integer currentPage,Integer pageSize,Integer totalCount,List<T> list){this.currentPage=currentPage;this.pageSize=pageSize;this.totalCount=totalCount;this.list=list;//总页数=总条数/每页显示条数 当求模运算值不等于0的时候总页数加1this.totalPage=(this.totalCount%this.pageSize==0)?(this.totalCount/this.pageSize):(this.totalCount/this.pageSize+1);//上一页this.prevPage=(this.currentPage==1)?(1):(this.currentPage-1);//下一页this.nextPage=(this.currentPage==this.totalPage)?(this.totalPage):(this.currentPage+1);}
}
StringUtil
public class StringUtil {public static boolean hasLength(String s){//判断输入的表单参数是否为空return s!=null && s.trim().length()!=0;}
}
UploadUtil
public class UploadUtil {public static String uploadImg(HttpServletRequest req, HttpServletResponse resp,Part part,String path){try {//上传文件的类型String contentType = part.getContentType();if (!contentType.startsWith("image")){//上传的不是图片,页面给出提示req.setAttribute("errorMsg","上传的文件必须是图片!");req.getRequestDispatcher("register.jsp").forward(req,resp);return null;}//获取文件的名称:pic.pngString fileName = part.getSubmittedFileName();//获取源文件类型或后缀名String type= fileName.substring(fileName.lastIndexOf("."));String s = UUID.randomUUID().toString().replace("-","");//使用uuid生成32位随机字符//设置新的文件名称String newfilename=s+type;//设置上传的目标目录地址
// String path="D:\\java\\upload\\";//将上传的文件保存到目标地址part.write(path+newfilename);return newfilename;} catch (Exception e) {e.printStackTrace();}return null;}
}