丟掉xml使用JavaConfig配置Spring

火堯發表於2017-10-11

Spring JavaConfig

最近擼了一遍Spring action 4,發現裡面講的都不再使用xml檔案來配置spring,全都採用Java程式碼來配置.

用Java程式碼配置的話,感覺要比xml更便於維護,而且用程式碼肯定比xml更爽嘛

下面來一步步用JavaConfig搭一個Spring工程

那在用xml配置的時候,專案都是從載入web.xml檔案再掃描到各種spring-*.xml檔案

那不用xml檔案,專案從哪裡啟動呢?

那就要靠這個類了,AbstractAnnotationConfigDispatcherServletInitializer,這個就相當於web.xml啦,在這裡面可以配置上下文,DispatcherServlet,過濾器等等bean;

首先我們先建立一個類SpittrWebAppInitialzer

package com.fireyao;

import org.springframework.web.filter.CharacterEncodingFilter;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;

import javax.servlet.Filter;

public class SpittrWebAppInitialzer extends AbstractAnnotationConfigDispatcherServletInitializer {
    /**
     * 配置root上下文,如Jpa資料來源等等的配置
     * @return
     */
    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class[]{RootConfig.class};
    }

    /**
     * 配置dispatcher servlet
     * @return
     */
    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class[]{WebConfig.class};
    }

    /**
     * 將DispatcherServlet對映到 "/"
     * 指定開始被servlet處理的url,配置從/開始  
     * @return
     */
    @Override
    protected String[] getServletMappings() {
        return new String[]{"/"};
    }

    /**
     * 這裡註冊的所有過濾器,都會對映到DispatcherServlet
     * 就是說這裡的過濾器過濾規則是 /*
     * 所有的請求都會先到這裡註冊的過濾器中
     *
     * @return
     */
    @Override
    protected Filter[] getServletFilters() {
        return new Filter[]{
                new CharacterEncodingFilter("UTF-8", true)
        };
    }
}複製程式碼

SpittrWebAppInitialzer類裡面載入了RootConfigWebConfig兩個配置類,

再建立這兩個類以及相關的配置(以下省略package和import)

RootConfig

/**
 * 相當於applicationContext.xml
 */
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(basePackages = {"com.fireyao.repository"},
        entityManagerFactoryRef = "entityManagerFactory",
        transactionManagerRef = "transactionManager")
@PropertySource(value = {"classpath:db.properties", "classpath:hibernate.properties", "classpath:app.properties"})
@ComponentScan(basePackages = "com.fireyao",
        excludeFilters = {
                @ComponentScan.Filter(
                        type = FilterType.ANNOTATION, value = EnableWebMvc.class
                )})
@EnableAspectJAutoProxy(proxyTargetClass = true)
/**
 *   proxyTargetClass = true ==> 使用cglib代理
 *   proxyTargetClass = false(預設) ==> 使用JDK代理
 */
public class RootConfig {


    @Value(value = "${db.driver:org.postgresql.Driver}")
    private String DRIVERCLASSNAME;

    @Value("${db.username}")
    private String USERNAME;

    @Value("${db.password}")
    private String PASSWORD;

    @Value("${db.jdbcURL}")
    private String URL;

    @Value("${hibernate.hbm2dll.create_namespaces}")
    private String CREATE_NAMESPACES;

    @Value("${hibernate.hbm2ddl.auto}")
    private String HBM2DDL_AUTO;

    @Value("${hibernate.show_sql}")
    private String SHOW_SQL;

    @Value("${hibernate.format_sql}")
    private String FORMAT_SQL;

    @Value("${hibernate.generate_statistics}")
    private String GENERATE_STATISTICS;

  /**
   * 配置資料來源
   */
    @Bean(name = "dataSource")
    public DruidDataSource dataSource() {
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setDriverClassName(DRIVERCLASSNAME);
        dataSource.setUrl(URL);
        dataSource.setUsername(USERNAME);
        dataSource.setPassword(PASSWORD);

        /*  配置初始化大小、最小、最大*/
        dataSource.setInitialSize(5);
        dataSource.setMinIdle(5);
        dataSource.setMaxActive(20);
        /* 配置獲取連線等待超時的時間*/
        dataSource.setMaxWait(30000);
        /*配置間隔多久才進行一次檢測,檢測需要關閉的空閒連線,單位是毫秒*/
        dataSource.setTimeBetweenEvictionRunsMillis(60000);
        /*配置一個連線在池中最小生存的時間,單位是毫秒*/
        dataSource.setMinEvictableIdleTimeMillis(300000);
        /*申請連線的時候檢測,如果空閒時間大於timeBetweenEvictionRunsMillis,執行validationQuery檢測連線是否有效*/
        dataSource.setTestWhileIdle(true);
        dataSource.setValidationQuery("select 1");
        return dataSource;
    }

    @Bean
    public HibernateJpaVendorAdapter hibernateJpaVendorAdapter() {
        return new HibernateJpaVendorAdapter();
    }

    @Bean(name = "entityManagerFactory")
    public LocalContainerEntityManagerFactoryBean entityManagerFactory(DruidDataSource dataSource,HibernateJpaVendorAdapter hibernateJpaVendorAdapter) {
        LocalContainerEntityManagerFactoryBean entityManagerFactory = new LocalContainerEntityManagerFactoryBean();
        entityManagerFactory.setDataSource(dataSource);
        entityManagerFactory.setJpaVendorAdapter(hibernateJpaVendorAdapter);
        entityManagerFactory.setPackagesToScan("com.fireyao.domain");

        /*指定JPA屬性;如Hibernate中指定是否顯示SQL的是否顯示、方言等*/
        Map<String, Object> jpaProp = new HashMap();
        jpaProp.put("hibernate.dialect", new PostgisDialect());
        jpaProp.put("hibernate.hbm2ddl.auto", HBM2DDL_AUTO);
        jpaProp.put("hibernate.show_sql", SHOW_SQL);
        jpaProp.put("hibernate.generate_statistics", GENERATE_STATISTICS);
        jpaProp.put("hibernate.format_sql", FORMAT_SQL);
        jpaProp.put("hibernate.hbm2dll.create_namespaces", CREATE_NAMESPACES);
        entityManagerFactory.setJpaPropertyMap(jpaProp);
        return entityManagerFactory;
    }

    /**
     * 事務管理器
     *
     * @param entityManagerFactory
     * @return
     */
    @Bean(name = "transactionManager")
    public JpaTransactionManager transactionManager(LocalContainerEntityManagerFactoryBean entityManagerFactory) {
        return new JpaTransactionManager(entityManagerFactory.getObject());
    }
}複製程式碼

WebConfig

/**
 * 相當於springmvc-servlet.xml
 */
@Configuration
@EnableWebMvc//啟用spring mvc
@ComponentScan(basePackages = "com.fireyao.controller") //啟用元件掃描
public class WebConfig extends WebMvcConfigurerAdapter {


    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter();
        FastJsonConfig fastJsonConfig = new FastJsonConfig();
        fastJsonConfig.setSerializerFeatures(SerializerFeature.PrettyFormat);
        //處理中文亂碼問題
        List<MediaType> fastMediaTypes = new ArrayList<>();
        fastMediaTypes.add(MediaType.APPLICATION_JSON_UTF8);
        fastConverter.setSupportedMediaTypes(fastMediaTypes);
        fastConverter.setFastJsonConfig(fastJsonConfig);
        converters.add(fastConverter);
    }


    /**
     * Thymeleaf檢視解析器
     *
     * @param springTemplateEngine
     * @return
     */
    @Bean
    public ThymeleafViewResolver viewResolver(SpringTemplateEngine springTemplateEngine) {
        ThymeleafViewResolver viewResolver = new ThymeleafViewResolver();
        viewResolver.setTemplateEngine(springTemplateEngine);
        viewResolver.setCharacterEncoding("utf-8");
        return viewResolver;
    }

    /**
     * 模版引擎
     *
     * @param iTemplateResolver
     * @return
     */
    @Bean
    public SpringTemplateEngine templateEngine(ITemplateResolver iTemplateResolver) {
        SpringTemplateEngine templateEngine = new SpringTemplateEngine();
        templateEngine.setTemplateResolver(iTemplateResolver);
        return templateEngine;
    }

    /**
     * Thymeleaf3.0之後
     * Thymeleaf模版解析器
     *
     * @return
     */
    @Bean
    public ITemplateResolver iTemplateResolver() {
        SpringResourceTemplateResolver templateResolver = new SpringResourceTemplateResolver();
        templateResolver.setTemplateMode("HTML5");
        templateResolver.setPrefix("/WEB-INF/templates/");
        templateResolver.setSuffix(".html");
        templateResolver.setTemplateMode("HTML");
        templateResolver.setCharacterEncoding("utf-8");

        templateResolver.setCacheable(false);
        return templateResolver;
    }

    /**
     * Thymeleaf3.0之前
     * Thymeleaf模版解析器
     * @return
     */
  /*  @Bean
    public TemplateResolver templateResolver() {
        TemplateResolver resolver = new ServletContextTemplateResolver();
        resolver.setPrefix("/WEB-INF/VIEWS/");
        resolver.setSuffix(".html");
        resolver.setTemplateMode("HTML5");
        resolver.setCacheable(false);
        return resolver;
    }*/


    /**
     * 配置靜態資源的處理
     * 要求DispatcherServlet將對靜態資源的請求轉發到Servlet容器中預設的Servlet上
     * 而不是使用DispatcherServlet本身來處理此類請求。
     *
     * @param configurer
     */
    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
        configurer.enable();
    }

    /**
     * 配置檢視解析器
     * ==> JSP檢視
     *
     * @return
     */
    /*@Bean
    public ViewResolver viewResolver() {
        InternalResourceViewResolver resolver = new InternalResourceViewResolver();
        resolver.setPrefix("/WEB-INF/views/");
        resolver.setSuffix(".jsp");
        resolver.setExposeContextBeansAsAttributes(true);
        return resolver;
    }*/
}複製程式碼

@Configuration 標註為配置類

@EnableTransactionManagement註解開啟註解式事務的支援。

@EnableJpaRepositories註解開啟對Spring Data JPA Repostory的支援

@PropertySource 掃面db.properties等配置檔案,可以用@Value註解取到properties中的值

@ComponentScan 配置掃描類包 相當於<context:component-scan base-package="com.fireyao"/>

@EnableAspectJAutoProxy 表示開啟AOP代理自動配置

@EnableAspectJAutoProxy中proxyTargetClass屬性
​ proxyTargetClass = true ==> 使用cglib代理
​ proxyTargetClass = false(預設) ==> 使用JDK代理

那spring最基本的JavaConfig就這樣了.

是不是看上去很舒服,果然還是要用Java程式碼才爽.

原文連結:丟掉xml使用JavaConfig配置Spring | 火堯

相關文章