Java_通过PreparedStatement往MySql数据库插入中文出现'?'乱码问题解决;

时间:2021-12-22 06:35:28

前言: 在Java中,通过PreparedStatement往MySql数据库插入中文出现'?'乱码问题,困扰好久!通过九九八十一难后,终于得到解决!其实,说起来不难理解, 我们知道,在java中经常通过jdbc连接MySQL数据库,如果我们在连接url的末尾加上?characterEncoding=gbk,明确指定编码,问题就迎刃而解。下面是示例(通过测试):


=>RequestListener.java

package lee;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;

import java.sql.*;

@WebListener
public class RequestListener implements ServletRequestListener {
	// 当用户请求到达、被初始化时触发该方法
	public void requestInitialized(ServletRequestEvent sre) {
		HttpServletRequest request = (HttpServletRequest)sre.getServletRequest();
		
		HttpSession session = request.getSession();
		String sessionId = session.getId();		// 获取session ID;
		String ip = request.getRemoteAddr();	// 获取访问的IP;
		String page = request.getRequestURI();	// 正在访问的页面;
		String user = (String)session.getAttribute("user");
		user = (user == null) ? "游23客" : user;	// 未登录用户当游客处理;

		try {
			// 特别说明数据库url中尾部添加?characterEncoding=gbk是解决java PreparedStatement 插入中文时出现的"?"乱码;
			DbDao dd = new DbDao(
					"com.mysql.jdbc.Driver",
					"jdbc:mysql://localhost:3306/online_inf?characterEncoding=gbk",
					"dbuser", "123456");
			ResultSet rs = dd.query(
					"select * from online_inf where session_id=?", true, sessionId);
			
			// 如果该用户对应的session ID存在,表明是旧的会话
			if (rs.next()) {
				// 更新记录
				rs.updateString(4, page);
				rs.updateLong(5, System.currentTimeMillis());
				rs.updateRow();
				rs.close();
			} else {
				// 插入该用户的在线信息
				dd.insert("insert into online_inf values(? , ? , ? , ? , ?)",
						sessionId, user, ip, page, System.currentTimeMillis());
			}
		} catch (Exception ex) {
			ex.printStackTrace();
		}
	}

	// 当用户请求结束、被销毁时触发该方法
	public void requestDestroyed(ServletRequestEvent sre) {
	}
}

=>OnlineListener.java

package lee;

import javax.servlet.*;
import javax.servlet.annotation.*;
import javax.servlet.http.*;

import java.sql.*;
import java.awt.event.*;

@WebListener
public class OnlineListener implements ServletContextListener {
	// 超过该时间(10分钟)没有访问本站即认为用户已经离线
	public final int MAX_MILLIS = 10 * 60 * 1000;

	// 应用启动时触发该方法
	public void contextInitialized(ServletContextEvent sce) {
		// 每5秒检查一次
		new javax.swing.Timer(1000 * 5, new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				try {
					// 特别说明数据库url中尾部添加?characterEncoding=gbk是解决java PreparedStatement 插入中文时出现的"?"乱码;
					DbDao dd = new DbDao(
							"com.mysql.jdbc.Driver",
							"jdbc:mysql://localhost:3306/online_inf?characterEncoding=gbk",
							"dbuser", "123456");
					
					ResultSet rs = dd.query("select * from online_inf", false);
					StringBuffer beRemove = new StringBuffer("(");
					while (rs.next()) {
						// 如果距离上次访问时间超过了指定时间
						if ((System.currentTimeMillis() - rs.getLong(5)) > MAX_MILLIS) {
							// 将需要被删除的session ID添加进来
							beRemove.append("'");
							beRemove.append(rs.getString(1));
							beRemove.append("' , ");
						}
					}
					// 有需要删除的记录
					if (beRemove.length() > 3) {
						beRemove.setLength(beRemove.length() - 3);
						beRemove.append(")");
						// 删除所有“超过指定时间未重新请求的记录”
						dd.modify("delete from online_inf where session_id in "	+ beRemove.toString());
					}
					dd.closeConn();
				} catch (Exception ex) {
					ex.printStackTrace();
				}
			}
		}).start();
	}

	public void contextDestroyed(ServletContextEvent sce) {
	}
}

=>DbDao.java

package lee;

import java.sql.*;

public class DbDao {
	private Connection conn;
	private String driver;
	private String url;
	private String username;
	private String pass;

	public DbDao() {
	}

	public DbDao(String driver, String url, String username, String pass) {
		this.driver = driver;
		this.url = url;
		this.username = username;
		this.pass = pass;
	}

	// 下面是各个成员属性的setter和getter方法
	public void setDriver(String driver) {
		this.driver = driver;
	}

	public void setUrl(String url) {
		this.url = url;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public void setPass(String pass) {
		this.pass = pass;
	}

	public String getDriver() {
		return (this.driver);
	}

	public String getUrl() {
		return (this.url);
	}

	public String getUsername() {
		return (this.username);
	}

	public String getPass() {
		return (this.pass);
	}

	// 获取数据库连接
	public Connection getConnection() throws Exception {
		if (conn == null) {
			Class.forName(this.driver);
			conn = DriverManager.getConnection(url, username, this.pass);
		}
		return conn;
	}

	// 插入记录
	public boolean insert(String sql, Object... args) throws Exception {
		PreparedStatement pstmt = getConnection().prepareStatement(sql);
		
		for (int i = 0; i < args.length; i++) {
			pstmt.setObject(i + 1, args[i]);
		}
		
		if (pstmt.executeUpdate() != 1) {
			return false;
		}
		
		pstmt.close();
		return true;
	}

	// 执行查询
	public ResultSet query(String sql, boolean updatable, Object... args)
			throws Exception {
		PreparedStatement pstmt = null;
		if (updatable) {
			// 创建可更新的PreparedStatement
			pstmt = getConnection().prepareStatement(sql,
					ResultSet.TYPE_SCROLL_INSENSITIVE,
					ResultSet.CONCUR_UPDATABLE);
		} else {
			pstmt = getConnection().prepareStatement(sql);
		}
		for (int i = 0; i < args.length; i++) {
			pstmt.setObject(i + 1, args[i]);
		}
		return pstmt.executeQuery();
	}

	// 执行修改
	public void modify(String sql, Object... args) throws Exception {
		PreparedStatement pstmt = getConnection().prepareStatement(sql);
		for (int i = 0; i < args.length; i++) {
			pstmt.setObject(i + 1, args[i]);
		}
		pstmt.executeUpdate();
		pstmt.close();
	}

	// 关闭数据库连接的方法
	public void closeConn() throws Exception {
		if (conn != null && !conn.isClosed()) {
			conn.close();
		}
	}
}

特别说明:如果能帮助到您,请您留下点滴痕迹,让我知道我的存在是有意义的;如果不能帮助到您,请接受我的歉意;(示例下载)