java web开发中文乱码终极解决方案总结(Tomcat+mysql+eclipse)
总的原则:各个层面编码一致!
第一层面:后台数据库层面
创建好数据库表之后,查看表结构中各字段的编码,确保为UTF-8,如果 不是,则在msql命令行或者在Navicat或者Workbench等中工具中执行以下脚本:
set character_set_database="utf8";
set character_set_client="utf8";
set character_set_connection="utf8";
set character_set_results="utf8";
set character_set_server="utf8";
set character_set_system="utf8";
第二层面 eclipse集成环境和Tomcat层面
打开Tomcat安装目录,打开conf目录,找到logging.properties配置文件,右击该文件,用记事本打开,将java.util.ConsoleHandler.encoding=UTF-8中的UTF-8改为GBK,保存文件,关闭记事本。
Eclipse ->window->proferences->General->workspace 设置成utf-8。
Eclipse ->window -> Preferences -> general -> Content Types(这里是设置不同文件的编码,例如Java文件,jsp文件,css文件等不同类型的文件的编码方式设置为utf-8)
在tomcat安装目录下的conf/server.xml(用记事本打开)下的connetor属性中增加URIEncoding = “UTF-8”。
<Service name="Catalina">
<Connector port="8080" protocol="HTTP/1.1" redirectPort="8443 **"URIEncoding="UTF-8"** />
<!-- 其他配置 -->
</Service>
第三层面 HTML、jsp前台代码层面
jsp:确保有这行
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
HTML:确保有这行
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
第四层面:控制层面(后台Servlet层面 )
1.没有过滤器的情况
确保doGet()方法或者Service()方法中有以下几行:
response.setContentType("text/html;charset=UTF-8"); //设置服务器返回页面编码方式
request.setCharacterEncoding("UTF-8"); //解决Post方式请求中文参数乱码
response.setCharacterEncoding("utf-8");
并且是在下面这行之前 !
PrintWriter pw=response.getWriter();
这种情况有个缺点,就是各个Servlet中都要写。因此推荐使用过滤器。
2.使用过滤器的情况
使用注解(适用于Servlet3.0及以上)
@WebFilter(//Servlet3.0注解配置字符编码
urlPatterns = { "/CharFilter" },
initParams = {
@WebInitParam(name = "charset", value = "UTF-8")//字符编码
})
再在doFilter()方法中加入以下代码,并确保在chain.doFilter(request, response)这行之前!
this.charSet=fConfig.getInitParameter("charset");
request.setCharacterEncoding(this.charSet);
response.setContentType("text/html;charset="+this.charSet);
第五层面:连接层面
1.直接使用连接字符串的情况
使用如下类似代码!
private static final String DBDRIVER="com.mysql.jdbc.Driver";//mysql低版本使用,如果 为8.0以上则为com.mysql.cj.jdbc.Driver
private static final String DBURL="jdbc:mysql://localhost:3306/countrystudent?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC&useSSL=false";
private static final String DBUSER="root";
private static final String DBPASSWORD="123456";
private Connection conn=null;
Class.forName(DBDRIVER);
conn=DriverManager.getConnection(DBURL,DBUSER,DBPASSWORD);
2.使用数据库连接池的情况
最好在项目的webContent的META-INF文件夹下建立content.xml文件,在其中定义数据库连接池, 注意:XML中字符串里的&等特殊符号需要转义,每个转义单元以分号结束。见红色代码部分
<Resource
name="jdbc/WyjDB"
auth="Container"
type="javax.sql.DataSource"
driverClassName="com.mysql.cj.jdbc.Driver"
url="jdbc:mysql://localhost:3306/countrystudent?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=UTC"
username="root"
password="123456"
maxActive="100"
maxIdle="30"
maxWait="1000"/>
连接池使用要用到JNDI上下文:
private static final String DSNAME="java:comp/env/jdbc/WyjDB";//数据源JNDI名,“java:comp/env/”为JavaEE规定上下文前缀,解决查找 时的名称冲突问题
private Connection conn=null;
public DatabaseConnection() throws Exception{
try{
Context ctx=new InitialContext();//初始化JNDI上下文对象
DataSource ds=(DataSource)ctx.lookup(DSNAME);//用JNDI名查找数据源
this.conn=ds.getConnection();//通过数据源获得连接,赋值给conn成员
}catch(Exception e){
throw e;
}
}
需要 注意的是,如果连接层面不设置的话,即使前面的数据库建立时设置了UTF-8,也还会出现 乱码!