JAVAWeb常用工具类

目录

JDBCUtil(数据库连接池管理)

主要功能解释

静态代码块

类方法

getDataSource()

getConnection()

releaseConnection()

代码示例

使用示例

JwtHelper(Token管理)

静态成员变量(tokenExpiration 和 tokenSignKey)

类方法

createToken(Long userId)

getUserId(String token)

isExpiration(String token)

代码示例

使用示例

MD5Util(MD5加密)

类方法

encrypt(String strSrc)

使用示例

代码示例

WebUtil(处理Web请求与响应)

静态成员变量及静态代码块

类方法

readJson(HttpServletRequest request, Class clazz)

writeJson(HttpServletResponse response, Result result)

使用示例

代码示例


JDBCUtil(数据库连接池管理)

        主要用于管理数据库连接。使用了 Druid 数据源ThreadLocal 来确保多线程环境下数据库连接的安全性与高效性,减少频繁创建与销毁数据库连接的开销。该类提供了获取连接池、获取数据库连接以及释放连接的方法。

主要功能解释

1. ThreadLocal<Connection> threadLocal

  • 使用 ThreadLocal 来存储每个线程的数据库连接。这保证了每个线程都有自己独立的数据库连接,避免了线程间的连接共享问题。

2. DataSource dataSource

  • DataSource 用于管理数据库连接池,允许获取和释放数据库连接。这里使用的是 Druid 数据源,它是一种高效、稳定的数据库连接池管理工具。

静态代码块

Properties properties = new Properties();
InputStream resourceAsStream = JDBCUtil.class.getClassLoader().getResourceAsStream("jdbc.properties");
properties.load(resourceAsStream);
dataSource = DruidDataSourceFactory.createDataSource(properties);

在类加载时进行,用于初始化数据库连接池(dataSource)。首先通过 Properties 类加载 jdbc.properties 文件中的配置,然后通过 DruidDataSourceFactory 创建连接池。

类方法

getDataSource()
public static DataSource getDataSource() {
    return dataSource;
}

用于向外界提供 DataSource 对象,使得其他类能够直接访问连接池,获取数据库连接。

getConnection()
public static Connection getConnection() {
    Connection connection = threadLocal.get();
    if (null == connection) {
        try {
            connection = dataSource.getConnection();
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
        threadLocal.set(connection);
    }
    return connection;
}

该方法用于获取数据库连接:

  • 先从 ThreadLocal 获取当前线程是否已有连接(如果有,则直接返回)。
  • 如果当前线程没有连接,则从连接池中获取新的连接,并将其存储到 ThreadLocal 中,确保该线程后续操作会使用相同的连接。
releaseConnection()
public static void releaseConnection() {
    Connection connection = threadLocal.get();
    if (null != connection) {
        threadLocal.remove();
        try {
            connection.setAutoCommit(true);
            connection.close();
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }
}

该方法用于释放数据库连接:

  • 先从 ThreadLocal 中获取当前线程的连接。
  • 如果连接存在,解除连接与 ThreadLocal 的关联(调用 threadLocal.remove()),并将连接的自动提交模式恢复为 true
  • 最后,调用 connection.close() 将连接归还到连接池中,而不是直接关闭它,从而可以重复使用该连接。

代码示例

import com.alibaba.druid.pool.DruidDataSourceFactory;

import javax.sql.DataSource;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;
public class JDBCUtil {
    private static ThreadLocal<Connection> threadLocal =new ThreadLocal<>();

    private static DataSource dataSource;
    // 初始化连接池
    static{
        // 可以帮助我们读取.properties配置文件
        Properties properties =new Properties();
        InputStream resourceAsStream = JDBCUtil.class.getClassLoader().getResourceAsStream("jdbc.properties");
        try {
            properties.load(resourceAsStream);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        try {
            dataSource = DruidDataSourceFactory.createDataSource(properties);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }


    }
    /*1 向外提供连接池的方法*/
    public static DataSource getDataSource(){
        return dataSource;
    }

    /*2 向外提供连接的方法*/
    public static Connection getConnection(){
        Connection connection = threadLocal.get();
        if (null == connection) {
            try {
                connection = dataSource.getConnection();
            } catch (SQLException e) {
                throw new RuntimeException(e);
            }
            threadLocal.set(connection);
        }

        return connection;
    }


    /*定义一个归还连接的方法 (解除和ThreadLocal之间的关联关系) */
    public static void releaseConnection(){
        Connection connection = threadLocal.get();
        if (null != connection) {
            threadLocal.remove();
            // 把连接设置回自动提交的连接
            try {
                connection.setAutoCommit(true);
                // 自动归还到连接池
                connection.close();
            } catch (SQLException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

使用示例

要先配置jdbc.properties

jdbc.url=jdbc:mysql://localhost:3306/mydb
jdbc.username=root
jdbc.password=root
jdbc.driverClassName=com.mysql.cj.jdbc.Driver
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

//查询用户信息
public class JdbcExample {
    public static void main(String[] args) {
        Connection conn = null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;

        try {
            // 获取数据库连接
            conn = JDBCUtil.getConnection();

            // SQL查询语句
            String sql = "SELECT id, name, email FROM users";

            // 创建PreparedStatement对象
            pstmt = conn.prepareStatement(sql);

            // 执行查询并获取结果集
            rs = pstmt.executeQuery();

            // 遍历结果集并打印用户信息
            while (rs.next()) {
                int id = rs.getInt("id");
                String name = rs.getString("name");
                String email = rs.getString("email");

                System.out.println("ID: " + id + ", Name: " + name + ", Email: " + email);
            }

        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            // 释放连接资源
            JDBCUtil.releaseConnection();
        }
    }
}

//新增数据
public class JdbcInsertExample {
    public static void main(String[] args) {
        Connection conn = null;
        PreparedStatement pstmt = null;

        try {
            // 获取数据库连接
            conn = JDBCUtil.getConnection();

            // SQL插入语句
            String sql = "INSERT INTO users (name, email) VALUES (?, ?)";

            // 创建PreparedStatement对象
            pstmt = conn.prepareStatement(sql);
            
            // 设置参数值
            pstmt.setString(1, "Alice");
            pstmt.setString(2, "alice@example.com");

            // 执行插入操作
            int rowsAffected = pstmt.executeUpdate();
            System.out.println("插入了 " + rowsAffected + " 行数据");

        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            // 释放连接资源
            JDBCUtil.releaseConnection();
        }
    }
}

JwtHelper(Token管理)

        这个类是一个用于生成、解析和验证 JSON Web Token (JWT) 的工具类,通常用于用户身份验证或授权。在这个类中,JWT 用于将用户的 userId 编码到一个安全的令牌中,令牌在一定的时间段内有效。

静态成员变量(tokenExpirationtokenSignKey

private static long tokenExpiration = 24*60*60*1000;
private static String tokenSignKey = "123456";

tokenExpiration:令牌的有效期(以毫秒为单位,如24 * 60 * 60 * 1000为24小时)。

tokenSignKey:用于签名和验证 JWT 的密钥,确保生成的令牌在传输过程中没有被篡改。这个密钥应设置为复杂的字符串来提高安全性。

类方法

createToken(Long userId)
public static String createToken(Long userId) {
    String token = Jwts.builder()
            .setSubject("YYGH-USER")
            .setExpiration(new Date(System.currentTimeMillis() + tokenExpiration))
            .claim("userId", userId)
            .signWith(SignatureAlgorithm.HS512, tokenSignKey)
            .compressWith(CompressionCodecs.GZIP)
            .compact();
    return token;
}

功能:生成一个 JWT 令牌。

  • Jwts.builder():创建一个 JWT 构造器,构建令牌。
  • setSubject("YYGH-USER"):设置令牌的主题(这里是 "YYGH-USER",可以表示用户身份或应用标识)。
  • setExpiration(...):设置令牌的过期时间,这里是当前时间加上 tokenExpiration(24小时)。
  • claim("userId", userId):在令牌中加入自定义声明,这里是用户的 userId,可以通过解析该令牌获取用户身份。
  • signWith(SignatureAlgorithm.HS512, tokenSignKey):使用 HS512 算法和密钥 tokenSignKey 对令牌进行签名,以保证令牌的安全性。
  • compressWith(CompressionCodecs.GZIP):对生成的令牌使用 GZIP 压缩,减少令牌的长度。
  • compact():生成最终的令牌字符串。

返回值:生成的 JWT 令牌是一个字符串,客户端可以使用该令牌在后续请求中进行身份验证。

getUserId(String token)
public static Long getUserId(String token) {
    if(StringUtils.isEmpty(token)) return null;
    Jws<Claims> claimsJws = Jwts.parser().setSigningKey(tokenSignKey).parseClaimsJws(token);
    Claims claims = claimsJws.getBody();
    Integer userId = (Integer)claims.get("userId");
    return userId.longValue();
}

功能:从 JWT 令牌中解析出用户的 userId

  • Jwts.parser().setSigningKey(tokenSignKey):创建一个解析器,并使用签名密钥 tokenSignKey 来验证令牌的签名。
  • parseClaimsJws(token):解析传入的令牌,获取其中的声明(Claims),包括自定义的 userId
  • claims.get("userId"):从声明中获取 userId,并将其转换为 Long 类型返回。

返回值:用户的 userId,如果令牌无效或者为空,则返回 null

isExpiration(String token)
public static boolean isExpiration(String token){
    try {
        boolean isExpire = Jwts.parser()
                .setSigningKey(tokenSignKey)
                .parseClaimsJws(token)
                .getBody()
                .getExpiration().before(new Date());
        return isExpire;
    }catch(Exception e) {
        return true;
    }
}

功能:判断 JWT 令牌是否过期。

  • getExpiration().before(new Date()):从令牌中获取到过期时间,并与当前时间进行比较。如果过期时间在当前时间之前,则表示令牌已过期。
  • 如果令牌已过期,或者在解析过程中抛出了异常(例如令牌格式错误或签名无效),则返回 true,表示令牌已失效。

返回值true 表示令牌无效或已过期,false 表示令牌有效。

代码示例

import com.alibaba.druid.util.StringUtils;
import io.jsonwebtoken.*;

import java.util.Date;

public class JwtHelper {
    private static long tokenExpiration = 24*60*60*1000;
    private static String tokenSignKey = "123456";

    //生成token字符串
    public static String createToken(Long userId) {
        String token = Jwts.builder()

                .setSubject("YYGH-USER")
                .setExpiration(new Date(System.currentTimeMillis() + tokenExpiration))
                .claim("userId", userId)
                .signWith(SignatureAlgorithm.HS512, tokenSignKey)
                .compressWith(CompressionCodecs.GZIP)
                .compact();
        return token;
    }

    //从token字符串获取userid
    public static Long getUserId(String token) {
        if(StringUtils.isEmpty(token)) return null;
        Jws<Claims> claimsJws = Jwts.parser().setSigningKey(tokenSignKey).parseClaimsJws(token);
        Claims claims = claimsJws.getBody();
        Integer userId = (Integer)claims.get("userId");
        return userId.longValue();
    }



    //判断token是否有效
    public static boolean isExpiration(String token){
        try {
            boolean isExpire = Jwts.parser()
                    .setSigningKey(tokenSignKey)
                    .parseClaimsJws(token)
                    .getBody()
                    .getExpiration().before(new Date());
            //没有过期,有效,返回false
            return isExpire;
        }catch(Exception e) {
            //过期出现异常,返回true
            return true;
        }
    }
}

使用示例

public class JwtExample {

    public static void main(String[] args) {
        // 模拟用户ID
        Long userId = 123L;

        // 1. 生成 JWT token
        String token = JwtHelper.createToken(userId);
        System.out.println("生成的 JWT Token: " + token);

        // 2. 从 token 中解析用户ID
        Long extractedUserId = JwtHelper.getUserId(token);
        System.out.println("从 JWT Token 中解析出的用户ID: " + extractedUserId);

        // 3. 验证 token 是否过期
        boolean isExpired = JwtHelper.isExpiration(token);
        System.out.println("JWT Token 是否过期: " + isExpired);
    }
}

MD5Util(MD5加密)

        这个类是一个用于对字符串进行 MD5 哈希加密的工具类。MD5 是一种广泛使用的散列函数,可以将任意长度的数据映射到一个固定长度的哈希值(通常是 128 位)。该类提供了一个静态的 encrypt 方法,用于将输入字符串加密为 MD5 哈希值,并将其结果以 16 进制格式输出。

类方法

encrypt(String strSrc)
public static String encrypt(String strSrc) {
    try {
        char hexChars[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8',
                            '9', 'a', 'b', 'c', 'd', 'e', 'f' };
        byte[] bytes = strSrc.getBytes();
        MessageDigest md = MessageDigest.getInstance("MD5");
        md.update(bytes);
        bytes = md.digest();
        int j = bytes.length;
        char[] chars = new char[j * 2];
        int k = 0;
        for (int i = 0; i < bytes.length; i++) {
            byte b = bytes[i];
            chars[k++] = hexChars[b >>> 4 & 0xf];
            chars[k++] = hexChars[b & 0xf];
        }
        return new String(chars);
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
        throw new RuntimeException("MD5加密出错!!+" + e);
    }
}
  • hexChars[] 数组:这个数组用于将 MD5 生成的字节结果转换为 16 进制字符。MD5 的结果是一个二进制数组,通过该数组,生成的字节可以被映射成 0-9a-f 的 16 进制形式。
  • strSrc.getBytes():将输入的字符串转换为字节数组,因为 MD5 加密是基于字节数组进行的。
  • MessageDigest.getInstance("MD5")MessageDigest 是 Java 提供的加密 API,用于生成散列值。这里通过 getInstance("MD5") 来创建一个 MD5 加密算法的实例。
  • md.update(bytes):将字节数组传入 MD5 算法进行处理。
  • bytes = md.digest():通过调用 digest() 方法,完成对数据的 MD5 哈希运算,并返回一个字节数组。这个字节数组长度是 16(128 位),表示 MD5 的加密结果。
  • 将字节转换为 16 进制字符:MD5 的结果是一个字节数组,每个字节是 8 位(二进制)。为了将其表示为 16 进制的字符串,需要将每个字节分为高 4 位和低 4 位,分别映射到 hexChars[] 数组中的字符。通过这个过程,最终会生成一个长度为 32 的字符数组(每个字节对应 2 个 16 进制字符),然后将其转换为字符串返回。

使用示例

String encrypted = MD5Util.encrypt("password123");
System.out.println("加密后的字符串: " + encrypted);

代码示例

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public final class MD5Util {
    public static String encrypt(String strSrc) {
        try {
            char hexChars[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8',
                    '9', 'a', 'b', 'c', 'd', 'e', 'f' };
            byte[] bytes = strSrc.getBytes();
            MessageDigest md = MessageDigest.getInstance("MD5");
            md.update(bytes);
            bytes = md.digest();
            int j = bytes.length;
            char[] chars = new char[j * 2];
            int k = 0;
            for (int i = 0; i < bytes.length; i++) {
                byte b = bytes[i];
                chars[k++] = hexChars[b >>> 4 & 0xf];
                chars[k++] = hexChars[b & 0xf];
            }
            return new String(chars);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            throw new RuntimeException("MD5加密出错!!+" + e);
        }
    }
}

WebUtil(处理Web请求与响应)

        这个类是一个用于处理 Web 请求和响应的工具类,主要用于将请求中的 JSON 数据转换为 Java 对象,以及将 Java 对象转换为 JSON 字符串并写入 HTTP 响应中。它通过 Jackson 库的 ObjectMapper 来实现 JSON 与 Java 对象之间的相互转换,并且处理了 HTTP 请求与响应的常见操作。

静态成员变量及静态代码块

private static ObjectMapper objectMapper;

static {
    objectMapper = new ObjectMapper();
    // 设置JSON和Object转换时的时间日期格式
    objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
}
  • ObjectMapper:这是 Jackson 提供的核心类,用于处理 JSON 数据与 Java 对象之间的转换。它支持将 JSON 字符串转换为 Java 对象,也支持将 Java 对象序列化为 JSON 字符串。
  • 静态初始化:在类加载时,静态代码块会被执行,初始化 ObjectMapper 对象,并设置 JSON 与对象转换时的日期格式为 "yyyy-MM-dd HH:mm:ss"。这样,在处理日期类型字段时,统一使用该格式。

类方法

readJson(HttpServletRequest request, Class<T> clazz)
public static <T> T readJson(HttpServletRequest request, Class<T> clazz) {
    T t = null;
    BufferedReader reader = null;
    try {
        reader = request.getReader();
        StringBuffer buffer = new StringBuffer();
        String line = null;
        while ((line = reader.readLine()) != null) {
            buffer.append(line);
        }
        t = objectMapper.readValue(buffer.toString(), clazz);
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
    return t;
}

功能:从 HttpServletRequest 中读取 JSON 字符串并将其转换为指定类型的 Java 对象。

  • 泛型支持:该方法是泛型方法,支持将 JSON 数据转换为任何类型的 Java 对象,类型由传入的 Class<T> 参数指定。
  • 步骤
    1. 使用 request.getReader() 获取请求体中的数据,这个方法返回 BufferedReader,可以按行读取请求的内容。
    2. 将读取到的内容逐行拼接到 StringBuffer 中。
    3. 通过 objectMapper.readValue(buffer.toString(), clazz) 将 JSON 字符串转换为指定的 Java 对象。
  • 异常处理:如果在读取或转换过程中发生 IOException 异常,则捕获该异常并抛出运行时异常。

用途:该方法适用于从客户端的 POST 请求体中读取 JSON 数据,并将其转换为对应的 Java 对象(如一个 DTO 类),以便在服务端处理。

writeJson(HttpServletResponse response, Result result)
public static void writeJson(HttpServletResponse response, Result result) {
    response.setContentType("application/json;charset=UTF-8");
    try {
        String json = objectMapper.writeValueAsString(result);
        response.getWriter().write(json);
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
}

功能:将 Result 对象转换为 JSON 字符串并写入到 HTTP 响应中。

  • 步骤
    1. 设置响应的内容类型为 application/json,并指定字符编码为 UTF-8,确保返回给客户端的 JSON 字符串能够被正确解析。
    2. 通过 objectMapper.writeValueAsString(result) 将 Java 对象(这里是 Result 对象)转换为 JSON 字符串。
    3. 使用 response.getWriter().write(json) 将生成的 JSON 写入到 HTTP 响应中,发送给客户端。
  • 异常处理:捕获可能的 IOException 异常并抛出运行时异常。

用途:该方法适用于将服务器处理结果(如业务处理的响应信息)转换为 JSON 格式并返回给客户端。例如,在 RESTful 接口中,服务器通常以 JSON 格式返回数据给前端或移动端应用。

使用示例

从请求中读取 JSON:

User user = WebUtil.readJson(request, User.class);
// 现在 user 对象包含了请求体中的 JSON 数据

将对象返回为 JSON 响应:

Result result = new Result(200, "Success", data);
WebUtil.writeJson(response, result);

代码示例

import com.atguigu.headline.common.Result;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import java.io.BufferedReader;
import java.io.IOException;
import java.text.SimpleDateFormat;

public class WebUtil {
    private static ObjectMapper objectMapper;
    // 初始化objectMapper
    static{
        objectMapper=new ObjectMapper();
        // 设置JSON和Object转换时的时间日期格式
        objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
    }
    // 从请求中获取JSON串并转换为Object
    public static <T> T readJson(HttpServletRequest request,Class<T> clazz){
        T t =null;
        BufferedReader reader = null;
        try {
            reader = request.getReader();
            StringBuffer buffer =new StringBuffer();
            String line =null;
            while((line = reader.readLine())!= null){
                buffer.append(line);
            }

            t= objectMapper.readValue(buffer.toString(),clazz);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return t;
    }
    // 将Result对象转换成JSON串并放入响应对象
    public static void writeJson(HttpServletResponse response, Result result){
        response.setContentType("application/json;charset=UTF-8");
        try {
            String json = objectMapper.writeValueAsString(result);
            response.getWriter().write(json);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值