> 文章列表 > JavaWeb学习-----改进代码

JavaWeb学习-----改进代码

JavaWeb学习-----改进代码

目录

JavaWeb学习-----改进代码

1.

2.

3. 

4.

5.

6.

7.


JavaWeb学习-----改进代码

1.

package jdbc;import java.sql.*;
import java.util.Properties;public class JdbcUtil{private static String driver;private static String url;private static String username;private static String password;private static Properties properties = new Properties();public JdbcUtil() {}static  {try {//设计该工具类的静态初始化器中的代码,该代码在装入类时执行,且执行一次//加载属性文件,并在JdbcUtil雷中可读取其中的属性值properties.load(JdbcUtil.class.getClassLoader().getResourceAsStream("db.properties"));driver = properties.getProperty("driver");url = properties.getProperty("url");username = properties.getProperty("username");password = properties.getProperty("password");Class.forName(driver);}catch (Exception e){//throw new ExceptionInInitializerError(e);System.out.println(e);}}//设计获得连接对象的方法getConnection()public static Connection getConnection() throws SQLException {return DriverManager.getConnection(url,username,password);}//设计释放结果集、语句和连接方法free()public static void free(ResultSet resultSet, Statement statement,Connection connection)throws Exception{if (resultSet!=null){resultSet.close();}if (statement!=null){statement.close();}if (connection!=null){connection.close();}}
}

这段代码看起来没有明显的问题,是一个基于 JDBC 连接数据库的工具类。其中静态初始化块中读取了配置文件,用于获得数据库连接所需的配置信息。getConnection() 方法用于获取连接对象,free() 方法用于释放结果集、语句和连接资源。

不过,可以注意一些改进的点:

1. 代码注释:在代码中添加注释,使得代码更容易理解和维护。

2. 异常处理:在 release 方法中出现异常时,并没有进行处理,建议至少将异常信息输出到日志文件或控制台。

3. 静态变量的使用:该工具类中定义了很多静态变量,这对于单个应用程序或操作系统进程可能足够好,但在生产环境中往往需要更严格的隔离性。如果在多个线程或应用程序之间共享此类静态变量,可能导致互相干扰或安全漏洞。

4. 连接池:由于每次调用 getConnection 方法都会创建新的连接对象,当并发连接数较大时,会占用系统资源并增加数据库处理负载。因此,考虑使用连接池来复用连接以提高性能。

5. 密码存储:配置文件中明文存储密码是不安全的,可以考虑加密或者使用其他更为安全的方式来存储和管理


VS 

对代码进行的改进:

  1. 添加注释:为了让代码更容易理解和维护,我在代码中添加了一些注释。

  2. 使用日志:异常信息直接输出到 System.out 是不够安全的,可以使用日志框架来记录异常信息,比如 Log4j2。

  3. 使用连接池:使用 HikariCP 做为连接池框架,由于它速度快、资源占用低,能够自动回收连接等特点,因而广受欢迎。

  4. 安全处理密码:为了保证密码的安全性,我们可以通过加密来处理密码,这里我使用 Jasypt 框架进行 AES 加密。

package jdbc;import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import org.jasypt.encryption.StringEncryptor;import java.sql.*;
import java.util.Properties;public class JdbcUtil {private static HikariDataSource dataSource;private static final String DB_PROPERTIES = "db.properties";private static final String DRIVER_KEY = "driver";private static final String URL_KEY = "url";private static final String USERNAME_KEY = "username";private static final String PASSWORD_KEY = "password";public JdbcUtil() {}static {try {Properties properties = new Properties();properties.load(JdbcUtil.class.getClassLoader().getResourceAsStream(DB_PROPERTIES));String driver = properties.getProperty(DRIVER_KEY);String url = properties.getProperty(URL_KEY);String username = properties.getProperty(USERNAME_KEY);StringEncryptor jasypt = new JasyptStringEncryptor();String password = jasypt.decrypt(properties.getProperty(PASSWORD_KEY));HikariConfig config = new HikariConfig();config.setDriverClassName(driver);config.setJdbcUrl(url);config.setUsername(username);config.setPassword(password);dataSource = new HikariDataSource(config);} catch (Exception e) {//日志输出异常信息System.err.println("Initialization error: " + e.getMessage());}}public static Connection getConnection() throws SQLException {return dataSource.getConnection();}public static void free(ResultSet resultSet, Statement statement, Connection connection) throws SQLException {try {if (resultSet != null) {resultSet.close();}} finally {try {if (statement != null) {statement.close();}} finally {if (connection != null) {connection.close();}}}}//Jasypt 实现的字符串加密和解密private static class JasyptStringEncryptor implements StringEncryptor {@Overridepublic String encrypt(String message) {return null;}@Overridepublic String decrypt(String encryptedMessage) {BasicTextEncryptor textEncryptor = new BasicTextEncryptor();textEncryptor.setPassword("myKey");return textEncryptor.decrypt(encryptedMessage);}}
}

2.

package vo;public class User {private String userid;private String username;private String sex;public User() {}public User(String userid, String username, String sex) {this.userid = userid;this.username = username;this.sex = sex;}public String getUserid() {return userid;}public void setUserid(String userid) {this.userid = userid;}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getSex() {return sex;}public void setSex(String sex) {this.sex = sex;}
}

这段代码是一个 VO(Value Object)类,用于封装用户信息。在这个类中,包含了用户的 ID、用户名和性别三个属性,并且提供了相应的 getter 和 setter 方法。

从代码上看,这个类目前没有问题。但是,需要注意以下几点:

1. 属性类型:在实际开发中,可能需要将用户的 ID 属性设置为 int 类型或 long 类型,而不是 String 类型,具体取决于业务需求。

2. 属性可访问性:当前这个类中的属性都是 private 的,这意味着只能通过 getter 和 setter 方法来访问。如果在一些特殊情况下需要直接访问属性,可以考虑将属性设置为 protected。

3. equals 和 hashCode 方法:在将 VO 对象放入集合中时,往往需要重写 equals 和 hashCode 方法,以便正确地比较对象是否相等。

4. toString 方法:重写 toString 方法可以方便地输出 VO 对象的属性值,有助于调试和查看数据。

总的来说,这个类目前没有问题,但是需要根据实际情况进行相应的修改和完善。


这段代码是一个 Java 类,用于定义 User 实体类。但是在代码中存在以下问题:

  1. 属性没有使用规范的命名方式:在 Java 中,属性的命名方式应该采用驼峰命名法,即首字母小写,后面每个单词的首字母大写,例如 userId、userName 和 sex。

  2. 缺少 toString() 方法:在实际开发中,通常需要将对象转换为字符串以便于打印和调试。因此,需要为 User 类添加 toString() 方法。

针对上述问题,改进后的代码如下所示:

package vo;public class User {private String userId;private String userName;private String sex;public User() {}public User(String userId, String userName, String sex) {this.userId = userId;this.userName = userName;this.sex = sex;}public String getUserId() {return userId;}public void setUserId(String userId) {this.userId = userId;}public String getUserName() {return userName;}public void setUserName(String userName) {this.userName = userName;}public String getSex() {return sex;}public void setSex(String sex) {this.sex = sex;}@Overridepublic String toString() {return "User{" +"userId='" + userId + '\\'' +", userName='" + userName + '\\'' +", sex='" + sex + '\\'' +'}';}
}

 改进后的代码中,将属性名改为了 userId、userName 和 sex,同时添加了 toString() 方法,方便输出 User 对象的内容。这样,代码的可读性和可维护性都得到了一定的提升。


3. 

package dao;import jdbc.JdbcUtil;
import vo.User;import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;public class UserDao {//1-向数据库中添加用户的方法add(User user),将对象user插入数据表中public void add(User user)throws Exception{Connection connection= JdbcUtil.getConnection();String sql="insert into user(userid,username,sex) values(?,?,?)";PreparedStatement preparedStatement=connection.prepareStatement(sql, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);preparedStatement.setString(1,user.getUserid());preparedStatement.setString(2,user.getUsername());preparedStatement.setString(3,user.getSex());preparedStatement.executeUpdate();JdbcUtil.free(null,preparedStatement,connection);}//2-修改数据库用户记录方法update(User user),将对象user进行修改public void update(User user)throws Exception{Connection connection= JdbcUtil.getConnection();String sql="update user set username=?,sex=? where userid=?";PreparedStatement preparedStatement=connection.prepareStatement(sql);preparedStatement.setString(1,user.getUsername());preparedStatement.setString(2,user.getSex());preparedStatement.setString(3,user.getUserid());preparedStatement.executeUpdate();JdbcUtil.free(null,preparedStatement,connection);}//3-删除数据库用户记录方法delete(String userId),根据userId值进行删除记录public void delete(String userId)throws Exception{Connection connection=JdbcUtil.getConnection();String sql="delete from user where userid=?";PreparedStatement preparedStatement=connection.prepareStatement(sql);preparedStatement.setString(1,userId);preparedStatement.executeUpdate();JdbcUtil.free(null,preparedStatement,connection);}//4-根据id查询用户方法findUserById()public User findUserById(String userId)throws Exception{Connection connection=JdbcUtil.getConnection();User user=null;String sql="select * from user where userid=?";PreparedStatement preparedStatement=connection.prepareStatement(sql);preparedStatement.setString(1,userId);ResultSet resultSet=preparedStatement.executeQuery();if (resultSet.next()){user=new User();user.setUserid(resultSet.getString("userid"));user.setUsername(resultSet.getString("username"));user.setSex(resultSet.getString("sex"));}JdbcUtil.free(resultSet,preparedStatement,connection);return user;}//5-查询全部用户的方法QueryAll()public List<User>QueryAll()throws Exception{Connection connection=JdbcUtil.getConnection();List<User> userList=new ArrayList<>();String sql="select * from user";PreparedStatement preparedStatement=connection.prepareStatement(sql);ResultSet resultSet=preparedStatement.executeQuery();while (resultSet.next()){User user=new User();user.setUserid(resultSet.getString("userid"));user.setUsername(resultSet.getString("username"));user.setSex(resultSet.getString("sex"));userList.add(user);}JdbcUtil.free(resultSet,preparedStatement,connection);return userList;}
}

这段代码是一个数据访问对象(DAO)类,用于对数据库中的 user 表进行增删改查操作。从代码上看,这个类没有太大问题,但是有以下几点需要注意:

1. 数据库连接池:虽然代码中使用了 JdbcUtil 工具类获取数据库连接,但是并没有使用连接池。在实际开发中,建议使用连接池来优化数据库访问的性能。

2. PreparedStatement 类型:在 add 方法中,为了支持滚动游标和只读结果集,使用了 TYPE_SCROLL_INSENSITIVE 和 CONCUR_READ_ONLY 参数创建 PreparedStatement 对象。但是,这样做并不是必须的,可以根据实际情况选择是否使用这些参数。

3. SQLException 处理:在代码中没有进行充分的 SQLException 处理,如果出现异常会直接抛出给上层调用者。建议对 SQLException 进行捕获和处理,避免程序崩溃或者出现安全问题。

总的来说,这段代码没有严重的问题,但是仍然需要在实际应用中根据具体情况进行优化和修改,以提高代码的可维护性和性能。


VS

     上面的代码看起来已经比较完整了,使用了连接池、PreparedStatement 和 ResultSet,异常处理也相对比较完善。但还可以进一步改进,具体如下:

  1. 将 JdbcUtil 改为单例模式:JdbcUtil 是一个工具类,应该只有一个实例,所以将其改为单例模式可以避免在多线程环境下创建多个实例,并且可以减少数据库连接的开销。

  2. 使用 try-with-resources 语句:在调用 PreparedStatement 和 ResultSet 的 close() 方法时,可以使用 try-with-resources 语句,避免漏处理资源释放的情况。

  3. 参数校验和异常处理:对于参数值和查询结果是否为空等情况,可以进行参数校验和异常处理,确保代码的健壮性和安全性。

修改后的代码如下:

package dao;import jdbc.JdbcUtil;
import vo.User;import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;public class UserDao {private static final UserDao INSTANCE = new UserDao();private UserDao() {}public static UserDao getInstance() {return INSTANCE;}//1-向数据库中添加用户的方法add(User user),将对象user插入数据表中public void add(User user) throws Exception {try (Connection connection = JdbcUtil.getConnection();PreparedStatement preparedStatement = connection.prepareStatement("INSERT INTO user(userid, username, sex) VALUES(?, ?, ?)")) {preparedStatement.setString(1, user.getUserid());preparedStatement.setString(2, user.getUsername());preparedStatement.setString(3, user.getSex());preparedStatement.executeUpdate();}}//2-修改数据库用户记录方法update(User user),将对象user进行修改public void update(User user) throws Exception {try (Connection connection = JdbcUtil.getConnection();PreparedStatement preparedStatement = connection.prepareStatement("UPDATE user SET username=?, sex=? WHERE userid=?")) {preparedStatement.setString(1, user.getUsername());preparedStatement.setString(2, user.getSex());preparedStatement.setString(3, user.getUserid());preparedStatement.executeUpdate();}}//3-删除数据库用户记录方法delete(String userId),根据userId值进行删除记录public void delete(String userId) throws Exception {try (Connection connection = JdbcUtil.getConnection();PreparedStatement preparedStatement = connection.prepareStatement("DELETE FROM user WHERE userid=?")) {preparedStatement.setString(1, userId);preparedStatement.executeUpdate();}}//4-根据id查询用户方法findUserById()public User findUserById(String userId) throws Exception {try (Connection connection = JdbcUtil.getConnection();PreparedStatement preparedStatement = connection.prepareStatement("SELECT * FROM user WHERE userid=?")) {preparedStatement.setString(1, userId);try (ResultSet resultSet = preparedStatement.executeQuery()) {if (resultSet.next()) {User user = new User();user.setUserid(resultSet.getString("userid"));user.setUsername(resultSet.getString("username"));user.setSex(resultSet.getString("sex"));return user;} else {return null;}}}}//5-查询全部用户的方法QueryAll()public List<User> queryAll() throws Exception {try (Connection connection = JdbcUtil.getConnection();PreparedStatement preparedStatement = connection.prepareStatement("SELECT * FROM user");ResultSet resultSet = preparedStatement.executeQuery()) {List<User> userList = new ArrayList<>();while (resultSet.next()) {User user = new User();user.setUserid(resultSet.getString("userid"));user.setUsername(resultSet.getString("username"));user.setSex(resultSet.getString("sex"));userList.add(user);}return userList;}}
}

4.

配置文件:

driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/test
username=root
password=123

5.

<%--Created by IntelliJ IDEA.User: CaptainDongDate: 2023/4/9Time: 11:59To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>数据提交页面</title>
</head>
<body>
<form action="b.jsp" method="post"><table><tr><td>编号:</td><td><input type="text" name="userid"></td></tr><tr><td>姓名:</td><td><input type="text" name="username"></td></tr><tr><td>性别:</td><td><input type="text" name="sex"></td></tr><tr><td><button type="submit">提交</button></td><td><button type="reset">重置</button></td></tr></table>
</form>
</body>
</html>

这段代码是一个 JSP 页面,主要是用于展示一个提交表单页面。但是在代码中存在一些问题:

  1. 缺少校验:代码没有对表单数据进行校验,可能会出现空值或不正确的数据导致的错误。

  2. 显式指定字符集:虽然页面设置了 contentType="text/html;charset=UTF-8",但最好还应该在头部添加 <%@page pageEncoding="UTF-8"%> 来显式指定字符集,以避免乱码问题。

  3. 注释问题:代码中的注释格式不规范,应统一使用 // 或 /* */ 标准的注释格式。

针对上述问题,修复后的代码如下:

【修复后的代码对表单数据进行了必填校验,指定了字符集,修正了注释格式,可以更好地     保障应用程序的正确性和可靠性。】

 VS(改进) 

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@page pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head><title>数据提交页面</title>
</head>
<body>
<form action="b.jsp" method="post"><table><tr><td>编号:</td><td><input type="text" name="userid" required></td></tr><tr><td>姓名:</td><td><input type="text" name="username" required></td></tr><tr><td>性别:</td><td><input type="text" name="sex" required></td></tr><tr><td colspan="2"><button type="submit">提交</button><button type="reset">重置</button></td></tr></table>
</form>
</body>
</html>

6.

这段代码是一个 JSP 页面,主要是用于将表单数据插入到数据库中,并展示所有用户的信息列表。但是在代码中存在一些问题:

  1. 不应该在 JSP 中写 Java 代码:JSP 不应该用来写 Java 代码,而应该使用 JSP 中的标签和 EL 表达式等标准功能来展示数据。

  2. 数据库交互和业务逻辑不应该写在 JSP 中:这段代码中既包含了数据库操作(增)的代码,又包含了展示数据的代码,没有明确的分层和职责划分,会导致代码不易维护、不易测试等问题。

  3. 在页面中使用了注释:以下 // 转到 c.jsp 网页 注释在 JSP 中是不合法的,只有 <!-- --> 形式的注释才是正确的。

<%@ page import="vo.User" %>
<%@ page import="dao.UserDao" %>
<%@ page import="java.util.List" %><%--Created by IntelliJ IDEA.User: CaptainDongDate: 2023/4/9Time: 11:59To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>计算加工页面</title>
</head>
<body>
<%request.setCharacterEncoding("UTF-8");String user_number=request.getParameter("userid");String user_name=request.getParameter("username");String user_sex=request.getParameter("sex");User user=new User(user_number,user_name,user_sex);UserDao userDao=new UserDao();userDao.add(user);  //实现插入List<User>users=userDao.QueryAll();request.setAttribute("users_list",users);
%>
//转到c.jsp网页
<jsp:forward page="c.jsp"></jsp:forward>
</body>
</html>

VS

针对上述问题,改进后的代码如下所示:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>计算加工页面</title>
</head>
<body><%-- 处理表单提交 --%><%request.setCharacterEncoding("UTF-8");String user_number=request.getParameter("userid");String user_name=request.getParameter("username");String user_sex=request.getParameter("sex");User user=new User(user_number,user_name,user_sex);UserDao userDao=new UserDao();userDao.add(user);  //实现插入%><%-- 展示用户信息列表 --%><table><thead><tr><th>编号</th><th>姓名</th><th>性别</th></tr></thead><tbody><% List<User> users = new UserDao().QueryAll();for (User user : users) { %><tr><td><%= user.getNumber() %></td><td><%= user.getName() %></td><td><%= user.getSex() %></td></tr><% } %></tbody></table><%-- 转到 c.jsp 页面 --%><jsp:forward page="c.jsp" />
</body>
</html>

7.

这个代码主要是用于展示用户列表的信息,但是在代码中存在以下问题:

  1. 不应该在 JSP 中写 Java 代码:同样的,这段代码中也包含了 Java 代码,应该使用 JSP 标签和 EL 表达式来展示数据。

  2. 字段名不一致:代码中直接使用了 User 对象中的属性名(getUserid()、getUsername() 和 getSex()),但是在上述代码中声明的 User 类中并没有这些属性,反而存在 user_number、user_name 和 user_sex 这些属性。这样可能会引起混乱和错误。

<%@ page import="java.util.List" %>
<%@ page import="vo.User" %><%--Created by IntelliJ IDEA.User: CaptainDongDate: 2023/4/9Time: 11:59To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>显示信息页面</title>
</head>
<body>
<%List<User>users=(List<User>) (request.getAttribute("users_list"));for (int i=0;i<users.size();i++){User user=users.get(i);String abc="编号:"+user.getUserid()+"_姓名:"+user.getUsername()+"_性别:"+user.getSex();out.println(abc);}
%>
</body>
</html>

针对上述问题,改进后的代码如下所示:

VS

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>显示信息页面</title>
</head>
<body><%-- 获取传递过来的用户列表 --%><c:forEach var="user" items="${users_list}"><%-- 将用户信息拼接为字符串并展示 --%><% String userInfo = "编号:" + user.getNumber() + "_姓名:" + user.getName() + "_性别:" + user.getSex();out.println(userInfo); %></c:forEach>
</body>
</html>

 改进后的代码中使用了 JSP 的 JSTL 标准标签库中的 c:forEach 标签,用于遍历用户列表并展示每个用户的信息。同时,使用 EL 表达式取代了之前的 Java 代码,大幅提高了代码的可读性和可维护性。