前言: 在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(); } } }
特别说明:如果能帮助到您,请您留下点滴痕迹,让我知道我的存在是有意义的;如果不能帮助到您,请接受我的歉意;(示例下载)