Spring,thymeleaf,JPA / hibernate,mysql UTF-8字符在db中持久存在

时间:2014-12-22 13:03:32

标签: mysql spring hibernate jpa thymeleaf

我在mysql db中持久保存抛光PL-pl语言环境字符时遇到问题。 我知道这是常见的问题,在互联网上有许多解决方案。但我无法弄明白。我想我已经尝试了一切。

我的所有网页都正确编码并显示UTF-8字符(来自html和db的静态字符)

当我在应用程序中使用表单在db中保存somthing时出现了问题。所以我认为它与JDBC,JPA和hibernate密切相关。

这是我的配置:

application.properties

#DB Properties:
# Mysql
db.driver=com.mysql.jdbc.Driver
db.url=jdbc:mysql://localhost:3300/derp?characterEncoding=UTF-8
hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
db.username=root
db.password=motorolaa835
# H2
#db.driver=org.h2.Driver
#db.url=jdbc:h2:~/sts/derp/db/derp_db
#hibernate.dialect=org.hibernate.dialect.H2Dialect
#db.username=root

#Hibernate Configuration:
hibernate.show_sql=true
hibernate.hbm2ddl.auto=update
#hibernate.hbm2ddl.auto=create
hibernate.connection.CharSet=utf8
hibernate.connection.characterEncoding=utf8
hibernate.connection.useUnicode=true
services.entitymanager.packages.to.scan=com.derp
cms.entitymanager.packages.to.scan=com.derp.cms.model
common.entitymanager.packages.to.scan=com.derp.common.model
procedure.entitymanager.packages.to.scan=com.derp.procedure.model

初始化程序

  package com.derp.common.init;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration.Dynamic;

import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.ContextLoaderListener;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.filter.CharacterEncodingFilter;
import org.springframework.web.filter.HiddenHttpMethodFilter;
import org.springframework.web.servlet.DispatcherServlet;

public class Initializer implements WebApplicationInitializer {


    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
        ctx.register(WebAppConfig.class);
        ctx.register(ThymeleafConfig.class);
        servletContext.addListener(new ContextLoaderListener(ctx));

        ctx.setServletContext(servletContext);

        Dynamic servlet = servletContext.addServlet("dispatcher", new DispatcherServlet(ctx));
        servlet.addMapping("/");
        servlet.setAsyncSupported(true);     
        servlet.setLoadOnStartup(1);
        // Allow to use Put and Delete method for REST architecture
        registerCharachterEncodingFilter(servletContext);
        registerHiddenFieldFilter(servletContext);

    }

private void registerCharachterEncodingFilter(ServletContext aContext) {
    CharacterEncodingFilter cef = new CharacterEncodingFilter();
    cef.setForceEncoding(true);
    cef.setEncoding("UTF-8");
    aContext.addFilter("charachterEncodingFilter", cef).addMappingForUrlPatterns(null ,true, "/*");
}
    private void registerHiddenFieldFilter(ServletContext aContext) {
        aContext.addFilter("hiddenHttpMethodFilter", new HiddenHttpMethodFilter()).addMappingForUrlPatterns(null ,true, "/*"); 
    }
}

WebAppConfig

package com.derp.common.init;

import java.util.Properties;

import javax.annotation.Resource;
import javax.sql.DataSource;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.http.MediaType;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.hibernate4.HibernateTransactionManager;
import org.springframework.orm.hibernate4.LocalSessionFactoryBean;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

//import com.derp.common.wicketView.HomePage;

@Configuration
@ComponentScan("com.derp")
@EnableWebMvc
@EnableTransactionManagement
@PropertySource("classpath:application.properties")
public class WebAppConfig extends WebMvcConfigurerAdapter {

    private static final String PROPERTY_NAME_DATABASE_DRIVER = "db.driver";
    private static final String PROPERTY_NAME_DATABASE_PASSWORD = "db.password";
    private static final String PROPERTY_NAME_DATABASE_URL = "db.url";
    private static final String PROPERTY_NAME_DATABASE_USERNAME = "db.username";

    private static final String PROPERTY_NAME_HIBERNATE_DIALECT = "hibernate.dialect";
    private static final String PROPERTY_NAME_HIBERNATE_SHOW_SQL = "hibernate.show_sql";
    private static final String PROPERTY_NAME_HIBERNATE_HBM2DDL_AUTO = "hibernate.hbm2ddl.auto";
    private static final String PROPERTY_NAME_HIBERNATE_CONNECTION_CHARSET = "hibernate.connection.CharSet";
    private static final String PROPERTY_NAME_HIBERNATE_CONNECTION_CHARACTERENCODING = "hibernate.connection.characterEncoding";
    private static final String PROPERTY_NAME_HIBERNATE_CONNECTION_USEUNICODE = "hibernate.connection.useUnicode";
    private static final String PROPERTY_NAME_ENTITYMANAGER_PACKAGES_TO_SCAN_SERVICES = "services.entitymanager.packages.to.scan";
    private static final String PROPERTY_NAME_ENTITYMANAGER_PACKAGES_TO_SCAN_COMMON = "common.entitymanager.packages.to.scan";
    private static final String PROPERTY_NAME_ENTITYMANAGER_PACKAGES_TO_SCAN_CMS = "cms.entitymanager.packages.to.scan";
    private static final String PROPERTY_NAME_ENTITYMANAGER_PACKAGES_TO_SCAN_PROCEDURE = "procedure.entitymanager.packages.to.scan";

    @Resource
    private Environment env;

    @Bean
    public DataSource dataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName(env.getRequiredProperty(PROPERTY_NAME_DATABASE_DRIVER));
        dataSource.setUrl(env.getRequiredProperty(PROPERTY_NAME_DATABASE_URL));
        dataSource.setUsername(env.getRequiredProperty(PROPERTY_NAME_DATABASE_USERNAME));
        dataSource.setPassword(env.getRequiredProperty(PROPERTY_NAME_DATABASE_PASSWORD));
        return dataSource;
    }

    @Bean
    public LocalSessionFactoryBean sessionFactory() {
        LocalSessionFactoryBean sessionFactoryBean = new LocalSessionFactoryBean();
        sessionFactoryBean.setDataSource(dataSource());
        //sessionFactoryBean.setPackagesToScan(env.getRequiredProperty(PROPERTY_NAME_ENTITYMANAGER_PACKAGES_TO_SCAN));
        sessionFactoryBean.setPackagesToScan(new String[] {
                env.getRequiredProperty(PROPERTY_NAME_ENTITYMANAGER_PACKAGES_TO_SCAN_SERVICES),
                env.getRequiredProperty(PROPERTY_NAME_ENTITYMANAGER_PACKAGES_TO_SCAN_COMMON),
                env.getRequiredProperty(PROPERTY_NAME_ENTITYMANAGER_PACKAGES_TO_SCAN_CMS),
                env.getRequiredProperty(PROPERTY_NAME_ENTITYMANAGER_PACKAGES_TO_SCAN_PROCEDURE)
                });
        sessionFactoryBean.setHibernateProperties(hibProperties());
        return sessionFactoryBean;
    }

    private Properties hibProperties() {
        Properties properties = new Properties();
        properties.put(PROPERTY_NAME_HIBERNATE_DIALECT, env.getRequiredProperty(PROPERTY_NAME_HIBERNATE_DIALECT));
        properties.put(PROPERTY_NAME_HIBERNATE_SHOW_SQL, env.getRequiredProperty(PROPERTY_NAME_HIBERNATE_SHOW_SQL));
        properties.put(PROPERTY_NAME_HIBERNATE_HBM2DDL_AUTO, env.getRequiredProperty(PROPERTY_NAME_HIBERNATE_HBM2DDL_AUTO));
        properties.put(PROPERTY_NAME_HIBERNATE_CONNECTION_CHARSET, env.getRequiredProperty(PROPERTY_NAME_HIBERNATE_CONNECTION_CHARSET));
        properties.put(PROPERTY_NAME_HIBERNATE_CONNECTION_CHARACTERENCODING, env.getRequiredProperty(PROPERTY_NAME_HIBERNATE_CONNECTION_CHARACTERENCODING));
        properties.put(PROPERTY_NAME_HIBERNATE_CONNECTION_USEUNICODE, env.getRequiredProperty(PROPERTY_NAME_HIBERNATE_CONNECTION_USEUNICODE));
        properties.put("jadira.usertype.autoRegisterUserTypes", "true");
        return properties;  
    }

    @Bean
    public HibernateTransactionManager transactionManager() {
        HibernateTransactionManager transactionManager = new HibernateTransactionManager();
        transactionManager.setSessionFactory(sessionFactory().getObject());
        return transactionManager;
    }


    @Override
    public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
        // Simple strategy: only path extension is taken into account
        configurer.favorPathExtension(true).
            ignoreAcceptHeader(true).
            useJaf(false).
            defaultContentType(MediaType.TEXT_HTML).
            mediaType("html", MediaType.TEXT_HTML).
            mediaType("xml", MediaType.APPLICATION_XML).
            mediaType("json", MediaType.APPLICATION_JSON);
    }
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/img/**").addResourceLocations("/WEB-INF/img/*");
        registry.addResourceHandler("/css/**").addResourceLocations("/WEB-INF/css/*");
        registry.addResourceHandler("/js/**").addResourceLocations("/WEB-INF/js/*");
        registry.addResourceHandler("/lib/**").addResourceLocations("/WEB-INF/lib/*");
    }
}

ThymeleafConfig

package com.derp.common.init;


import nz.net.ultraq.thymeleaf.LayoutDialect;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.thymeleaf.spring4.SpringTemplateEngine;
import org.thymeleaf.spring4.view.ThymeleafViewResolver;
import org.thymeleaf.templateresolver.ServletContextTemplateResolver;

@Configuration 
public class ThymeleafConfig {

    @Bean 
    public ServletContextTemplateResolver templateResolver() {
        ServletContextTemplateResolver resolver = new ServletContextTemplateResolver();
        resolver.setPrefix("/WEB-INF/view/");
        resolver.setSuffix(".html");
        resolver.setTemplateMode("HTML5");
        resolver.setOrder(1);
        resolver.setCacheable(false);
        return resolver;
    }

    @Bean 
    public SpringTemplateEngine templateEngine() {
        SpringTemplateEngine templateEngine = new SpringTemplateEngine();
        templateEngine.setTemplateResolver(templateResolver());
        templateEngine.addDialect(new LayoutDialect());
        //templateEngine.addDialect(new SpringStandardDialect());
        return templateEngine;
    }

    @Bean 
    public ThymeleafViewResolver thymeleafViewResolver() {
        ThymeleafViewResolver resolver = new ThymeleafViewResolver();
        resolver.setTemplateEngine(templateEngine());
        resolver.setCharacterEncoding("UTF-8");
        return resolver;
    }

}

修改

在控制器上使用此方法时,没有utf-8字符 的控制器

@RequestMapping(value="/test", method=RequestMethod.PUT)
@ResponseBody
public String ajaxTest() {
    return "Characters test: ęółąśżźćń";
}

和javasscript ajax方法

  $(document).ready(function() {
      $('h1').click(function() {
          $.ajax({
              type: "PUT",
              url: "/derp/procedury/test",
              data: "none",
              success: function (response, status, xhr) {
                  showNotifications(status, xhr.responseText);
              },
              error: function (response, status, xhr) {
                  showNotifications('error', JSON.stringify(response));
                  showNotifications('error', status);
                  showNotifications('error', xhr);
              }
          });
      });

我得到的结果是:

  Characters test: ?�???????

请提供一些有用的建议。提前谢谢。

2 个答案:

答案 0 :(得分:0)

我遇到了同样的问题,我已将以下过滤器配置添加到MyServletInitializer 并且没有问题(在我的情况下,其他配置不起作用):

public class MyServletInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

    ....

    @Override
    protected Filter[] getServletFilters() {
        CharacterEncodingFilter filter = new CharacterEncodingFilter();
        filter.setEncoding("UTF-8");
        filter.setForceEncoding(true);
        return new Filter[]{filter};
    } 

    ....

}

答案 1 :(得分:0)

工作解决方案:

要在初始化程序类中添加的代码:

private void registerCharachterEncodingFilter(ServletContext aContext) {
    CharacterEncodingFilter cef = new CharacterEncodingFilter();
    cef.setForceEncoding(true);
    cef.setEncoding("UTF-8");
    aContext.addFilter("charachterEncodingFilter", cef).addMappingForUrlPatterns(null ,true, "/*");
}

然后在初始化程序中调用它 onStartup方法 使用ServletContext:

registerCharachterEncodingFilter