实验五 Servlet控制层设计(设计性)
//代码放在资源包里了
- 实验目的
- 熟悉Servlet的基本语法。
- 掌握采用HTML、JS、JDBC、JSP、Servlet和四层结构的综合应用。
- 实验要求
- 本实验要求每个同学单独完成;
- 调试程序要记录调试过程中出现的问题及解决办法,并写入到实验总结和心得;
- 完成实验后直接在题目后面按要求给出本实验的实验报告。
- 实验设备、环境
奔腾以上计算机,装有Myeclipse 6.0以上。
- 实验内容
- 使用前面所介绍的Servlet知识构建一个登陆应用,具体要求如下:
-
- 创建一个登陆应用,如下图所示。
- 用户输入登陆信息,如用户名和密码,
- LoginServlet调用UserBean完成身份验证(编写UserService,UserDao类,完成数据的访问),如果身份验证成功,跳转到成功页面,否则,跳转到失败页面。
`
把程序运行界面截图贴在这里,源码贴到附录部分:
-
- 使用Servlet和四层结构知识,改进实验四中题4.2的用户信息管理系统,使其具有更好的软件结构,以及提升可读性和可扩展性。
把程序运行界面截图贴在这里,源码贴到附录部分:
- 实验总结与心得(请详细叙述你通过该实验掌握的知识点和心得,比如对错误的解决办法等)
问题:
1.java.lang.IllegalArgumentException: 名为 [LoginServlet]和 [com.example.controller.LoginServlet] 的servlet不能映射为一个url模式(url-pattern) [/login]
有两个Servlet试图映射到相同的URL模式(/login),这是不允许的。以下是解决此问题的步骤:
后面重新检查了web.xml配置,解决了问题
<servlet>
<servlet-name>LoginServlet</servlet-name>
<servlet-class>com.example.controller.LoginServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>LoginServlet</servlet-name>
<url-pattern>/login</url-pattern>
</servlet-mapping>
2. SQL异常处理:在与数据库交互时,我经常遇到SQLException。我学会了如何使用try-catch块来捕获异常,并在控制台输出错误信息。这不仅帮助我快速定位问题,还让我意识到在生产环境中需要更优雅的错误处理机制,比如记录日志或向用户显示友好的错误信息。
3.表单验证:在用户注册和登录过程中,我发现表单输入的有效性非常重要。我通过在JSP中使用required属性来确保用户输入的完整性。此外,我还学习了如何在服务层中进行更复杂的验证,比如检查用户名是否已存在。
4.调试技巧:在调试过程中,我使用了System.out.println和调试器来跟踪程序的执行流程。这让我能够清晰地看到每一步的输出,帮助我理解程序的运行状态。
心得:
表现层:学习了如何使用JSP页面来构建用户界面。通过JSP,我能够动态生成HTML内容,并与用户进行交互。理解了如何使用JSP表达式和脚本来处理用户输入和显示信息。
控制层:在UserServlet中,我实现了请求的处理逻辑。通过doPost和doGet方法,我能够根据不同的请求参数(如action)调用相应的服务层方法。这让我认识到控制层在MVC架构中的重要性,它负责协调表现层和服务层之间的交互。
服务层:在UserService中,我实现了用户注册、删除和验证等业务逻辑。通过将业务逻辑与控制层分离,我提高了代码的可维护性和可读性。这一层的设计让我意识到,良好的业务逻辑封装可以使得后续的功能扩展更加容易。
数据访问层:在UserDAO中,我学习了如何使用JDBC与数据库进行交互。通过封装数据库操作,我能够更好地管理数据访问逻辑,避免在控制层中直接处理SQL语句。这种分层设计使得代码更加模块化。
- 源码附录
4.1实验
DatabaseConnection.java
package com.example;
import java.sql.Connection;
import java.sql.DriverManager;
// 数据库连接类
public class DatabaseConnection {
// 获取数据库连接的方法
public static Connection getConnection() {
Connection con = null; // 初始化连接对象
try {
// 加载MySQL JDBC驱动
Class.forName("com.mysql.cj.jdbc.Driver");
// 连接到数据库
con = DriverManager.getConnection("jdbc:mysql://localhost:3306/user_system", "root", "123456");
} catch (Exception e) {
e.printStackTrace(); // 打印异常信息
}
return con; // 返回连接对象
}
}
package com.example;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/LoginServlet") // 映射URL到此Servlet
public class LoginServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 获取用户输入的用户名和密码
String username = request.getParameter("username");
String password = request.getParameter("password");
// 创建UserService实例以验证用户
UserService userService = new UserService();
boolean isValidUser = userService.validateUser(username, password);
// 根据验证结果重定向到相应的页面
if (isValidUser) {
response.sendRedirect("success.jsp"); // 验证成功,跳转到成功页面
} else {
response.sendRedirect("failure.jsp"); // 验证失败,跳转到失败页面
}
}
}
package com.example;
// 用户数据模型类
public class UserBean {
private String username; // 用户名
private String password; // 密码
// 获取用户名
public String getUsername() {
return username;
}
// 设置用户名
public void setUsername(String username) {
this.username = username;
}
// 获取密码
public String getPassword() {
return password;
}
// 设置密码
public void setPassword(String password) {
this.password = password;
}
}
package com.example;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
// 数据访问类,用于与数据库交互
public class UserDao {
// 验证用户凭据的方法
public boolean validate(String username, String password) {
boolean status = false; // 默认状态为无效用户
try {
// 获取数据库连接
Connection con = DatabaseConnection.getConnection(); // 假设您有一个DatabaseConnection类
// 准备SQL查询
PreparedStatement ps = con.prepareStatement("SELECT * FROM users WHERE username=? AND password=?");
ps.setString(1, username); // 设置用户名参数
ps.setString(2, password); // 设置密码参数
ResultSet rs = ps.executeQuery(); // 执行查询
status = rs.next(); // 如果找到记录,则用户有效
} catch (Exception e) {
e.printStackTrace(); // 打印异常信息
}
return status; // 返回用户验证状态
}
}
package com.example;
// 用户服务类,处理用户相关的业务逻辑
public class UserService {
private UserDao userDao = new UserDao(); // 创建UserDao实例
// 验证用户的方法
public boolean validateUser(String username, String password) {
return userDao.validate(username, password); // 调用UserDao的验证方法
}
}
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<title>Failure</title>
</head>
<body>
<h2>登录失败</h2>
<!-- 登录失败后的提示 -->
</body>
</html>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<title>Login</title>
</head>
<body>
<h2>登录</h2>
<!-- 表单提交到LoginServlet -->
<form action="LoginServlet" method="post">
用户名: <input type="text" name="username" required /><br />
密码: <input type="password" name="password" required /><br />
<input type="submit" value="登录" />
</form>
</body>
</html>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<title>Success</title>
</head>
<body>
<h2>登录成功</h2>
<!-- 登录成功后的提示 -->
</body>
</html>
4.2实验
editUser
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<servlet>
<servlet-name>UserServlet</servlet-name>
<servlet-class>com.example.controller.UserServlet</servlet-class> <!-- 确保包名正确 -->
</servlet>
<servlet-mapping>
<servlet-name>UserServlet</servlet-name>
<url-pattern>/user</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>LoginServlet</servlet-name>
<servlet-class>com.example.controller.LoginServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>LoginServlet</servlet-name>
<url-pattern>/login</url-pattern>
</servlet-mapping>
</web-app>
Index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>用户信息管理系统</title>
</head>
<body>
<h1>欢迎来到用户信息管理系统</h1>
<a href="login.jsp">登录</a> | <a href="register.jsp">注册</a>
</body>
</html>
Login.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>用户登录</title>
</head>
<body>
<h1>用户登录</h1>
<form action="login" method="post">
用户名: <input type="text" name="username" required><br>
密码: <input type="password" name="password" required><br>
<input type="submit" value="登录">
</form>
<%
String errorMessage = (String) request.getAttribute("errorMessage");
if (errorMessage != null) {
out.println("<p>" + errorMessage + "</p>");
}
%>
</body>
</html>
Register.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>注册</title>
</head>
<body>
<h1>用户注册</h1>
<form action="user" method="post">
<input type="hidden" name="action" value="register">
用户名: <input type="text" name="username" required><br>
密码: <input type="password" name="password" required><br>
年龄: <input type="number" name="age" required><br>
<input type="submit" value="注册">
</form>
</body>
</html>
userList.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page import="com.example.entity.User" %>
<%@ page import="com.example.service.UserService" %>
<%@ page import="java.util.List" %>
<%@ page import="java.sql.SQLException" %>
<html>
<head>
<title>用户列表</title>
<script>
function confirmDelete() {
return confirm("您确定要删除该用户吗?");
}
</script>
</head>
<body>
<h1>用户列表</h1>
<%
String deleteMessage = request.getParameter("message");
if (deleteMessage != null) {
%>
<p style="color: green;"><%= deleteMessage %></p>
<%
}
%>
<h2>通过 JavaBean 删除用户</h2>
<form action="user" method="post" οnsubmit="return confirmDelete();">
<input type="hidden" name="action" value="delete">
<label for="usernameToDelete">用户名:</label>
<input type="text" id="usernameToDelete" name="username" required>
<input type="submit" value="删除用户">
</form>
<table border="1">
<tr>
<th>用户名</th>
<th>年龄</th>
<th>操作</th>
</tr>
<%
UserService userService = new UserService();
try {
List<User> users = userService.getAllUsers();
for (User user : users) {
%>
<tr>
<td><%= user.getUsername() %></td>
<td><%= user.getAge() %></td>
<td>
<form action="user" method="post" style="display:inline;">
<input type="hidden" name="action" value="edit">
<input type="hidden" name="username" value="<%= user.getUsername() %>">
<input type="submit" value="编辑">
</form>
</td>
</tr>
<%
}
} catch (SQLException e) {
e.printStackTrace();
out.println("<tr><td colspan='3'>无法获取用户列表: " + e.getMessage() + "</td></tr>");
}
%>
</table>
<a href="login.jsp">注销</a>
</body>
</html>
package com.example.controller;
import javax.servlet.ServletException;
import javax.servlet.http.*;
import com.example.service.UserService;
import java.io.IOException;
import java.sql.SQLException;
public class LoginServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
private UserService userService = new UserService();
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String username = request.getParameter("username");
String password = request.getParameter("password");
try {
if (userService.validateUser(username, password)) {
request.getSession().setAttribute("user", username);
response.sendRedirect("userList.jsp");
} else {
request.setAttribute("errorMessage", "用户名或密码错误");
request.getRequestDispatcher("login.jsp").forward(request, response);
}
} catch (SQLException e) {
e.printStackTrace();
response.sendRedirect("login.jsp?message=登录失败: " + e.getMessage());
}
}
}
//控制层(Controller Layer):负责接收用户请求并调用相应的服务层逻辑。在你的项目中,UserServlet类就是控制层的实现,它处理用户的请求,如注册、删除和更新用户信息。
package com.example.controller;
import java.io.IOException;
import java.sql.SQLException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.net.URLEncoder;
import com.example.entity.User;
import com.example.service.UserService;
public class UserServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
private UserService userService = new UserService();
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String action = request.getParameter("action");
String username = request.getParameter("username");
try {
if ("register".equals(action)) {
String password = request.getParameter("password");
int age = Integer.parseInt(request.getParameter("age"));
User user = new User(username, password, age);
userService.registerUser(user);//调用userService中的registerUser方法
response.sendRedirect("login.jsp");
} else if ("delete".equals(action)) {
userService.deleteUser(username);
response.sendRedirect("userList.jsp?message=" + URLEncoder.encode("用户 " + username + " 已成功删除。", "UTF-8"));
} else if ("edit".equals(action)) {
User user = userService.getUser(username);
request.setAttribute("user", user);
request.getRequestDispatcher("editUser.jsp").forward(request, response);
} else if ("save".equals(action)) {
String password = request.getParameter("password");
int age = Integer.parseInt(request.getParameter("age"));
User user = new User(username, password, age);
userService.updateUser(user);
response.sendRedirect("userList.jsp?message=用户 " + username + " 信息已成功保存。");
}
} catch (SQLException e) {
e.printStackTrace();
response.sendRedirect("userList.jsp?message=操作失败: " + e.getMessage());
}
}
}
package com.example.dao;
// UserDAO.java
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
import com.example.entity.User;
public class UserDAO {
private String jdbcURL = "jdbc:mysql://localhost:3306/user_management";
private String jdbcUsername = "root";
private String jdbcPassword = "123456";
public void registerUser(User user) throws SQLException {
String sql = "INSERT INTO users (username, password, age) VALUES (?, ?, ?)";
try (Connection connection = DriverManager.getConnection(jdbcURL, jdbcUsername, jdbcPassword);
PreparedStatement ps = connection.prepareStatement(sql)) {
ps.setString(1, user.getUsername());
ps.setString(2, user.getPassword());
ps.setInt(3, user.getAge());
ps.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
throw e; // 重新抛出异常以便上层处理
}
}
public List<User> getAllUsers() throws SQLException {
List<User> users = new ArrayList<>();
try (Connection connection = DriverManager.getConnection(jdbcURL, jdbcUsername, jdbcPassword);
Statement stmt = connection.createStatement();
ResultSet rs = stmt.executeQuery("SELECT * FROM users")) {
while (rs.next()) {
String username = rs.getString("username");
String password = rs.getString("password");
int age = rs.getInt("age");
users.add(new User(username, password, age));
}
} catch (SQLException e) {
e.printStackTrace();
throw e; // 重新抛出异常以便上层处理
}
return users;
}
public void deleteUser(String username) throws SQLException {
// 使用 try-with-resources 确保连接和语句被正确关闭
try (Connection connection = DriverManager.getConnection(jdbcURL, jdbcUsername, jdbcPassword);
PreparedStatement statement = connection.prepareStatement("DELETE FROM users WHERE username=?")) {
statement.setString(1, username);
statement.executeUpdate();
} catch (SQLException e) {
// 记录异常信息
e.printStackTrace();
throw e; // 重新抛出异常以便上层处理
}
}
public User getUser(String username) throws SQLException {
User user = null;
try (Connection connection = DriverManager.getConnection(jdbcURL, jdbcUsername, jdbcPassword);
PreparedStatement ps = connection.prepareStatement("SELECT * FROM users WHERE username=?")) {
ps.setString(1, username);
ResultSet rs = ps.executeQuery();
if (rs.next()) {
String password = rs.getString("password");
int age = rs.getInt("age");
user = new User(username, password, age);
}
} catch (SQLException e) {
e.printStackTrace();
throw e; // 重新抛出异常以便上层处理
}
return user;
}
public void updateUser(User user) throws SQLException {
try (Connection connection = DriverManager.getConnection(jdbcURL, jdbcUsername, jdbcPassword);
PreparedStatement ps = connection.prepareStatement("UPDATE users SET password=?, age=? WHERE username=?")) {
ps.setString(1, user.getPassword());
ps.setInt(2, user.getAge());
ps.setString(3, user.getUsername());
ps.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
throw e; // 重新抛出异常以便上层处理
}
}
public boolean validateUser(String username, String password) throws SQLException {
try (Connection connection = DriverManager.getConnection(jdbcURL, jdbcUsername, jdbcPassword);
PreparedStatement ps = connection.prepareStatement("SELECT * FROM users WHERE username=? AND password=?")) {
ps.setString(1, username);
ps.setString(2, password);
ResultSet rs = ps.executeQuery();
return rs.next();
} catch (SQLException e) {
e.printStackTrace();
throw e; // 重新抛出异常以便上层处理
}
}
}
//数据访问层: 负责与数据库进行交互,执行SQL查询和更新操作。UserDAO类则实现了这一层的功能,通过JDBC与数据库进行交互。
package com.example.entity;
public class User {
private String username;
private String password;
private int age;
public User(String username, String password, int age) {
this.username = username;
this.password = password;
this.age = age;
}
// Getters and Setters
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
package com.example.service;
import com.example.dao.UserDAO;
import com.example.entity.User;
import java.sql.SQLException;
import java.util.List;
public class UserService {
private UserDAO userDAO = new UserDAO();
public void registerUser(User user) throws SQLException {
userDAO.registerUser(user); // 调用 UserDAO 的 registerUser 方法
}
public List<User> getAllUsers() throws SQLException {
return userDAO.getAllUsers();
}
public void deleteUser(String username) throws SQLException {
try {
userDAO.deleteUser(username);
} catch (Exception e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
public User getUser(String username) throws SQLException {
try {
return userDAO.getUser(username);
} catch (Exception e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
return null;
}
public void updateUser(User user) throws SQLException {
try {
userDAO.updateUser(user);
} catch (Exception e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
public boolean validateUser(String username, String password) throws SQLException {
return userDAO.validateUser(username, password);
}
}
//服务层:负责业务逻辑的处理。你的UserService类实现了用户相关的业务逻辑,例如注册、删除和验证用户。