Java 在webapp中使用自定义字符集

Java 在webapp中使用自定义字符集,java,servlets,character-encoding,Java,Servlets,Character Encoding,我在使用Web应用程序中的自定义字符集时遇到问题。字符集是在JAR中提供的,charset.forName(“MYCUSTOMCHARSET”)在JavaSE应用程序中工作时不会出现问题。但是,在webapp中,此方法将抛出不受支持的HarsetException 我知道这是类加载器的问题,我知道我可以通过将JAR添加到servlet引擎的类路径来解决这个问题。但这不是我想要的。我希望能够向我的客户交付一个自包含的WAR文件,而无需客户摆弄周围的容器 换句话说:我正在搜索一种允许我的webapp

我在使用Web应用程序中的自定义字符集时遇到问题。字符集是在JAR中提供的,
charset.forName(“MYCUSTOMCHARSET”)
在JavaSE应用程序中工作时不会出现问题。但是,在webapp中,此方法将抛出
不受支持的HarsetException

我知道这是类加载器的问题,我知道我可以通过将JAR添加到servlet引擎的类路径来解决这个问题。但这不是我想要的。我希望能够向我的客户交付一个自包含的WAR文件,而无需客户摆弄周围的容器

换句话说:我正在搜索一种允许我的webapp“手动”加载字符集的方法。从提供自定义字符集的JAR中的
services
文件夹中,我可以看到CharsetProvider的完全限定名,例如
com.acme.CustomCharsetProvider
。我想知道这对我是否有帮助


平台:Java8和Tomcat8。

根据上面来自Joop的评论,我能够得出以下结论。下面的方法是一个防弹配方的尝试,无论我们处于何种场景(例如独立的JavaSE应用程序、webapp等),都可以始终获得自定义字符集

在该方法中,自定义字符集预期由class
com.acme.CustomCharsetProvider提供(替换为您自己的)

该方法使用三种不同的尝试来获取字符集:

  • 标准方法。这将适用于JavaSE应用程序,但不适用于 webapps,除非保存自定义字符集的JAR可用 在servlet引擎的类路径上
  • ServiceLoader方法。这应该行得通,但对我来说不行。无法解释原因
  • 手动实例化提供程序类。(这对我有用)
  • 代码如下:

    public static Charset getMyCustomCharset() throws java.nio.charset.UnsupportedCharsetException {
        Charset customCharset = null;
        try {
            // This will fail if running in web container because
            // the JDK loads charsets using the system class loader in the servlet
            // engine (e.g. Tomcat) so unless the JAR is available on the engine's
            // classpath then the charset will not be visible to the webapp.
            // The solution is to load the charset "manually" as below.
            customCharset = Charset.forName(CHARSET_NAME);
        } catch (Exception ex) {
            // Try to load the charset manually using ServiceLoader concept
            for (CharsetProvider charsetProvider : ServiceLoader.load(com.acme.CustomCharsetProvider.class)) {
                customCharset  = charsetProvider.charsetForName(CHARSET_NAME);
                if (customCharset != null) {
                    break;
                }
            }
            // Make a final attempt. This time directly, i.e. without the use of
            // the ServiceLoader.
            if (customCharset == null) {
                com.acme.CustomCharsetProvider p = new com.acme.CustomCharsetProvider();
                customCharset = p.charsetForName(CHARSET_NAME);
            }
        }
        if (customCharset == null) {
            throw new java.nio.charset.UnsupportedCharsetException("Unknown charset : " + CHARSET_NAME);
        }
        return customCharset;
    }
    

    根据以上来自Joop的评论,我能够得出以下结论。下面的方法是一个防弹配方的尝试,无论我们处于何种场景(例如独立的JavaSE应用程序、webapp等),都可以始终获得自定义字符集

    在该方法中,自定义字符集预期由class
    com.acme.CustomCharsetProvider提供(替换为您自己的)

    该方法使用三种不同的尝试来获取字符集:

  • 标准方法。这将适用于JavaSE应用程序,但不适用于 webapps,除非保存自定义字符集的JAR可用 在servlet引擎的类路径上
  • ServiceLoader方法。这应该行得通,但对我来说不行。无法解释原因
  • 手动实例化提供程序类。(这对我有用)
  • 代码如下:

    public static Charset getMyCustomCharset() throws java.nio.charset.UnsupportedCharsetException {
        Charset customCharset = null;
        try {
            // This will fail if running in web container because
            // the JDK loads charsets using the system class loader in the servlet
            // engine (e.g. Tomcat) so unless the JAR is available on the engine's
            // classpath then the charset will not be visible to the webapp.
            // The solution is to load the charset "manually" as below.
            customCharset = Charset.forName(CHARSET_NAME);
        } catch (Exception ex) {
            // Try to load the charset manually using ServiceLoader concept
            for (CharsetProvider charsetProvider : ServiceLoader.load(com.acme.CustomCharsetProvider.class)) {
                customCharset  = charsetProvider.charsetForName(CHARSET_NAME);
                if (customCharset != null) {
                    break;
                }
            }
            // Make a final attempt. This time directly, i.e. without the use of
            // the ServiceLoader.
            if (customCharset == null) {
                com.acme.CustomCharsetProvider p = new com.acme.CustomCharsetProvider();
                customCharset = p.charsetForName(CHARSET_NAME);
            }
        }
        if (customCharset == null) {
            throw new java.nio.charset.UnsupportedCharsetException("Unknown charset : " + CHARSET_NAME);
        }
        return customCharset;
    }
    

    @乔迪卡斯蒂拉。我猜您指的是在编码/解码HTTP请求的上下文中使用字符集?我说的是字符集的一般用法,例如在应用程序本身中对字符串进行编码/解码。另外,我的问题并不是真正针对Tomcat的,尽管我对Tomcat特定的解决方案没有意见。实际上
    META-INF/services/java.nio.charset.spi.CharsetProvider
    然后
    for(CharsetProvider CharsetProvider:ServiceLoader.load(CharsetProvider.class)){…
    ?@JoopEggen。谢谢。请参阅下面我建议的解决方案。@JordiCastilla。我猜您指的是在编码/解码HTTP请求的上下文中使用字符集?我指的是一般情况下使用字符集,例如,在应用程序本身中对字符串进行编码/解码。另外,我的问题并非真正针对Tomcat虽然我可以使用Tomcat特定的解决方案。事实上,
    META-INF/services/java.nio.charset.spi.CharsetProvider
    ,然后是(CharsetProvider CharsetProvider:ServiceLoader.load(CharsetProvider.class)){…
    ?@JoopEggen。谢谢。请参阅下面我建议的解决方案。