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 {
        @Override
        public String encrypt(String message) {
            return null;
        }

        @Override
        public 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;
    }

    @Override
    public 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: CaptainDong
  Date: 2023/4/9
  Time: 11:59
  To 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: CaptainDong
  Date: 2023/4/9
  Time: 11:59
  To 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: CaptainDong
  Date: 2023/4/9
  Time: 11:59
  To 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 代码,大幅提高了代码的可读性和可维护性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

captain_dong

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值