1、JavaWeb学习(smbms准备工作)
1、Http响应
200:请求成功
3xx:请求重定向
4xx:资源不存在
5xx:服务器代码错误 500
502:网关错误
2、两个时代
-
http 1.0
-
HTTP/1.0:客户端可以与web服务器连接后,只能获得一个web资源,断开连接
-
-
http 2.0
-
HTTP/1.1:客户端可以与web服务器连接后,可以获得多个web资源
-
-
https是安全的,端口号443;http端口号80
3、Maven
自动帮忙导入和配置jar包
4、Servlet(初学)
Ctrl + o 可以快速重写( override ) doGet和doPost方法
-
在类中重写完doGet等方法后,进入web.xml中写注释,映射才能反映到浏览器中显示
public class ErrorServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/html");//响应的类型为html resp.setCharacterEncoding("UTF-8");//字符集类型为UTF-8 PrintWriter writer = resp.getWriter(); writer.println("<h1>404</h1>"); super.doGet(req, resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { super.doPost(req, resp); } }
//继承父亲类的接口 public class HelloServlet extends HttpServlet { //由于get或者post只是请求实现的不同方式,可以相互调用,业务逻辑一样 @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("进入了doGet方法"); PrintWriter writer = resp.getWriter();//响应流 writer.println("<html>"); super.doGet(req, resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { super.doPost(req, resp); } }
web.xml
<web-app> <display-name>Archetype Created Web Application</display-name> <!-- 注册Servlet映射,为了能在浏览器中访问--> <servlet> <servlet-name>hello</servlet-name> <servlet-class>com.mao.servlet.HelloServlet</servlet-class> </servlet> <!-- Servlet的请求路径--> <!-- url-pattern这里必须是/开头,不能只是hello servlet的映射地址必须以 “/” 开头 *前面不能加项目映射的路径 --> <servlet-mapping> <!-- mapping映射--> <servlet-name>hello</servlet-name> <url-pattern>/hello</url-pattern> </servlet-mapping> <!-- 404报错--> <servlet> <servlet-name>error</servlet-name> <servlet-class>com.mao.servlet.ErrorServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>error</servlet-name> <!-- 通配符,访问下面的任意网页--> <url-pattern>/*</url-pattern> </servlet-mapping> </web-app>
2、搭建一个Maven项目
-
创建一个Maven web app的项目
-
把pom.xml删干净
-
建立java包、resources包
-
把Tomcat最新的web.xml的内容移植到maven项目中的web.xml中,删除tomcat多余内容
-
配置tomcat
-
测试项目是否能够进入index.jsp
-
导入jar包,通过pom.xml进行导入
-
导入Mysql的jar包时出现问题,版本号不对应
-
例如我自己是8.0的版本,需要补齐8.0.32才能自动加载成功
-
-
导入javax.servlet的jar包
-
导入javax.servlet.jsp的jar包
-
导入JSTL、Standard的jar包
-
-
编写实体类
1、编写实体类
-
根据数据库中的变量、变量类型在IDEA中定义字段
-
获取其get / set方法,用于返回具体值
-
特殊的:年龄字段应为 当前年份 — 出生年份
-
-
-
用Integer去定义时,需要大写!!!!同时定义访问权限如:private等
1.1 实体类的编写其实就是在ORM映射的过程 从表 到 类的映射
package com.mao.pojo; import java.math.BigDecimal; import java.util.Date; public class Bill { private Integer id; private String billCode;//账单编码 private String productName; private String productDesc; private String productUnit;//账单单位 private BigDecimal productCount; private BigDecimal totalPrice; private Integer isPayment; private Integer createdBy; private Date createDate; private Integer modifyBy; private Date modifyDate; private Integer providerId;//供应商ID private String providerName; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getBillCode() { return billCode; } public void setBillCode(String billCode) { this.billCode = billCode; } public String getProductName() { return productName; } public void setProductName(String productName) { this.productName = productName; } public String getProductDesc() { return productDesc; } public void setProductDesc(String productDesc) { this.productDesc = productDesc; } public String getProductUnit() { return productUnit; } public void setProductUnit(String productUnit) { this.productUnit = productUnit; } public BigDecimal getProductCount() { return productCount; } public void setProductCount(BigDecimal productCount) { this.productCount = productCount; } public BigDecimal getTotalPrice() { return totalPrice; } public void setTotalPrice(BigDecimal totalPrice) { this.totalPrice = totalPrice; } public Integer getIsPayment() { return isPayment; } public void setIsPayment(Integer isPayment) { this.isPayment = isPayment; } public Integer getCreatedBy() { return createdBy; } public void setCreatedBy(Integer createdBy) { this.createdBy = createdBy; } public Date getCreateDate() { return createDate; } public void setCreateDate(Date createDate) { this.createDate = createDate; } public Integer getModifyBy() { return modifyBy; } public void setModifyBy(Integer modifyBy) { this.modifyBy = modifyBy; } public Date getModifyDate() { return modifyDate; } public void setModifyDate(Date modifyDate) { this.modifyDate = modifyDate; } public Integer getProviderId() { return providerId; } public void setProviderId(Integer providerId) { this.providerId = providerId; } public String getProviderName() { return providerName; } public void setProviderName(String providerName) { this.providerName = providerName; } }
package com.mao.pojo; import java.util.Date; public class Provider { private Integer id; private String proCode;//供应商编码 private String proName; private String proDesc; private String proContact; private String proPhone; private String proAddress; private String proFax;//供应商传真 private Integer createdBy; private Date creationDate; private Date modifyDate; private Integer modifyBy; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getProCode() { return proCode; } public void setProCode(String proCode) { this.proCode = proCode; } public String getProName() { return proName; } public void setProName(String proName) { this.proName = proName; } public String getProDesc() { return proDesc; } public void setProDesc(String proDesc) { this.proDesc = proDesc; } public String getProContact() { return proContact; } public void setProContact(String proContact) { this.proContact = proContact; } public String getProPhone() { return proPhone; } public void setProPhone(String proPhone) { this.proPhone = proPhone; } public String getProAddress() { return proAddress; } public void setProAddress(String proAddress) { this.proAddress = proAddress; } public String getProFax() { return proFax; } public void setProFax(String proFax) { this.proFax = proFax; } public Integer getCreatedBy() { return createdBy; } public void setCreatedBy(Integer createdBy) { this.createdBy = createdBy; } public Date getCreationDate() { return creationDate; } public void setCreationDate(Date creationDate) { this.creationDate = creationDate; } public Date getModifyDate() { return modifyDate; } public void setModifyDate(Date modifyDate) { this.modifyDate = modifyDate; } public Integer getModifyBy() { return modifyBy; } public void setModifyBy(Integer modifyBy) { this.modifyBy = modifyBy; } }
package com.mao.pojo; import java.util.Date; public class Role { private Integer id; private String roleCode;//角色编码 private String roleName; private Integer createBy; private Date creationDate; private Integer modifyBy; private Date modifyDate; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getRoleCode() { return roleCode; } public void setRoleCode(String roleCode) { this.roleCode = roleCode; } public String getRoleName() { return roleName; } public void setRoleName(String roleName) { this.roleName = roleName; } public Integer getCreateBy() { return createBy; } public void setCreateBy(Integer createBy) { this.createBy = createBy; } public Date getCreationDate() { return creationDate; } public void setCreationDate(Date creationDate) { this.creationDate = creationDate; } public Integer getModifyBy() { return modifyBy; } public void setModifyBy(Integer modifyBy) { this.modifyBy = modifyBy; } public Date getModifyDate() { return modifyDate; } public void setModifyDate(Date modifyDate) { this.modifyDate = modifyDate; } }
package com.mao.pojo; import java.util.Date; public class User { private Integer id; private String userCode;//用户编码 private String userName; private String userPassword; private Integer gender; private Date birthday; private String phone; private String address; private Integer userRole; private Integer createBy;//创建角色 private Date creationDate;//创建日期 private Integer modifyBy;//更新者 private Date modifyDate;//更新日期 private String idPicPath; private String workPicPath; private Integer age;//年龄 private String userRoleName;//用户角色名称 /*特殊的日期计算——必须掌握*/ public Integer getAge() { //导入Date工具包,利用当前年份 —— 出生年份 得到年龄 Date date = new Date(); Integer age = date.getYear() - birthday.getYear(); return age; } public void setAge(Integer age) { this.age = age; } public String getUserRoleName() { return userRoleName; } public void setUserRoleName(String userRoleName) { this.userRoleName = userRoleName; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getUserCode() { return userCode; } public void setUserCode(String userCode) { this.userCode = userCode; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public String getUserPassword() { return userPassword; } public void setUserPassword(String userPassword) { this.userPassword = userPassword; } public Integer getGender() { return gender; } public void setGender(Integer gender) { this.gender = gender; } public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } public String getPhone() { return phone; } public void setPhone(String phone) { this.phone = phone; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public Integer getUserRole() { return userRole; } public void setUserRole(Integer userRole) { this.userRole = userRole; } public Integer getCreateBy() { return createBy; } public void setCreateBy(Integer createBy) { this.createBy = createBy; } public Date getCreationDate() { return creationDate; } public void setCreationDate(Date creationDate) { this.creationDate = creationDate; } public Integer getModifyBy() { return modifyBy; } public void setModifyBy(Integer modifyBy) { this.modifyBy = modifyBy; } public Date getModifyDate() { return modifyDate; } public void setModifyDate(Date modifyDate) { this.modifyDate = modifyDate; } public String getIdPicPath() { return idPicPath; } public void setIdPicPath(String idPicPath) { this.idPicPath = idPicPath; } public String getWorkPicPath() { return workPicPath; } public void setWorkPicPath(String workPicPath) { this.workPicPath = workPicPath; } }
1.2 编写基础公共类(重点)
-
数据库配置文件
//驱动器 driver = com.mysql.jdbc.Driver //地址(后面加了两个保证安全的验证) url = jdbc:mysql://localhost:3306?useSSL=true&useUnicode=true&usecharacterEncoding=utf-8 //用户名和密码 username = root password = 123456
-
编写数据库的公共类(BaseDao、提供对数据库的基本操作)
package com.mao.dao; import com.mysql.jdbc.Driver; import java.io.IOException; import java.io.InputStream; import java.sql.*; import java.util.Objects; import java.util.Properties; /* * BaseDao 是一种通用的数据访问对象(DAO),用于提供对数据库的基本操作,例如插入、更新、删除和查询数据等 * */ //操作数据库的公共类 public class BaseDao { //定义字段(静态方便调用) private static String driver; private static String url; private static String username; private static String password; //静态代码块,类加载的时候就初始化了,将获取的数据转成流的形式 static{ //properties 是一个 Java 类,可以用来读取、写入 properties 文件。 //这个对象可以用来储存一组 key-value 对,方便配置文件的读取、写入等操作。 Properties properties = new Properties(); /* 通过类加载器读取对应的资源转成流的形式,InputStream 提供了从输入流中读取数据的方法,通过对象能够去调用方法 Class是当前类的Class对象,Class.getClassLoader()是获取当前类的类加载器。类加载器的大概作用是当需要使用一个类时,加载该类 的".class"文件并创建对应的class对象,将class文件加载到虚拟机的内存。 getResourceAsStream()是获取资源的输入流,当使用Class.getClassLoader.getResourceAsStream()加载资源时 是从classPath路径下进行加载,放在resources下的文件加载时不能加(“/”) */ InputStream is = BaseDao.class.getClassLoader().getResourceAsStream("db.properties"); try { //加载properties 文件,读取数据库的连接 properties.load(is); } catch (IOException e) { throw new RuntimeException(e); } //通过getProperty方法获取数据库参数,四个参数被获取并赋值 driver = properties.getProperty("driver"); url = properties.getProperty("url"); username = properties.getProperty("username"); password = properties.getProperty("password"); } //获取数据库的连接 //Connection 对象是JDBC(Java数据库连接)中的一个接口,它代表着与数据库的物理连接。 //通过这个对象,您可以与数据库建立通信,发送SQL语句,并获取查询结果。 public static Connection getConnection(){ Connection connection = null; try { //此为一个静态方法,用于提前加载类 Class.forName(driver); //返回一个connection对象 //DriverManager 是 Java JDBC API 的一部分,用于管理数据库驱动程序和建立数据库连接。 //它的主要功能包括注册数据库驱动程序、创建数据库连接以及管理数据库连接池 //将数据库的三个大属性获取再传给connection,用于获取连接 connection = DriverManager.getConnection(url,username,password); } catch (Exception e) { throw new RuntimeException(e); } return connection; } //编写查询公共类 public static ResultSet execute(Connection connection, String sql, Object[] params,ResultSet resultSet,PreparedStatement preparedStatement) throws SQLException{ //预编译传sql,在后面直接执行就可以了,PreparedStatement 是 Java 中用于执行预编译 SQL 语句的接口 preparedStatement = connection.prepareStatement(sql); for (int i = 0; i < params.length; i++) { //setObject,占位符从1开始,但是我们的数组是从0开始的 preparedStatement.setObject(i + 1, params[i]); } //执行查询返回结果数据集 resultSet = preparedStatement.executeQuery(); return resultSet; } //编写增删改公共方法 public static int execute(Connection connection, String sql, Object[] params,PreparedStatement preparedStatement) throws SQLException{ preparedStatement = connection.prepareStatement(sql); for (int i = 0; i < params.length; i++) { //setObject,占位符从1开始,但是我们的数组是从0开始的 //使用PreparedStatement:是Statement的子接口,可以传入带占位符的SQL语句,提供了补充占位符变量的方法 //作用如下: // String sql="insert into examstudent values(?,?,?,?,?,?,?)"; preparedStatement.setObject(i + 1, params[i]); } //本质上是只修改了这里的处理方法,返回值变成 整数型的行数 也就是修改的行数 int updateRows = preparedStatement.executeUpdate(); return updateRows; } //释放资源 public static boolean closeResource(Connection connection, ResultSet resultSet, PreparedStatement preparedStatement){ boolean flag = true; //资源若存在,进入语句块进行关闭 if(resultSet != null){ try { resultSet.close(); //若未关闭,则GC回收 resultSet = null; } catch (SQLException e) { e.printStackTrace(); //关闭失败 flag = false; } } if(connection != null){ try { connection.close(); //若未关闭,则GC回收 connection = null; } catch (SQLException e) { e.printStackTrace(); flag = false; } } if(preparedStatement != null){ try { preparedStatement.close(); //若未关闭,则GC回收 preparedStatement = null; } catch (SQLException e) { e.printStackTrace(); flag = false; } } //最后返回一个释放资源的结果 return flag; } }
-
编写字符编码过滤器
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="https://jakarta.ee/xml/ns/jakartaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_6_0.xsd" version="6.0" metadata-complete="true"> <!-- 字符编码过滤器--> <filter> <filter-name>CharacterEncodingFilter</filter-name> <!-- 所用到的类的地址--> <filter-class>com.mao.filter.CharacterEncodingFilter</filter-class> </filter> <filter-mapping> <filter-name>CharacterEncodingFilter</filter-name> <!-- 模式: /* 表示所有请求都会被过滤--> <url-pattern>/*</url-pattern> </filter-mapping> <!-- 设置欢迎界面--> <welcome-file-list> <welcome-file>login.jsp</welcome-file> </welcome-file-list> </web-app>
-
Filter过滤器的类
package com.mao.filter; import javax.servlet.*; import java.io.IOException; public class CharacterEncodingFilter implements Filter { public void init(FilterConfig filterConfig) throws ServletException { } public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { request.setCharacterEncoding("UTF-8"); response.setCharacterEncoding("UTF-8"); chain.doFilter(request,response); } public void destroy() { } }
-
2、导入静态资源
导入login.jsp和静态资源,启动Tomcat进入网页的登录界面
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head lang="en"> <meta charset="UTF-8"> <title>系统登录-超市订单管理系统</title> <link type="text/css" rel="stylesheet" href="${pageContext.request.contextPath}/statics/css/style.css"> <script> </script> </head> <body class="login_bg"> <section class="loginBox"> <header class="loginHeader"> <h1>超市订单管理系统</h1> </header> <section class="loginCont"> <%-- action 的 login.do 判断是否登录成功--%> <form class="loginForm" action="${pageContext.request.contextPath}/login.do" name="actionForm" id="actionForm" method="post"> <div class="info">${error}</div> <div class="inputbox"> <label>用户名:</label> <input type="text" class="input-text" id="userCode" name="userCode" placeholder="请输入用户名" required/> </div> <div class="inputbox"> <label>密码:</label> <input type="password" id="userPassword" name="userPassword" placeholder="请输入密码" required/> </div> <div class="subBtn"> <input type="submit" value="登录"/> <input type="reset" value="重置"/> </div> </form> </section> </section> </body> </html>
3、登录功能的实现
1. Dao层(持久层)
(1) dao层登录用户登录的接口
package com.mao.dao.user; import com.mao.pojo.User; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; //接口只是抽象的一个约束,不去真正的实现方法,所以只需要定义它的方法即可 public interface UserDao { //得到要登录的用户(根据userCode去查询要查询的数据,如admin ) //Connection用于与数据库的物理连接通信,发送sql语句,并获取查询结果 //这里出现了一个问题,使用抽象类方法后,需要去重写这个方法,重写这个方法需要注意的是参数值、参数类型、参数个数必须一致,否则会报错 public User getLoginUser(Connection connection, String userCode) throws SQLException; }
(2) dao接口的实现类
-
真正实现dao接口的实现类,注意抽象方法的真正实现的参数情况
package com.mao.dao.user; import com.mao.dao.BaseDao; import com.mao.pojo.User; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; //实现接口的方法,接口只是一个约束,实现才是具体的事情(接口的真正实现) public class UserDaoImpl implements UserDao { public User getLoginUser(Connection connection, String userCode) throws SQLException { //就不在方法头上进行传参了,直接在下面进行定义 PreparedStatement pstm = null; ResultSet rs = null; User user = null; if (connection != null) { //where后的条件语句用于获取预编译的userCode数据,安全考虑 String sql = "select * from smbms_user where userCode = ?"; //封装参数(用于存储后访问获取) Object[] params = {userCode}; //连接数据库后,sql语句传递给rs参数 rs = BaseDao.execute(connection, pstm, rs, sql, params); //挨个对数据库中存在的数据进行遍历 if (rs.next()) { user = new User(); user.setId(rs.getInt("id")); user.setUserCode(rs.getString("userCode")); user.setUserName(rs.getString("userName")); user.setUserPassword(rs.getString("userPassword")); user.setGender(rs.getInt("gender")); user.setBirthday(rs.getDate("birthday")); user.setPhone(rs.getString("phone")); user.setAddress(rs.getString("address")); user.setUserRole(rs.getInt("userRole")); user.setCreateBy(rs.getInt("createdBy")); user.setCreationDate(rs.getTimestamp("creationDate")); user.setModifyBy(rs.getInt("modifyBy")); user.setModifyDate(rs.getTimestamp("modifyDate")); user.setIdPicPath(rs.getString("idPicPath")); user.setWorkPicPath(rs.getString("workPicPath")); } //对资源的关闭(连接可以不用关闭,因为有别的层可能还需要)关闭时需要注意关闭顺序 BaseDao.closeResource(null, pstm, rs); } return user; } }
2. Service层(业务层)
(1) 业务层的接口(service层)
package com.mao.service.user; import com.mao.pojo.User; //用户登录的业务层 public interface UserService { //用户登录的抽象方法,包括用户名和密码,有具体实现类 public User login(String userCode, String password); }
(2) 业务层接口的实现类(service层)
package com.mao.service.user; import com.mao.dao.BaseDao; import com.mao.dao.user.UserDao; import com.mao.dao.user.UserDaoImpl; import com.mao.pojo.User; import org.junit.jupiter.api.Test; import java.sql.Connection; import java.sql.SQLException; public class UserServiceImpl implements UserService { //service层调用dao层,因为业务层都会调用dao层,所以引入dao层 private UserDao userDao; //实现dao接口的被调用 public UserServiceImpl() { userDao = new UserDaoImpl(); } //抽象方法的重写,注意参数 @Override public User login(String userCode, String password) { Connection connection = null; User user = null; try { //Dao层获得了数据库的连接传到Service层中继续使用 connection = BaseDao.getConnection(); //通过业务层调用对应的具体的数据库操作 user = userDao.getLoginUser(connection, userCode); } catch (SQLException e) { throw new RuntimeException(e); } finally { //关闭连接,以免资源浪费 BaseDao.closeResource(connection,null,null); } //最后返回得到的user对象 return user; } //单元测试用例,需要在pom.xml中导入junit依赖 /* 测试是否能够正确调用数据库中的数据,这里是传admin进去获取其密码,我们可以看到密码不受我们所提前定义的123abc所影响 测试说明,只与我们传入的userCode有关,根据userCode去查询其密码 */ @Test public void test(){ UserServiceImpl userService = new UserServiceImpl(); User admin = userService.login("ass", "7867"); System.out.println(admin.getUserPassword()); } }
3. Servlet层(控制服务层)
package com.mao.servlet.user; import com.mao.pojo.User; import com.mao.service.user.UserService; import com.mao.service.user.UserServiceImpl; import com.mao.util.Constants; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServlet; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; //首先要继承内部的HttpServlet类 public class LoginServlet extends HttpServlet { // Servlet: 控制层,调用业务层代码 @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //通过request请求获取用户名和密码 String userCode = req.getParameter("userCode"); String userPassword = req.getParameter("userPassword"); //和数据库中的密码进行对比,调用业务层(通过接口进行调用) UserService userService = new UserServiceImpl(); User user = userService.login(userCode, userPassword);//后半段是调用login的登录方法,获取用户名和密码,前半段是获取后传递给user对象 //判断是否查有此人,可以登录,并请信息传递给Constants类里的常量,完成登录后进行跳转 if (user != null) { //将用户的信息放到Session中 req.getSession().setAttribute(Constants.User_Session, user); //跳转到主页(请求重定向——用于跳转网页) resp.sendRedirect("jsp/frame.jsp"); } else { //页面相应请求,与jsp页面中的 ${error} 进行相应 并返回字符串提示 req.setAttribute("error","用户名或密码错误"); /* getRequestDispatcher()包含两个重要方法,分别是请求转发和请求包含。一个请求跨多个Servlet时,需要使用请求转发和请求包含。 首先需要获得一个RequestDispatcher 对象:RequestDispatcher rd = request.getRequestDispatcher("/MyServlet"); 请求转发: rd.forward( request , response ); 请求包含: rd.include( request , response); */ //请求转发到新页面,并带入两个请求参数 req.getRequestDispatcher("login.jsp").forward(req,resp); } } @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { super.doGet(req, resp); } }
(1) 工具类的常量设定(此处为了存储获取的用户信息)
package com.mao.util; public class Constants { //编写常量,用于存储控制层获取到的业务层字符段属性 public final static String User_Session = "userSession";//等待被调用 }
(2) Frame.jsp的编写
<%-- Created by IntelliJ IDEA. User: Administrator Date: 2021/1/27 Time: 19:57 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@ include file="/jsp/common/head.jsp"%> <div class="right"> <img class="wColck" src="${pageContext.request.contextPath}/statics/images/clock.jpg" alt=""/> <div class="wFont"> <h2>${userSession.userName}</h2> <p> 欢迎来到超市订单管理系统!</p> </div> </div> </section> <%@ include file="/jsp/common/foot.jsp"%>
(3) web.xml 中 servlet的注册
<!--编写Servlet的xml文件 注册Servlet文件--> <servlet> <servlet-name>LoginServlet</servlet-name> <servlet-class>com.mao.servlet.user.LoginServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>LoginServlet</servlet-name> <!-- 登录请求页面--> <url-pattern>/login.do</url-pattern> </servlet-mapping>
这里出现一个问题,frame.jsp中某一行代码的初始化失败,经检查是 pom.xml的依赖没有导入
<!-- https://mvnrepository.com/artifact/org.apache.taglibs/taglibs-standard-spec--> <dependency> <groupId>org.apache.taglibs</groupId> <artifactId>taglibs-standard-spec</artifactId> <version>1.2.5</version> </dependency> <!-- https://mvnrepository.com/artifact/org.glassfish.web/jakarta.servlet.jsp.jstl--> <dependency> <groupId>org.glassfish.web</groupId> <artifactId>jakarta.servlet.jsp.jstl</artifactId> <version>3.0.1</version> </dependency>
(4) 测试登录成功后,注销登录
思路:将session的信息进行移除,然后返回到登录界面
package com.mao.servlet.user; import com.mao.util.Constants; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServlet; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; //先要继承HttpServlet服务类 public class LogoutServlet extends HttpServlet { //servlet层进行业务服务,编写业务逻辑!doPost、doGet,利用快捷键Ctrl + o @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //清除已经保存的session信息,再重定向回登录界面(但是此处还需要进行优化、因为没有做登录拦截优化,简单来说就是复制登录后的地址同样能进入,无须账号密码) req.getSession().removeAttribute(Constants.User_Session);//对工具常量类的对象进行移除,接着进行重定向 resp.sendRedirect("/login.jsp");//重定向需要编写退出的xml文件 } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { super.doPost(req, resp); } }
编写注销登录的xml文件
<!-- 注销登录的xml文件--> <servlet> <servlet-name>LogoutServlet</servlet-name> <servlet-class>com.mao.servlet.user.LogoutServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>LogoutServlet</servlet-name> <url-pattern>/logout.do</url-pattern> </servlet-mapping>
(5) 登录拦截优化
编写系统过滤类(此处必须导入jakarta.servlet的包,而不是javax.servlet的包)
package com.mao.filter; import com.mao.pojo.User; import com.mao.util.Constants; import jakarta.servlet.*; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; //登录拦截过滤器 public class SysFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { Filter.super.init(filterConfig); } @Override public void destroy() { Filter.super.destroy(); } //系统拦截登录过滤优化 @Override public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException { /*1. 先定义请求变量 * 2. 通过请求变量去session中拿到信息 * 3. 判断是否获取到用户 * 4. 需要在xml文件中编写登录拦截过滤器 * */ //1.定义请求变量 HttpServletRequest request = (HttpServletRequest) req; HttpServletResponse response = (HttpServletResponse) resp; //2.获取session信息(通过常量类中存储的session信息),并且用变量进行接收 //这里出现了一个致命错误,我们是需要去拿到它的信息,而不是setAttribute设置它的信息 User user = (User) request.getSession().getAttribute(Constants.User_Session); //3.判断是否获取到用户 if (user == null) {//未登录、已退出登录、获取失败等情况,并重定向至错误界面 response.sendRedirect(request.getContextPath() + "/error.jsp"); } else {//获取到了用户就继续执行此过滤方法 chain.doFilter(req, resp); } //4.接着去xml文件中编写登录拦截过滤器 } }
编写登录拦截优化的xml文件
<!-- 登录拦截过滤器--> <filter> <filter-name>SysFilter</filter-name> <filter-class>com.mao.filter.SysFilter</filter-class> </filter> <filter-mapping> <filter-name>SysFilter</filter-name> <!-- 过滤jsp文件夹下面的所有文件--> <url-pattern>/jsp/*</url-pattern> </filter-mapping>
登录拦截后,检测到未登录或登录错误,则返回error.jsp界面
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>ERROR,Please return login.jsp</title> </head> <style type="text/css"> * { margin: 0; padding: 0; } body { background: url("${pageContext.request.contextPath}/statics/images/pic-error.png") 0 0 no-repeat; background-position:55% -70%; } /* body{ background-color: #ccc; } */ </style> <body> <!-- 使用输出全局异常信息--> <%-- <h1>全局异常信息:${exception.message}</h1> --%> <%-- 用来使用局部输出 <h1>${e}</h1> --%> <a href="${pageContext.request.contextPath }/login.jsp">返回</a> </body> </html>
4、密码修改
-
导入前端素材:pwdmodify.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@include file="/jsp/common/head.jsp" %> <div class="right"> <div class="location"> <strong>你现在所在的位置是:</strong> <span>密码修改页面</span> </div> <div class="providerAdd"> <form id="userForm" name="userForm" method="post" action="${pageContext.request.contextPath }/jsp/user.do"> <input type="hidden" name="method" value="savepwd"/> <!--div的class 为error是验证错误,ok是验证成功--> <div class="info">${message}</div> <div class=""> <label for="oldPassword">旧密码:</label> <input type="password" name="oldpassword" id="oldpassword" value=""> <font color="red"></font> </div> <div> <label for="newPassword">新密码:</label> <input type="password" name="newpassword" id="newpassword" value=""> <font color="red"></font> </div> <div> <label for="newPassword">确认新密码:</label> <input type="password" name="rnewpassword" id="rnewpassword" value=""> <font color="red"></font> </div> <div class="providerAddBtn"> <!--<a href="#">保存</a>--> <input type="button" name="save" id="save" value="保存" class="input-button"> </div> </form> </div> </div> </section> <%@include file="/jsp/common/foot.jsp" %> <script type="text/javascript" src="${pageContext.request.contextPath }/statics/js/pwdmodify.js"></script>
-
搞清楚逻辑,如图所示:(编写应该自底向上,先数据库,再Dao,再Service,再Servlet,因为他们存在调用关系,调用则是反过来)
6.1 UserDao层接口(修改用户密码)
//修改密码的抽象方法(返回值类型为int型、1则是修改成功,0则是修改失败)根据ID进行修改 public int updatePassword(Connection connection,int id,String password) throws SQLException;
6.2 修改密码的UserDao接口实现类
//修改当前用户密码 @Override public int updatePassword(Connection connection, int id, String password) throws SQLException { PreparedStatement pstm = null; int result = 0; //若连接不为空,也即没有进行此操作才进入执行语句 if (connection != null) { //编写即将执行的修改密码sql语句 String sql = "update smbms_user set userPassword = ? where id = ?"; //将修改后的id和密码存储在Object下的params数组内 Object[] params = {password, id}; //调用BaseDao的执行方法(参数一定不能漏,顺序也不可以错) 最后将执行完的方法返回至一个新的参数 result = BaseDao.execute(connection, pstm, sql, params); //关闭BaseDao的资源 BaseDao.closeResource(null, pstm, null); } return result; }
6.3 UserService层接口(针对业务的功能)
//用户修改密码 public boolean updatePassword(int id, String userPassword);
6.4 修改密码的UserService接口实现类
//用户修改密码 @Override public boolean updatePassword(int id, String userPassword) { //传数据库的连接,并获取数据库的url Connection connection = null; //定义一个布尔值的标记符,用于记录是否修改成功 Boolean flag = false; try { //通过调用BaseDao类的对象获取数据库url的值 connection = BaseDao.getConnection(); //加入判断,如果dao层修改成功返回的参数值为1,失败则为0,所以需要判断其值 if (userDao.updatePassword(connection, id, userPassword) > 0) { flag = true; } } catch (SQLException e) { throw new RuntimeException(e); }finally { //最后需要关闭BaseDao,以避免浪费资源 BaseDao.closeResource(connection, null, null); } //最后返回修改结果 return flag; }
6.5 UserServlet类的实现
本小节遇到了诸多问题:
-
首先是导包问题,必须是Jakarta.servlet的包才能让sql数据库进行实现
-
用于接收sql语句所得信息的数组,必须与sql语句的参数顺序一致
-
进行旧密码的校验
package com.mao.servlet.user; import com.alibaba.fastjson.JSONArray; import com.mao.pojo.User; import com.mao.service.user.UserService; import com.mao.service.user.UserServiceImpl; import com.mao.util.Constants; import com.mysql.cj.util.StringUtils; import com.mysql.cj.xdevapi.JsonArray; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServlet; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; import java.util.HashMap; import java.util.Map; import static com.mysql.cj.xdevapi.JsonArray.*; //实现Servlet的复用(将方法单独写出来,然后在doGet中调用即可) public class UserServlet extends HttpServlet { //需要在doGet中调用自己所写的方法,才能实现相应的操作 @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) { String method = req.getParameter("method"); //点保存修改密码后,跳转至此类中的修改密码方法 if (method.equals("savepwd") && method != null) { this.updatePwd(req, resp); } else if (method.equals("pwdmodify") && method != null) {//修改密码前的密码验证,跳转至此类中的密码验证方法 this.pwdModify(req, resp); } } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) { doGet(req, resp); } //修改密码 public void updatePwd(HttpServletRequest req, HttpServletResponse resp) { //从Session中拿到用户信息(User_Session中包含了用户的所有信息) Object object = req.getSession().getAttribute(Constants.User_Session); //获取新密码,用于判断密码是否为空,或者是新输入的密码是否相等 String newpassword = req.getParameter("newpassword"); System.out.println("UserServlet: " + newpassword); //定义一个标记符,用于返回修改是否成功的结果 boolean flag = false; System.out.println("String的状态:" + !(StringUtils.isNullOrEmpty(newpassword))); //判断获取的信息是否为空,或者密码是否为空 //这里需要用到一个jdbc已经定义好的StirngUtils if (object != null && !(StringUtils.isNullOrEmpty(newpassword))) { System.out.println("我进入Servlet层了"); //不为空则可以开始调用service层以及接口进行密码的更新操作,实现抽象方法 UserService userService = new UserServiceImpl(); //调用接口后,去实现具体的方法(通过id去修改密码,有两个参数),因为updatePassword最后返回的结果是布尔值,所以需要利用标记符 //同时这里需要把object强制转换为User类对象,才能去调用它的get方法,获取其id,newPassword不需要是因为在这个类就可以获取到 flag = userService.updatePwd(((User) object).getId(), newpassword); System.out.println("flag的状态:" + flag); //若修改成功,则告知用户成功,并移除已经存在的Session if (flag) { System.out.println("我成功修改了!"); req.setAttribute("message", "密码修改成功,请退出,使用新密码登录"); //移除Session信息 req.getSession().removeAttribute(Constants.User_Session); } else {//若失败,告知失败, System.out.println("我修改失败了!"); req.setAttribute("message", "密码修改失败!"); } } else { System.out.println("我压根进不去!"); req.setAttribute("message", "新密码有误"); } //修改后则跳转页面,做出转发操作,跳转到修改密码的界面(其实自我认为应该跳转到登录页面) try { req.getRequestDispatcher("pwdmodify.jsp").forward(req, resp); } catch (ServletException e) { throw new RuntimeException(e); } catch (IOException e) { throw new RuntimeException(e); } } //验证旧密码,session中有用户的密码 public void pwdModify(HttpServletRequest req, HttpServletResponse resp) { //从Session中拿到ID Object object = req.getSession().getAttribute(Constants.User_Session); //从前端页面拿到旧密码 String oldpassword = req.getParameter("oldpassword"); //万能的Map类:结果集 Map<String, String> resultMap = new HashMap<String, String>(); if (object == null) {//Session失效了,Session过期了 resultMap.put("result", "sessionerror"); } else if (StringUtils.isNullOrEmpty(oldpassword)) {//如果旧密码为空 resultMap.put("result", "error"); } else { String userPassword = ((User) object).getUserPassword();//Session中用户的密码 if(oldpassword.equals(userPassword)){ resultMap.put("result", "true");//比对成功 }else { resultMap.put("result", "false"); } } try { resp.setContentType("application/json"); PrintWriter writer = resp.getWriter(); //JSONArray 阿里巴巴的JSON工具类,转换格式 /* resultMap = ["result","sessionerror","result","error"] Json格式 = {key: value} * */ writer.write(JSONArray.toJSONString(resultMap)); writer.flush(); writer.close(); } catch (IOException e) { throw new RuntimeException(e); } } }
-
5、用户管理层实现
1. 导入分页的工具类
package com.mao.util; public class PageSupport { //当前页码-来自于用户输入 private int currentPageNo = 1; //总数量(表) private int totalCount = 0; //页面容量 private int pageSize = 0; //总页数-totalCount/pageSize(+1) private int totalPageCount = 1; public int getCurrentPageNo() { return currentPageNo; } public void setCurrentPageNo(int currentPageNo) { if(currentPageNo > 0){ this.currentPageNo = currentPageNo; } } public int getTotalCount() { return totalCount; } public void setTotalCount(int totalCount) { if(totalCount > 0){ this.totalCount = totalCount; //设置总页数 this.setTotalPageCountByRs(); } } public int getPageSize() { return pageSize; } public void setPageSize(int pageSize) { if(pageSize > 0){ this.pageSize = pageSize; } } public int getTotalPageCount() { return totalPageCount; } public void setTotalPageCount(int totalPageCount) { this.totalPageCount = totalPageCount; } public void setTotalPageCountByRs(){ if(this.totalCount % this.pageSize == 0){ this.totalPageCount = this.totalCount / this.pageSize; }else if(this.totalCount % this.pageSize > 0){ this.totalPageCount = this.totalCount / this.pageSize + 1; }else{ this.totalPageCount = 0; } } }
2. 用户列表页面的导入
count(1)比count(*)要高效,前者是查一个列表,后者则是查所有列表
3. 查询用户总数功能
(1) Dao接口的抽象方法
//查询用户总数 public int getUserCount(Connection connection,String userName,int userRole);
(2) Dao接口实现类
//根据用户名或者角色查询用户总数【最难理解的SQL语句】 @Override public int getUserCount(Connection connection, String userName, int userRole) { //预编译 PreparedStatement pstm = null; ResultSet rs = null; int count = 0; if (connection != null) { //StringBuffer在执行字符串拼接或修改操作时更加高效,这里我们要将sql语句转为此类的作用是,sql语句需要拼接 StringBuffer sql = new StringBuffer(); //append(String str): 将指定的字符串追加到此字符序列(接下来使用多表查询) sql.append("select count(1) as count from smbms_user u,smbms_role r where u.userRole = r.id"); //存放我们的参数列表,ArrayList 是一个可以动态调整大小的数组。它实现了 List 接口,可以存储重复的元素。 ArrayList<Object> list = new ArrayList<Object>(); //接下来进行判断 if (!StringUtils.isNullOrEmpty(userName)) { sql.append("and u.userName like ?"); list.add("%" + userName + "%");//此处list的index为0 } if (userRole > 0) { sql.append("and u.userRole = ?"); list.add(userRole);//此处list的index为1 } //怎么把List转换为数组 Object[] params = list.toArray(); //输出完整的sql语句用于调试 System.out.println("UserDaoImpl -> : " + sql.toString()); try { //执行底层BaseDao的方法 rs = BaseDao.execute(connection, pstm, rs, sql.toString(), params); if (rs.next()) { //从结果集中获取最终的数量 count = rs.getInt("count"); } } catch (SQLException e) { throw new RuntimeException(e); } } BaseDao.closeResource(null, pstm, rs); return count; }
(3) Service业务层调用Dao层进行查询操作
-
Service层接口
//查询用户总数 public int getUserCount(String userName,int userRole);
-
接口实现类
@Override public int getUserCount(String userName, int userRole) { //调用dao层即可,先建立连接,获取数据库连接 Connection connection = null; connection = BaseDao.getConnection(); int count = 0; //连接完数据库后,可以进行接口方法的调用了 count = userDao.getUserCount(connection, userName, userRole); //查询完毕后,关闭资源即可 BaseDao.closeResource(connection, null, null); return count; }
-
单元测试
//测试是否能够根据userRole的值获取其总数(测试成功) @Test public void test() { //首先需要将此类进行实例化,才能获取方法 UserServiceImpl userService = new UserServiceImpl(); int count = userService.getUserCount(null, 0);//这里放的参数意思是根据userRole等于1来查询,可随意更改 System.out.println(count); }
4. 根据条件查询用户列表
(1) Dao接口的抽象方法
//根据条件查询用户列表(Dao层接口) public List getUserList(Connection connection, String userName, int userRole, int currentPageNo, int pageSize) throws SQLException;
(2) Dao接口的实现类
//Dao层的接口实现类: //根据条件查询用户列表 @Override public List<User> getUserList(Connection connection, String userName, int userRole, int currentPageNo, int pageSize) throws SQLException { //执行sql语句的地方,先预编译 PreparedStatement pstm = null; ResultSet rs = null; //使用List动态存储数组(动态页) List<User> userList = new ArrayList<User>(); // 连接成功后,即连接不为空的情况下,继续向下走 if (connection != null) { //将sql语句转换为字符流的形式,便于增加修改操作 //实现动态拼接,若不需要则直接把sql写死 StringBuffer sql = new StringBuffer(); sql.append("select u.*,r.roleName as userRoleName from smbms_user u,smbms_role r where u.userRole = r.id"); //使用动态数组,存储获取到的动态人员信息(为什么需要list,一个原因是可能存在多个角色、这里需要动态的更新)最后只需要将自己add进去即可 ArrayList<Object> list = new ArrayList<>(); //查询所有人(只要用户名不为空则查询出来) if(!StringUtils.isNullOrEmpty(userName)) { sql.append(" and u.userName like ?"); list.add("%" + userName + "%"); } //根据用户的id来查询(区分用户角色)append用于追加sql的查询条件,限制级 if (userRole > 0) { sql.append(" and u.userRole = ?"); } //接下来是数据库的分页查询操作,分页使用 //limit startIndex pageSize //当前数据包含页 (当前页 - 1 ) * 页面大小 // 0,5(0,1,2,3,4) 1 0 (1-1)*5 // 5,5(5,6,7,8,9) 2 5 (2-1)*5 // 10,5(10,11,12,13,14) 3 10 (3-1)*5 sql.append("order by creationDate desc limit ?,?");//根据用户创建时间降序排序(limit限制页面展示数据从?到?) //那么当前页面要如何计算 currentPageNo = (currentPageNo - 1) * pageSize;//也就是上面的公式 list.add(currentPageNo);//将当前页存储至list动态数组中 list.add(pageSize);//将页面大小也存储进去 Object[] params = list.toArray();//将list对象转换为数组对象,因为我们定义的是数组对象,这样才能输出 System.out.println("UserDaoImpl -> : " + sql.toString());//用于debug当前sql语句是否有误 //接收Base处理的sql语句结果集 rs = BaseDao.execute(connection, pstm, rs, sql.toString(), params); //接收后,开始依次写入获取,用于后续的输出展示 while (rs.next()) { //从数据库中读取,然后通过set方法写入user对象 User user = new User(); user.setId(rs.getInt("id")); user.setUserCode(rs.getString("userCode")); user.setUserName(rs.getString("userName")); user.setGender(rs.getInt("gender")); user.setBirthday(rs.getDate("birthday")); user.setPhone(rs.getString("phone")); user.setUserRole(rs.getInt("userRole")); user.setUserRoleName(rs.getString("userRoleName"));//role表的字段,用于对比 //最后将user对象的值添加到userList动态数组中 userList.add(user); } //释放资源 BaseDao.closeResource(null, pstm, rs); } //最后返回动态数组 return userList; }
(3) 业务层Service去dao层调用获取结果到页面
//根据条件查询用户列表(Service层接口) public List<User> getUserList(String queryUserName,int queryUserRole,int currentPage,int pageSize);
//根据条件查询用户列表(分页) @Override public List<User> getUserList(String queryUserName, int queryUserRole, int currentPage, int pageSize) { //预定义连接为空,后再赋值 Connection connection = null; List<User> userList = null; System.out.println("queryUserName ---- > " + queryUserName); System.out.println("queryUserRole ---- > " + queryUserRole); System.out.println("currentPage ---- > " + currentPage); System.out.println("pageSize ---- > " + pageSize); try { //将BaseDao中处理的数据用connection接收 connection = BaseDao.getConnection(); userList = userDao.getUserList(connection, queryUserName, queryUserRole, currentPage, pageSize); } catch (SQLException e) { throw new RuntimeException(e); } //关闭资源 BaseDao.closeResource(connection, null, null); return userList; }
5、获取角色列表
(1) dao层接口的定义与接口实现
package com.mao.dao.role; import com.mao.pojo.Role; import java.sql.Connection; import java.sql.SQLException; import java.util.List; public interface RoleDao { //获取角色列表,只需要连接即可,抽象方法 public List<Role> getRoleList(Connection connection) throws SQLException; }
package com.mao.dao.role; import com.mao.dao.BaseDao; import com.mao.pojo.Role; import java.sql.*; import java.util.ArrayList; import java.util.List; public class RoleDaoImpl implements RoleDao { //获取角色列表 @Override public List<Role> getRoleList(Connection connection) throws SQLException { //预编译 PreparedStatement pstm = null; //结果集 ResultSet rs = null; //多角色列表需要List集合存储 ArrayList<Role> roleList = new ArrayList<>(); //如果连接不为空,即连接上数据库 if (connection != null) { //这里不需要去给sql进行扩展操作,直接写死就可以 String sql = "select * from smbms_role"; //需要一个数组进行存储从数据库中所获取的信息,初始值为空 Object[] params = {}; //去BaseDao底层执行sql语句再返回结果集,dao层接触底层,所以是执行sql,而service则是过来获取 rs = BaseDao.execute(connection, pstm, rs, sql, params); //开始读取写入到网页端,反馈数据 while (rs.next()) { Role role = new Role(); role.setId(rs.getInt("id")); role.setRoleName(rs.getString("roleName")); role.setRoleCode(rs.getString("roleCode")); //最后把自己这个对象添加到结果集 roleList.add(role); } //关闭资源 BaseDao.closeResource(null, pstm, rs); } return roleList; } }
(2) Service层(接口与实现)
package com.mao.service.role; import com.mao.pojo.Role; import java.util.List; public interface RoleService { //与dao层的抽象方法相对应,只是少了connection //查询角色列表 public List<Role> getRoleList(); }
package com.mao.service.role; import com.mao.dao.BaseDao; import com.mao.dao.role.RoleDao; import com.mao.dao.role.RoleDaoImpl; import com.mao.pojo.Role; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.util.List; public class RoleServiceImpl implements RoleService { //实例化RoleService,再通过一个构造函数去访问dao层,引入dao层 private RoleDao roleDao; public RoleServiceImpl(RoleDao roleDao) { //这里的赋值不能是简单的this指向,而是需要去调用接口 roleDao = new RoleDaoImpl(); } //实现抽象方法(获取角色列表) public List<Role> getRoleList() { //连接数据库执行操作 Connection connection = null; ResultSet rs = null; List<Role> roleList = null; try { //利用service层去dao层获取数据库的连接 connection = BaseDao.getConnection(); //获取数据库的连接后去调用想要使用的方法 roleList = roleDao.getRoleList(connection); } catch (SQLException e) { throw new RuntimeException(e); } finally {//最后关闭资源 BaseDao.closeResource(connection, null, null); } return roleList; } }
6、用户管理功能的实现(Servlet层)【重难点】
else if (method.equals("query") && method != null) {//对应前端页面head.jsp中的点击事件,响应其方法 //跳转当前类中的方法 this.query(req, resp); }
-
引入PageSupport.java,与前端的method --- name相对应
-
获取用户前端的数据(查询)
-
判断请求是否需要执行,看参数的值进行判断
-
为了实现分页,需要计算出当前页面和总页面,页面大小
-
用户列表展示
-
最后返回前端
//查询用户列表(方法体传入请求、相应参数) public void query(HttpServletRequest req, HttpServletResponse resp) { //每次的数据是单次获取的,而不是在session中获取(否则每次点到这个页面都需要清除再相应) /*额外的请求: 属性从前端进行获取(获取关键信息,如用户编码、用户名称即可,因为都有一个额外的请求) 根据用户名查询用户、根据用户角色查询用户、根据页面页码跳转页面、根据总记录数获取总共页数,所以需要以下几个属性 做了个表单的操作,文本框那些,req.getParameter() 的参数是前端元素的 name 属性。 */ String queryName = req.getParameter("queryname");//后面解析的参数必须与前端输入框的name属性值进行对应 String queryUserRoleTemp = req.getParameter("queryUserRole");//这三个变量都是初始化加载,反映在前端的数据 String pageIndex = req.getParameter("pageIndex");//从前端获取的当前页码 //默认定义当前角色为0,即系统管理员(主要是防止系统报错) int queryUserRole = 0; //获取用户列表(需要去service中业务拿取,然后在业务层中,又会去主动调用dao层进行连接数据库获取信息) UserService userService = new UserServiceImpl(); List<User> userList = null;//需要一个动态数组去存储未知容量的数据 //第一次走这个请求,一定是第一页,页面大小是固定的 int pageSize = 5;//如果用户的需求不是每页5个数据展示,可以将这个字段定义在配置文件中,用户就可以不用通过更改代码来达到其目的 int currentPageNo = 1;//进入管理页面,默认第一页 //这三个if判断,对应的是前端查询页面的,用户名文本框、用户角色下拉框以及当前页面 if (queryName == null) {//如果前端获取的用户名为null,那么则赋空字符串,也就是进入页面后,看到文本框是空的 queryName = "请键入数据"; } if (queryUserRoleTemp != null && !queryUserRoleTemp.equals("")) { //如果用户在下拉框进行选择了,那就进入判断,将前端传来的数据进行解析,给到我们想要的结果返回在前端页面,如userRole为0,1,2,3 queryUserRole = Integer.parseInt(queryUserRoleTemp); } if (pageIndex != null) { currentPageNo = Integer.parseInt(pageIndex);//解析前端的页码给后端 } //获取用户的总数(分页:上一页,下一页的情况) int totalCount = userService.getUserCount(queryName, queryUserRole); //总页数支持 PageSupport pageSupport = new PageSupport(); pageSupport.setCurrentPageNo(currentPageNo);//设置当前的页码值 pageSupport.setPageSize(pageSize);//设置当前页面大小 pageSupport.setTotalCount(totalCount);//设置当前总页数 int totalPageCount = pageSupport.getTotalPageCount();//获取总页面数 //控制首页和尾页 //如果页面要小于1了,就显示第一页的东西 if (currentPageNo < 1) { currentPageNo = 1; } else if (currentPageNo > totalPageCount) {//当前页面大于了最后一页,即显示最后一页 currentPageNo = totalPageCount; } //获取用户列表展示(根据条件查询用户列表时,同样页面要展示其他几个数据) userList = userService.getUserList(queryName, queryUserRole, currentPageNo, pageSize); req.setAttribute("userList", userList);//引号内是后续通过它来获取数据的 //调用service层,再间接调用dao层 RoleService roleService = new RoleServiceImpl(); //获取角色列表 List<Role> roleList = null; roleList = roleService.getRoleList(); req.setAttribute("roleList", roleList); req.setAttribute("queryName", queryName); req.setAttribute("queryUserRole", queryUserRole); req.setAttribute("totalPageCount", totalPageCount); req.setAttribute("currentPageNo", currentPageNo); req.setAttribute("totalCount", totalCount); //返回前端 try { req.getRequestDispatcher("userlist.jsp").forward(req,resp); } catch (ServletException e) { throw new RuntimeException(e); } catch (IOException e) { throw new RuntimeException(e); } }