使用Spring4.x 搭建注解式 Spring MVC + JPA 项目

使用Spring4.x 搭建注解式 Spring MVC + JPA 项目

在我们使用Spring3.x 系列或者是更早的系列中,大都是通过xml文件来实现配置的,大量的配置文件,和繁琐的配置。
让开发特别的不爽,在4.x 系列出来后,改变了这一状况,小编也很兴奋,就搭了一个项目体验了一下。

假设我们的基础包名为:
com.mycompany.myapp

那么小编喜欢把启动class 放在 :
com.mycompany.myapp.config 下面。

首先 基础环境必须是支持Servlet3及以上,小编使用的 Tomcat8 。
(注:在Servlet3 已经可以通过实现ServletContainerInitializer接口来配置 Filter,Servlet 和 Listener ,
Spring 进行了一些封装实现WebApplicationInitializer接口也可以达到这一效果。)

小编这里是通过三个java文件来实现的。
1。ApplicationBoot (启动类)
2。MvcConfig (mvc 的配置类)
3。RootConfig (组件配置类)

先看 ApplicationBoot 继承的是AbstractAnnotationConfigDispatcherServletInitializer
(如果需要自己控制ApplicationContext的实现类型也可以继承AbstractDispatcherServletInitializer)

public class ApplicationBoot extends 
                AbstractAnnotationConfigDispatcherServletInitializer{

    /**
     * 该方法定义的是全局的 applicationContext
     * 在初始化时需要去扫描哪些带注解(如:@Configuration)的类
     */
    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class<?>[]{RootConfig.class};
    }

    /**
     * 该方法定义的时Servlet级别的applicationContext
     * 在初始化时需要去扫描哪些带注解(如:@Configuration)的类
     */
    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class<?>[]{MvcConfig.class};
    }

    /**
     * 定义 DispatcherServlet 拦截的路径
     */
    @Override
    protected String[] getServletMappings() {
        return new String[]{"/"};
    }

}

那么全局的 ApplicationContext(root) 和 Servlet级的 ApplicationContext 有什么区别呢?
1.他们是父子关系,root 是 Servlet级的 父环境,也就是说 Servlet级的环境中可以访问到root环境中的实例,反之则不成立
2.项目中有几个Servlet就可以对应有几个ApplicationContext,他们都共享一个root 达到了多Servlet的实例共享

那么我们怎么来分配实例具体由哪个环境来持有呢,通常我们可以把Controller层 交给Servlet级的环境来持有,将Dao和Service层交于root来持有,当然面对项目中只有一个Servlet的情况下也可以不配置root环境(那么就需要继承AbstractDispatcherServletInitializer来精确配置)

好我们来看 MvcConfig 类

@EnableWebMvc
@Configuration
@ComponentScan("com.mycompany.myapp.controller")
public class MvcConfig extends WebMvcConfigurerAdapter{

    /**
     * 设置静态文件的映射关系
     */
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
    }

    /**
     * 配置视图处理技术,这里使用了jsp方式
     */
    @Override
    public void configureViewResolvers(ViewResolverRegistry registry) {
        registry.jsp("/WEB-INF/views",".jsp");
    }

    /**
     * 配置使用 服务器默认Servlet 来处理静态资源。DispatcherServlet 我们设置了拦截所以,所以在找静态资源的选择让default 去做。
     */
    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
        configurer.enable();
    }

    /**
     * 添加拦截器
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addWebRequestInterceptor(openEntityManagerInViewInterceptor());
    }

    /**
     * 使用JPA  懒加载数据容易出现 no session 问题,可以加这个拦截器,
     * 相对使用Filter 来说, 这个数据库事物是在找到相应的处理者之后才会打开
     */
    @Bean
    public OpenEntityManagerInViewInterceptor openEntityManagerInViewInterceptor(){
        return new OpenEntityManagerInViewInterceptor();
    }

}

好再看一下 RootConfig类

@Configuration
@EnableTransactionManagement
@ComponentScan({"com.mycompany.myapp.service"
                    ,"com.mycompany.myapp.dao"})
public class RootConfig {

    /**
     * 配置项目的配置文件信息
     */
    @Bean
    public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
        PropertySourcesPlaceholderConfigurer config  = new PropertySourcesPlaceholderConfigurer();
        config.setLocation(new ClassPathResource("META-INF/system-cnf.properties"
                                            , AbstractMvcConfigurer.class.getClassLoader()));

        return config;
    }


    /**
     * 小编比较喜欢通过配置文件来管理数据配置信息,而没有把这部分信息配置在 persistence.xml中
     */
    @Bean
    public DataSource  dataSource(
            @Value("${db.url}")String url,
            @Value("${db.user}")String username,
            @Value("${db.password}")String password,
            @Value("${db.driver}")String driverClassName
            ){


        DriverManagerDataSource dataSource = new DriverManagerDataSource(url, username, password);
        dataSource.setDriverClassName(driverClassName);

        return dataSource;
    }

    /**
     * JPA 实体管理工厂
     */
    @Bean
    public LocalContainerEntityManagerFactoryBean  entityManagerFactory(DataSource dataSource){

        LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();

        factory.setPersistenceUnitName("PU");
        factory.setDataSource(dataSource);

        return factory;
    }

    /**
     * JPA 事物处理
     */
    @Bean
    public JpaTransactionManager  jpaTransactionManager(EntityManagerFactory  factory){
        JpaTransactionManager  manager = new JpaTransactionManager();

        manager.setEntityManagerFactory(factory);

        return manager;
    }
    /**
     * 事物异常处理
     */
    @Bean
    public PersistenceExceptionTranslationPostProcessor  persistenceExceptionTranslationPostProcessor(){
        return new PersistenceExceptionTranslationPostProcessor();
    }
}

到这里我们还需要在 META-INF 下面放置
persistence.xml 文件
和 system-cnf.properties 的配置文件。

事务操作 仅需要在 相应方法上添加@Transactional 即可,希望小编的分享对您有所帮助。

最后贴上小编的 pom 的 jar 依赖吧。

    <properties>
        <org.springframework-version>4.1.7.RELEASE</org.springframework-version>
        <org.aspectj-version>1.6.10</org.aspectj-version>
        <org.slf4j-version>1.6.6</org.slf4j-version>
    </properties>

<dependencies>
     <dependency>
              <groupId>commons-io</groupId>
                    <artifactId>commons-io</artifactId>
                         <version>2.1</version>
             </dependency>

    <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.6.0</version>
        </dependency>

    <!-- Spring -->
        <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-tx</artifactId>
                <version>${org.springframework-version}</version>
        </dependency>
         <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-orm</artifactId>
            <version>${org.springframework-version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${org.springframework-version}</version>
            <exclusions>
                <!-- Exclude Commons Logging in favor of SLF4j -->
                <exclusion>
                    <groupId>commons-logging</groupId>
                    <artifactId>commons-logging</artifactId>
                 </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${org.springframework-version}</version>
        </dependency>

        <!-- AspectJ -->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
            <version>${org.aspectj-version}</version>
        </dependency>   

        <!-- Logging -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>${org.slf4j-version}</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>jcl-over-slf4j</artifactId>
            <version>${org.slf4j-version}</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>${org.slf4j-version}</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.15</version>
            <exclusions>
                <exclusion>
                    <groupId>javax.mail</groupId>
                    <artifactId>mail</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>javax.jms</groupId>
                    <artifactId>jms</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>com.sun.jdmk</groupId>
                    <artifactId>jmxtools</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>com.sun.jmx</groupId>
                    <artifactId>jmxri</artifactId>
                </exclusion>
            </exclusions>
            <scope>runtime</scope>
        </dependency>

        <!-- hibernate -->
        <dependency>
              <groupId>org.hibernate</groupId>
              <artifactId>hibernate-entitymanager</artifactId>
              <version>5.0.3.Final</version>
              <scope>compile</scope>
            </dependency>

            <dependency>
                <groupId>org.hibernate</groupId>
                <artifactId>hibernate-validator</artifactId>
                <version>5.2.2.Final</version>
            </dependency>


        <!-- @Inject -->
        <dependency>
            <groupId>javax.inject</groupId>
            <artifactId>javax.inject</artifactId>
            <version>1</version>
        </dependency>

        <!-- Servlet -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>2.5</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>jsp-api</artifactId>
            <version>2.1</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>




        <!-- Test -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.7</version>
            <scope>test</scope>
        </dependency>        
    </dependencies>
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值