纯手工系列--零配置实现Spring MVC+Spring Data JPA

纯手工系列–零配置实现Spring MVC+Spring Data JPA

最近忙于一个项目,将以前Spring boot搭建的系统,降为Spring传统的一个系统。事情的缘由是因为我们发现Spring boot搭建的系统出现了几次莫名奇妙的错误,然后又莫名奇妙的好了。后来我们又在每个环节做了单元测试,也没有出现问题。但是问题必须要解决啊,所以小组决定改成传统的Spring,方便查找到问题的所在,好除去错误。这里又出现了一个问题,就是按照原来的配置方法搭建Spring,不能真正的体现现在Spring boot零配置的优势,也不能帮我们理解Spring boot隐藏的一些细节,所以我们决定使用JavaConfig的方式来配置我们的系统。下面就进入主题。
作者使用的开发环境是Linux,使用的IDE是NetBeans8.2,但是这里将使用纯手工进行,但首先需要大家把JDK1.8与Maven的环境变量配置好,环境配置这里就不多说了,网上有很多的资料。我们使用Maven的命令创建一个web项目命令如下:

mvn archetype:create
-DgrounpId=packageName //项目的包名
-DartifactId=appName //项目的名称
-DarchetypeArtifactId=maven-archetype-webapp //告诉Maven创建的是一个Web项目

创建好项目后我们需要添加依赖,打开pom.xml文件。这里只给出依赖的部分。代码如下:

<dependencies>
<!--后面使用WebSocket-->
        <dependency>
            <groupId>javax</groupId>
            <artifactId>javaee-web-api</artifactId>
            <version>7.0</version>
            <scope>provided</scope>
        </dependency>
<!--单元测试-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
        <!--spring基于注释的校验机制 支持J2EE的JSR303规范 -->
        <dependency>
            <groupId>javax.validation</groupId>
            <artifactId>validation-api</artifactId>
            <version>1.1.0.Final</version>
        </dependency>
        <!-- hibernate基于注释的校验,也支持J2EE的JSR303规范 -->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-validator</artifactId>
            <version>5.2.4.Final</version>
            <type>jar</type>
        </dependency>
        <!--日志库-->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.21</version>
        </dependency>
        <!--spring javaConfig的主要使用的依赖-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>4.3.3.RELEASE</version>
        </dependency>
      <!--spring对事务的处理依赖-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
            <version>4.3.3.RELEASE</version>
        </dependency>
      <!--java持久化依赖-->
        <dependency>
            <groupId>javax.persistence</groupId>
            <artifactId>persistence-api</artifactId>
            <version>1.0.2</version>
        </dependency>
      <!--阿里的数据库连接池-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.0.26</version>
        </dependency>
      <!-- 这里需要注意:这个适配spring-tx依赖的 -->
        <dependency>
            <groupId>org.lucee</groupId>
            <artifactId>commons-collections</artifactId>
            <version>3.2.1</version>
        </dependency>
      <!-- javax.servlet只是在编译时使用 -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
        </dependency>
        <!--spring mvc-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>4.3.3.RELEASE</version>
        </dependency>
        <!--支持JSTL标签-->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>
        <!--spring 测试-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>4.3.3.RELEASE</version>
            <scope>test</scope>
            <type>jar</type>
        </dependency>
        <!--我们通过javaConfig来实现它的@EntityScan
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-autoconfigure</artifactId>
            <version>1.4.1.RELEASE</version>
            <type>jar</type>-->
        </dependency>
      <!--这里偷一个懒,不然还要添加hibernate-core、spring-aspect、hibernate-entitymanager、javax.transaction-api等一系列的依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
            <version>1.4.1.RELEASE</version>
        </dependency>
        <!--之前项目使用的Json库,延续以前的,建议新项目中不使用它,使用jackson之类的,听说java 9自带-->
        <dependency>
            <groupId>net.sf.json-lib</groupId>
            <artifactId>json-lib</artifactId>
            <version>1.1</version>
            <type>jar</type>
            <classifier>jdk15</classifier>
        </dependency>
        <!--mysql驱动-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.39</version>
        </dependency>
      <!-- commons工具类 -->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.3.2</version>
        </dependency>

    </dependencies>

接下来就是编写java类来配置Spring了,首先,我们使用servlet3.0的特性,通过java类来启动spring的服务,代码如下:


//文件名:WebInitializer.java

//表明这个类同时还是一个控制器
@RestController
//这里的package.component"根据自己的实际情况填写
@ComponentScan("package.component")
//通过WebApplicationinitializer表示可以在web应用程序启动时被加载
public class WebInitializer implements WebApplicationInitializer{

    @Override
    public void onStartup(ServletContext sc) throws ServletException {
        AnnotationConfigWebApplicationContext ctx=new
            AnnotationConfigWebApplicationContext();
        //加载配置文件类,这里与xml配置是对应的,每个被加载的类需要使用@Configuration注解进行标注
        //WebConfig.class是对spring MVC的配置
        //JpaConfiguration是对spring data jpa的配置
        ctx.register(WebConfig.class,JpaConfiguration.class);
        //增加一个跨域访问的过滤器
        sc.addFilter("CorsFilter", CorsFilter.class);
        ctx.setServletContext(sc);

        //动态加载DispatcherServlet,它时spring mvc的核心
        Dynamic springmvc=sc.addServlet("springmvc", new DispatcherServlet(ctx));
        springmvc.addMapping("/");
        springmvc.setLoadOnStartup(1);
        springmvc.setMultipartConfig(new MultipartConfigElement("/tmp/uploads"));
    }

下面来看看,WebConfig.java和JpaConfiguration.java这个两个文件的说明

//文件名:WebConfig.java

//告诉spring我是一个配置类
@Configuration
//使用Spring MVC功能
@EnableWebMvc
//请按实际情况进行配
@ComponentScan("package.component.controller")
public class WebConfig extends WebMvcConfigurerAdapter {


//创建一个spring MVC视图解析器的Bean,当Controller将请求处理结果放入到ModelAndView中以后,DispatcherServlet会根据ModelAndView选择合适的视图进行渲染
  @Bean
  public ViewResolver viewResolver() {
    InternalResourceViewResolver resolver = new InternalResourceViewResolver();
    resolver.setPrefix("/WEB-INF/views/");
    resolver.setSuffix(".jsp");
    return resolver;
  }

//通过默认的servlet容器处理静态资源的请求
  @Override
  public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
    configurer.enable();
  }

//增加静态资源的配置
  @Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
  registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
  registry.addResourceHandler("/web/**").addResourceLocations("/WEB-INF/web/");

//文件上传表单的视图解析器
@Bean
  public MultipartResolver multipartResolver()throws IOException{
      return new StandardServletMultipartResolver();
  }
//这个方法一般用来处理中文乱码的问题
  @Override
  public void configureMessageConverters(List<HttpMessageConverter<?>> converters){
      StringHttpMessageConverter converter =new StringHttpMessageConverter();
      MediaType mediaType1=new MediaType("data", "json", Charset.forName("UTF-8"));
      MediaType mediaType2=new MediaType("text", "html", Charset.forName("UTF-8"));
            List<MediaType> mtList=new ArrayList<>();
      mtList.add(mediaType1);
      mtList.add(mediaType2);
      converter.setSupportedMediaTypes(mtList);
      converters.add(converter);
  }
//文件名:JpaConfiguration.java
//最高优先级
@Order(Ordered.HIGHEST_PRECEDENCE)
//告诉spring我是一个配置类
@Configuration
//开启事务管理
@EnableTransactionManagement(proxyTargetClass = true)
//使用这个注释,开启spring data jpa的功能,并要告诉要使用那个包的文件
@EnableJpaRepositories(basePackages = "package.**.repository")
//获得在resources文件夹下面的datasource.properties文件
@PropertySource("classpath:datasource.properties")
public class JpaConfiguration implements EnvironmentAware{
     private Environment env;
     @Bean
    public DataSource dataSource() {
    //通过数据库线程池创建数据库连接,这里使用的是阿里的 DruidDataSource
    //它提供了一个简单的后台监视功能
    //这里,没有进行过多的配置,在spring boot中可以通过xml或者yml文件进行配置
        DruidDataSource dataSource = new DruidDataSource();

        dataSource.setDriverClassName(env.getProperty("jdbc.driverClassName"));
        dataSource.setUrl(env.getProperty("jdbc.url"));
        dataSource.setUsername(env.getProperty("jdbc.username"));
        dataSource.setPassword(env.getProperty("jdbc.password"));

        return dataSource;
    }
  /**
  如果Spring部署在J2EE的应用服务器中,Spring可能已经创建好EntityManagerFactory并将其置于JNDI中使用,这种情况可使用JNDI来获取对EntityManagerFactory的引用
      @Bean
      @Profile("javaee")
      public JndiObjectFactoryBean dataSource() throws IllegalArgumentException {
          JndiObjectFactoryBean dataSource = new JndiObjectFactoryBean();
          dataSource.setExpectedType(DataSource.class);
          dataSource.setJndiName(env.getProperty("jdbc.jndiDataSource"));
          return dataSource;
      }
  **/

  //相当于在文件顶部使用Spring boot中的@EntityScan(basePackages = "package.**.entities")注释
    @Bean(name = "entityManagerFactory")
    public LocalContainerEntityManagerFactoryBean entityManagerFactory(){
      //LocalContainerEntityManagerFactoryBean说明我们仅使用JPA进行数据访问
        LocalContainerEntityManagerFactoryBean entityManagerFactoryBean=new LocalContainerEntityManagerFactoryBean();
        entityManagerFactoryBean.setDataSource(dataSource());
        entityManagerFactoryBean.setPackagesToScan("package.**.entities");
        entityManagerFactoryBean.setJpaVendorAdapter(jpaVendorAdapter());
        return entityManagerFactoryBean;
    }

    @Bean
    public JpaVendorAdapter jpaVendorAdapter(){
      //使用Hibernate的数据库适配器
      //当然还要其他的例如EclipseLinkJpaVendorAdapter、OpenJpaVendorAdapter、TopLinkJpaVendorAdapter

         HibernateJpaVendorAdapter hibernateJpaVendorAdapter = new HibernateJpaVendorAdapter();
        hibernateJpaVendorAdapter.setShowSql(false);
        hibernateJpaVendorAdapter.setGenerateDdl(true);
        hibernateJpaVendorAdapter.setDatabase(Database.MYSQL);
        return hibernateJpaVendorAdapter;
    }

    //异常处理
    @Bean
    PersistenceExceptionTranslationPostProcessor persistenceExceptionTranslationPostProcessor(){
        return new PersistenceExceptionTranslationPostProcessor();
    }

    //属性管理API,可实现不同数据源的无缝切换方便的访问property属性,包含系统属性,环境变量和自定义的。并且是可配置的,可以加入自定义的property,这基于spring使用PropertySources 来管理不同的PropertySource

    @Override
    public void setEnvironment(Environment environment) {
        env = environment;
    }

//对事务的处理
    @Bean(name = "transactionManager")
    public PlatformTransactionManager creaPlatformTransactionManager(EntityManagerFactory entityManagerFactory){
        JpaTransactionManager transactionManager=new JpaTransactionManager();
        transactionManager.setEntityManagerFactory(entityManagerFactory);
        return transactionManager;
    }
}

在文件JpaConfiguration.java中我们提到了
@EnableJpaRepositories(basePackages = “package.**.repository”),来开启实现JPA持久化的功能,使用它的好处就是我们不用在写实现类了,直接提供接口进行,剩下的事情由spring来完成。这里假设你已经写好了一个User的实体类,下面看一个例子,还说明它是怎么工作的:

//文件名称:UserRepository.java


//告诉spring 这个类用于数据访问组件
@Repository
public interface UserRepository extends JapRepository<User,Integer>{

}

好了,这样就实现了存取数据库的功能,现在就可以对数据库进行增删改查、进行分页查询和指定排序等操作了,是不是很方便。
最后我们通过给个UserController类使用Spring MVC来时模拟实现RESTful服务,代码如下:

//文件名称:UserController.java

@RestController
@RequestMapping({"/user"})
public class UserController {
    private static Logger logger = LoggerFactory.getLogger(LoginController.class);

    //进行自动状态之前的JPA
    @Autowired
    UserRepository userRepository;

//设置请求的路径与请求的方法
  @RequestMapping(value = "/getUserInfo",method = RequestMethod.GET)
  public String getUserInfo() throws  Exception{
      List<User> users=userRepository.findAll();
      JSONArray jsonArray = JSONArray.fromObject(users);
      return  jsonArray.toString();
  }

这样一个完整的零配置实现Spring MVC+Spring Data JPA就可以工作了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值