一 登录流程
将服务器资源给有权限的人访问,只有登录的管理员可以访问员工信息进行 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 mapper
PUBLIC "-//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 mapper
PUBLIC "-//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 configuration
PUBLIC "-//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();
@Override
public Users queryByUsername(String username) {
return sqlSession.selectOne("cn.tj.mapper.UserMapper.queryByUsername", username);
}
@Override
public int updateImg(Users users) {
return sqlSession.update("cn.tj.mapper.UserMapper.updateImg",users);
}
}
EmployeeDaoImpl
public class EmployeeDaoImpl implements EmployeeDao {
/*定义成员变量*/
private SqlSession sqlSession= MybatisUtil.getSqlSession();
@Override
public int add(Employee employee) {
int row = sqlSession.insert("cn.tj.mapper.EmployeeMapper.add", employee);
return row;
}
@Override
public int update(Employee employee) {
int row= sqlSession.update("cn.tj.mapper.EmployeeMapper.update",employee);
return row;
}
@Override
public int delete(Long id) {
int row= sqlSession.delete("cn.tj.mapper.EmployeeMapper.delete",id);
return row;
}
@Override
public List<Employee> list() {
List<Employee> list = sqlSession.selectList("cn.tj.mapper.EmployeeMapper.list");
return list;
}
@Override
public Employee selectOne(Long id) {
Employee employee= sqlSession.selectOne("cn.tj.mapper.EmployeeMapper.selectOne", id);
return employee;
}
@Override
public int queryCount(QueryObject qo) {
return sqlSession.selectOne("cn.tj.mapper.EmployeeMapper.queryCount",qo);
}
@Override
public 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();
@Override
protected 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 {
//获取session
HttpSession session = req.getSession();
// session.invalidate();//销毁session
session.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 EmployeeServiceImpl();
@Override
protected 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();
/*将参数的获取及封装对象过程抽取成一个方法*/
req2employee(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 req2employee(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.jsp
req.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 {
//获取目标id
String 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();
@Override
public 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;
}
@Override
public int updateImg(Users users) {
int row = userDao.updateImg(users);
return row;
}
}
EmployeeServiceImpl
public class EmployeeServiceImpl implements EmployeeService {
private EmployeeDao employeeDao=new EmployeeDaoImpl();
@Override
public int add(Employee employee) {
return employeeDao.add(employee);
}
@Override
public int update(Employee employee) {
return employeeDao.update(employee);
}
@Override
public int delete(Long id) {
return employeeDao.delete(id);
}
@Override
public List<Employee> list() {
return employeeDao.list();
}
@Override
public Employee selectOne(Long id) {
return employeeDao.selectOne(id);
}
/*分页查询*/
@Override
public 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的时候总页数加1
this.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.png
String 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;
}
}