Version 2

    原文:开发基于JBoss AS 7.2.0的Java EE程序 - 08.如何设置UTF-8

    英文:JBoss AS 7.2.0 - Java EE application development - 08.How to configure UTF-8

     

    概述

    为了能够让我们的Java EE程序显示中文,英文,等多国文字,我们需要在很多地方设置UTF-8编码格式。缺一不可!

     

    1. MySql数据库编码设置

    请参见 CentOS 6.4安装MySql Server和Client,设置字符集为UTF-8,修改登陆密码

    一文中的 链接

     

    2. ServletRequest和ServletResponse编码设置

    我们通过Servlet Filter将所有ServletRequest和ServletResponse的编码格式设置为UTF-8。

     

    package com.ybxiang.forum.servlet.filter;

     

    import java.io.IOException;

    import java.io.UnsupportedEncodingException;

    import java.util.logging.Logger;

     

    import javax.servlet.*;

    import javax.servlet.http.HttpServletRequest;

    import javax.servlet.http.HttpServletResponse;

     

    import com.ybxiang.forum.jsfmbean.ParameterHelper;

     

    /**

    * http://bbs.csdn.net/topics/300037688

    * @author yingbinx

    *

    */

    @javax.servlet.annotation.WebFilter("/*")

    public class EncodingFilter implements Filter {

        static final Logger logger = Logger.getLogger(EncodingFilter.class.getName());

     

        //FilterConfig config;

     

        public void doFilter(ServletRequest r1, ServletResponse r2, FilterChain chain)throws ServletException,IOException {

            HttpServletRequest request = (HttpServletRequest)r1;

            HttpServletResponse response = (HttpServletResponse)r2;

           

            try {

                request.setCharacterEncoding(ParameterHelper.ENCODING);
                response.setCharacterEncoding(ParameterHelper.ENCODING);

            } catch (UnsupportedEncodingException e) {

                logger.severe(e.getMessage());

            }

           

            //WARNING: do NOT swallow any Exception!!! If container can not see any exception, it will not redirect client to related error page.

            //You can catch Exceptions and print them, and you must throw them at last!

            chain.doFilter(r1, r2);

        }

        @Override

        public void destroy() {

        }

        @Override

        public void init(FilterConfig arg0) throws ServletException {

            //config = arg0;

        }

    }

     

    其中ParameterHelper.ENCODING 的定义:

    public class ParameterHelper{
        static final Logger logger = Logger.getLogger(ParameterHelper.class.getName());
        public static final String ENCODING = "UTF-8";
        ...
    }

     

    3. ServletResponse编码设置

    如果我们的Servlet要想客户端(浏览器)写入一些字符,那么也要设置UTF-8。

    当然我们在前面已经对所有的Servlet的请求和相应设置过UTF-8编码格式了,这里是否需要这么做,本人没有测试过。

     

    @WebServlet("/UploadPortraitServlet")

    public class UploadPortraitServlet extends HttpServlet {

        private static final long serialVersionUID = 1L;

       

        ....

     

        protected void doPost(HttpServletRequest request,

                HttpServletResponse response) throws ServletException, IOException {

            response.setContentType("text/html;charset=UTF-8");

            ...

        }

    ...

    }

     

    4. web.xml

    <?xml version="1.0" encoding="UTF-8"?>

    <web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">

        <context-param>

          <param-name>PARAMETER_ENCODING</param-name>
          <param-value>UTF-8</param-value>

        </context-param>

        <!-- Production,Development,UnitTest,SystemTest,Extension -->

        <context-param>

            <param-name>javax.faces.PROJECT_STAGE</param-name>

            <param-value>Development</param-value>

        </context-param>

        <context-param>

    ...

    }

     

     

    5. jboss-web.xml

    如果所有地方都设置了UTF-8,唯独这里没有设置UTF-8,那么中文用户名进行JAAS登陆会失败。

     

    <?xml version="1.0" encoding="UTF-8"?>

    <jboss-web>

        <security-domain>java:/jaas/ybxiang-forum-jaas-security-domain</security-domain>

        <!-- encoding for login servlet 'j_security_check' -->

        <valve>

            <class-name>org.apache.catalina.authenticator.FormAuthenticator</class-name>

            <param>

                <param-name>characterEncoding</param-name>
                <param-value>UTF-8</param-value>

            </param>

        </valve>

    </jboss-web>

     

     

    6. faces-config.xml

    <?xml version="1.0" encoding="UTF-8"?>

    <faces-config version="2.1" xmlns="http://java.sun.com/xml/ns/javaee"

    xmlns:xi="http://www.w3.org/2001/XInclude"

    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_2_1.xsd">

    ...

    </faces-config>

     

    7. JSF pages

    (a) 常规页面

    <?xml version='1.0' encoding='UTF-8' ?>
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml"
          xmlns:h="http://java.sun.com/jsf/html"
          xmlns:f="http://java.sun.com/jsf/core"
          xmlns:ui="http://java.sun.com/jsf/facelets">
        ...
    </html>

    (b) 组件(component)页面

    <?xml version='1.0' encoding='UTF-8' ?>

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

    <ui:composition xmlns="http://www.w3.org/1999/xhtml"

        xmlns:ui="http://java.sun.com/jsf/facelets"

        xmlns:h="http://java.sun.com/jsf/html"

        xmlns:f="http://java.sun.com/jsf/core">

        ...

    </ui:composition>

     

     

     

    8. JSF MBean中解析URL中的UTF-8参数

    比如,我们的访问

    http://javaarm.com/faces/list.xhtml?mid=42&keywords=介绍
    或者
    http://javaarm.com/faces/list.xhtml?mid=42&keywords=%E4%BB%8B%E7%BB%8D

    那么,我就需要在TopicGroupingPagerMBean.java中对“keywords”这个参数进行UTF-8解码!

     


    @ManagedBean
    @RequestScoped
    public class TopicGroupingPagerMBean extends AbstractPagerMBean{
        static final Logger logger = Logger.getLogger(TopicGroupingPagerMBean.class.getName());
        ...
       
        //*****************************************[地址参数]*****************************************//
        ...
        public final String getKeywords(){
            String keywords = ParameterHelper.getString(ParameterHelper.URL_PARAMETER_NAME_KEYWORDS);
            if(keywords==null || keywords.trim().length()==0){
                return "";
            }
            try{
                keywords = java.net.URLDecoder.decode(keywords, ParameterHelper.ENCODING);
            }catch(Exception e){
                Log.error(e);
            }
            return keywords;
        }
        ...
    }

     

    其中 ParameterHelper为:
    public class ParameterHelper{

        public static final String ENCODING = "UTF-8";
        ...
        public static String getString(String parameterName) {
            //logger.info("ParameterName:"+parameterName);
            //Map mp = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap();
            @SuppressWarnings("rawtypes")
            Map mp = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap();
            if (mp == null || mp.isEmpty()) {
                //logger.info("parameters are null");
                return null;
            } else {
                Object obj_by_paramId = mp.get(parameterName);
                Object obj_by_formIdPlusParamId = mp.get(FORM_ID+":"+parameterName);

                if(obj_by_paramId!=null){
                    return obj_by_paramId.toString();
                }else if(obj_by_formIdPlusParamId!=null){
                    return obj_by_formIdPlusParamId.toString();
                }else{
                   // logger.severe(parameterName+" has NO value!!!");
                    return null;
                }
            }
        }

     

     

    9. JBoss AS 7 的 standalone.xml UTF-8设置

    (a) JAAS hashCharset

            <subsystem xmlns="urn:jboss:domain:security:1.2">
                <security-domains>
                    <security-domain name="ybxiang-forum-jaas-security-domain" cache-type="default">
                        <authentication>
                            <login-module code="Remoting" flag="optional">
                                <module-option name="password-stacking" value="useFirstPass"/>
                            </login-module>
                            <login-module code="org.jboss.security.auth.spi.DatabaseServerLoginModule" flag="required">
                                <module-option name="password-stacking" value="useFirstPass"/>
                                <module-option name="dsJndiName" value="java:jboss/datasources/ybxiangForumMySqlDataSource"/>
                                <module-option name="principalsQuery" value="SELECT hashedPassword FROM User WHERE username=? and activated=true and locked=false"/>
                                <module-option name="rolesQuery" value="SELECT DISTINCT r.name, 'Roles' FROM User u, User_UserGroup ug, UserGroup_JaasRole gr, JaasRole r WHERE u.id=ug.user_id AND ug.usergroup_id=gr.usergroup_id AND gr.jaasrole_id=r.id AND u.username=?"/>
                                <module-option name="hashAlgorithm" value="SHA-256"/>
                                <module-option name="hashEncoding" value="Base64"/>
                                <module-option name="hashCharset" value="UTF-8"/>
                                <module-option name="unauthenticatedIdentity" value="guest"/>
                            </login-module>
                        </authentication>
                    </security-domain>
                    ...
                ...
            ...