SpringBoot + MyBatis 重构 Web 应用

来源:互联网 发布:淘宝买家秀卖家秀搞笑 编辑:程序博客网 时间:2024/05/23 11:23

前言

 项目构建的时候是截取了另一个项目的部分功能形成的,截取出的功能代码少但项目结构比较复杂,依赖严重 。改写过后,不少代码成了”鸡肋”,搞不清楚谁是谁 。

 web/controller在一块,dao/domain独占一方 ; junit在6个pom。xml中出现了4次,版本还不一样 ; spring/mybatis的配置文件也有好几个,里面的xml代码也是长而杂 。

Clean Code,之前专门买了一本书,讲述代码清洁之道 。 整洁的代码对项目的开发效率至关重要,宏观一点,项目结构的清晰,也对后续的开发有所帮助。

SpringBoot

  GitHub示例 Anddd7/SSM-SpringBoot-Starter`

 前一段时间还没正式学习使用Spring时就听说了SpringBoot,还记得学生时代配置SSH,满篇的xml简直是童年阴影(- -如果xml节点还没对齐的话, 那 ……)。
 SpringBoot可以达到0配置 (- -当然这是不可能的) 快速启动一个Spring应用,对简化配置有显著提升。

准备 - pom.xml

  • 首先还是从Maven配置入手
<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0"         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">    <modelVersion>4.0.0</modelVersion>    <groupId>anddd7.boot4ssh</groupId>    <artifactId>SSM-SpringBoot-Starter</artifactId>    <version>1.0-SNAPSHOT</version>    <packaging>jar</packaging>    <!--官方推荐使用 spring-boot-starter-parent 包括一些预设配置:        1.使用java6编译级别<java.version>1.8</java.version>        2.使用utf-8编码<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>        3.实现了通用的测试框架 (JUnit, Hamcrest, Mockito).        4.智能资源过滤        5.智能的插件配置(exec plugin, surefire, Git commit ID, shade).        不继承也可使用dependcy引入 ,因为scope是import,不再允许在<properties>覆盖第三方包版本        如果要使用其他版本,需要在上面的前面添加一个完整的dependency        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-dependencies</artifactId>            <version>1.4.0.RELEASE</version>            <type>pom</type>            <scope>import</scope>        </dependency>    -->    <parent>        <groupId>org.springframework.boot</groupId>        <artifactId>spring-boot-starter-parent</artifactId>        <version>RELEASE</version>        <relativePath/>    </parent>    <properties>        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>        <java.version>1.8</java.version>        <mybatis.version>3.4.2</mybatis.version>        <mybatis-spring.version>1.3.1</mybatis-spring.version>        <spring-boot.version>1.4.4.RELEASE</spring-boot.version>    </properties>    <!-- 对应模块的starter包含常用依赖 ,例如starter-web{spring-web,spring-mvc}-->    <dependencies>        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-web</artifactId>        </dependency>        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-dependencies</artifactId>            <version>${spring-boot.version}</version>            <type>pom</type>            <scope>import</scope>        </dependency>        <dependency>            <groupId>org.mybatis</groupId>            <artifactId>mybatis</artifactId>            <version>${mybatis.version}</version>        </dependency>        <dependency>            <groupId>org.mybatis</groupId>            <artifactId>mybatis-spring</artifactId>            <version>${mybatis-spring.version}</version>        </dependency>        <!-- springboot+mybatis官方连接包 -->        <dependency>            <groupId>org.mybatis.spring.boot</groupId>            <artifactId>mybatis-spring-boot-autoconfigure</artifactId>            <version>1.1.1</version>        </dependency>        <dependency>            <groupId>org.mybatis.spring.boot</groupId>            <artifactId>mybatis-spring-boot-starter</artifactId>            <version>1.1.1</version>        </dependency>        <!-- dbcp 数据源 -->        <dependency>            <groupId>commons-dbcp</groupId>            <artifactId>commons-dbcp</artifactId>            <version>1.4</version>        </dependency>        <dependency>            <groupId>mysql</groupId>            <artifactId>mysql-connector-java</artifactId>            <version>5.1.38</version>        </dependency>    </dependencies>    <build>        <plugins>            <!--用于将项目打包成fat jar(executable jar)-->            <plugin>                <groupId>org.springframework.boot</groupId>                <artifactId>spring-boot-maven-plugin</artifactId>            </plugin>            <!-- mybatis 工具 -->            <plugin>                <groupId>org.mybatis.generator</groupId>                <artifactId>mybatis-generator-maven-plugin</artifactId>                <version>1.3.2</version>                <configuration>                    <verbose>true</verbose>                    <overwrite>true</overwrite>                </configuration>            </plugin>        </plugins>    </build></project>
  • 如果使用Jetty ,需要替换掉内置的Tomcat
<dependency>    <groupId>org.springframework.boot</groupId>    <artifactId>spring-boot-starter-web</artifactId>    <version>${spring-boot.version}</version>    <!-- 使用jetty启动 ,先移除tomcat组件 -->    <exclusions>        <exclusion>        <groupId>org.springframework.boot</groupId>        <artifactId>spring-boot-starter-tomcat</artifactId>        </exclusion>    </exclusions></dependency><!-- 添加jetty支持 --><dependency>    <groupId>org.springframework.boot</groupId>    <artifactId>spring-boot-starter-jetty</artifactId>    <version>${spring-boot.version}</version></dependency>

开始 - Application 和 Configuration

引入Maven后 ,准备一个Controller ,然后通过SpringApplication启动Spring就可以使用了 Spring Boot 快速入门 ;需要对Spring进行一些配置的时候(和Mybatis融合、配置数据源等)就需要将Application单独出来 。

  • 1 Spring配置application.xml -> application.yaml
# application.yaml# Server settings (ServerProperties)# 以数据为中心的标记语言 ,易于读写 ,替代xml# springboot 默认是8080端口 ,没有项目地址# 服务器设置server:  port: 8080  address: 127.0.0.1  sessionTimeout: 30  contextPath: /testboot  # 内置tomcat设置tomcat:  accessLogEnabled: false  protocolHeader: x-forwarded-proto  remoteIpHeader: x-forwarded-for  basedir:  backgroundProcessorDelay: 30 # secs
  • 2 设置SpringBoot启动入口
package anddd7.springboot;import anddd7.springboot.configuration.MapperScannerConfiguration;import anddd7.springboot.configuration.MyBatisConfiguration;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.context.annotation.Import;/** * 将spring的启动和配置单独出来 * * @SpringBootApplication 等价于 : * -     @Configuration 通过@ImportResource引入xml文件,@Value读取键值 ,@Bean读取配置的bean实例 * -     @ComponentScan 同xml中的自动扫描组件 * -     @EnableAutoConfiguration * @EnableAutoConfiguration 下包含了一系列自动配置类的清单 ,并按顺序执行 ,在Spring3时代就有@EnableWebMvc注解 * [SpringBoot之@EnableAutoConfiguration原理及自定义扩展 ](http://blog.csdn.net/xiaoyu411502/article/details/52770723) * <p> * MongoAutoConfiguration.class为例 : * -    使用了@Configuration ,标识是一个配置 * -    定义了必要的Mongo对象@Bean * -    使用了@EnableConfigurationProperties ,将application.properties配置文件中的属性映射到Java类中 ,便于使用 * -    @ConditionOnClass表明加载条件 - Mongo.class位于类路径上 * -    @ConditionalOnMissingBean说明Spring Boot仅仅在当前上下文中不存在Mongo对象时,才会实例化一个Bean */@Import({MyBatisConfiguration.class, MapperScannerConfiguration.class})@SpringBootApplicationpublic class Application {    public static void main(String[] args) {        //一键自动启动        SpringApplication.run(Application.class, args);        //配置启动//        SpringApplication app = new SpringApplication();//        app.setBannerMode(Banner.Mode.OFF);        //链式API构建器//        new SpringApplicationBuilder()//                .bannerMode(Banner.Mode.OFF)//                .child(Application.class)//                .run();    }}

依旧是@SpringBootApplication,只不过@Import了一些配置类,使用过xml配置Mybatis和Spring的童鞋对这些类名一定很熟悉,其实就是将原来xml转化为了Java类配置 — @Configuration注解

  • 3.1 数据源
package anddd7.springboot.configuration;import org.apache.commons.dbcp.BasicDataSource;import org.springframework.beans.factory.annotation.Value;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.context.annotation.PropertySource;/** * 对应xml中datasource的配置 */@Configuration@PropertySource("classpath:prop.properties")public class DataSourceConfiguration {    @Value("${jdbc.driver}")    private String driver;    @Value("${jdbc.url}")    private String url;    @Value("${jdbc.username}")    private String username;    @Value("${jdbc.password}")    private String password;    @Value("${jdbc.maxActive}")    private int maxActive;    @Value("${jdbc.maxIdel}")    private int maxIdel;    @Value("${jdbc.maxWait}")    private long maxWait;    @Bean(name = "dataSource")    public BasicDataSource dataSource() {        BasicDataSource dataSource = new BasicDataSource();        dataSource.setDriverClassName(driver);        dataSource.setUrl(url);        dataSource.setUsername(username);        dataSource.setPassword(password);        dataSource.setMaxActive(maxActive);        dataSource.setMaxIdle(maxIdel);        dataSource.setMaxWait(maxWait);        dataSource.setValidationQuery("SELECT 1");        dataSource.setTestOnBorrow(true);        return dataSource;    }}
  • 3.2 prop.properties
#jdbcjdbc.driver=com.mysql.jdbc.Driverjdbc.url=jdbc:mysql://localhost:3306/testdb?useUnicode=true&characterEncoding=utf8jdbc.username=rootjdbc.password=214124jdbc.maxActive=2335jdbc.maxIdel=120jdbc.maxWait=100
  • 4 MapperScanner
package anddd7.springboot.configuration;import org.mybatis.spring.mapper.MapperScannerConfigurer;import org.springframework.boot.autoconfigure.AutoConfigureAfter;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;/** * 扫描mybatis的接口 */@Configuration// 因为这个对象的扫描,需要在MyBatisConfig的后面注入,所以加上下面的注解@AutoConfigureAfter(MyBatisConfiguration.class)public class MapperScannerConfiguration {    @Bean(name = "mapperScannerConfigurer")    public MapperScannerConfigurer mapperScannerConfigurer() {        //创建内置的config        MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer();        //获取之前注入的beanName为sqlSessionFactory的对象        mapperScannerConfigurer.setSqlSessionFactoryBeanName("sqlSessionFactory");        //指定mapper接口的路径 ,批量加上@Mapper ,也可以手动加上 ,省略此配置        //会触发 No MyBatis mapper was found in '[anddd7.springboot.controller, anddd7.springboot]' package.  警告        //mapperScannerConfigurer.setBasePackage("anddd7.springboot.dao");        return mapperScannerConfigurer;    }}
  • 5.1 SqlSessionFactory
package anddd7.springboot.configuration;import org.apache.ibatis.session.SqlSessionFactory;import org.mybatis.spring.SqlSessionFactoryBean;import org.mybatis.spring.SqlSessionTemplate;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.context.annotation.Import;import org.springframework.core.io.DefaultResourceLoader;import org.springframework.core.io.ResourceLoader;import org.springframework.core.io.support.PathMatchingResourcePatternResolver;import org.springframework.core.io.support.ResourcePatternResolver;import org.springframework.jdbc.datasource.DataSourceTransactionManager;import org.springframework.transaction.PlatformTransactionManager;import org.springframework.transaction.annotation.EnableTransactionManagement;import org.springframework.transaction.annotation.TransactionManagementConfigurer;import javax.sql.DataSource;import java.io.IOException;/** * 对应xml中事务和sqlSessionFactory的配置 */@Configuration@EnableTransactionManagement@Import(DataSourceConfiguration.class)public class MyBatisConfiguration implements TransactionManagementConfigurer {    @Autowired    private DataSource dataSource;    @Override    public PlatformTransactionManager annotationDrivenTransactionManager() {        return new DataSourceTransactionManager(dataSource);    }    @Bean(name = "sqlSessionFactory")    public SqlSessionFactory sqlSessionFactoryBean() {        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();        //设置数据源        bean.setDataSource(dataSource);        //设置config路径        ResourceLoader resourceLoader = new DefaultResourceLoader();        bean.setConfigLocation(resourceLoader.getResource("classpath:mybatis-configuration.xml "));        //设置mapper.xml路径        ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();        try {            bean.setMapperLocations(resolver.getResources("classpath:anddd7/springboot/mapping/*.xml"));        } catch (IOException e) {            e.printStackTrace();        }        try {            return bean.getObject();        } catch (Exception e) {            e.printStackTrace();            throw new RuntimeException(e);        }    }    @Bean    public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {        return new SqlSessionTemplate(sqlSessionFactory);    }}
  • 5.2 mybatis-configuration.xml
<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE configuration    PUBLIC "-//mybatis.org//DTD Config 3.0//EN"    "http://mybatis.org/dtd/mybatis-3-config.dtd"><configuration>    <settings>        <setting name="cacheEnabled" value="false" />        <setting name="lazyLoadingEnabled" value="false" />        <setting name="multipleResultSetsEnabled" value="true" />        <setting name="useColumnLabel" value="true" />        <setting name="useGeneratedKeys" value="false" />        <setting name="defaultExecutorType" value="SIMPLE" />        <setting name="defaultStatementTimeout" value="25000" />    </settings></configuration>
  • 6 除了application.xml还以properties或yaml存在,其他配置都Java化了,web.xml自然也不存在了(顺应servlet 3.0的注解方式)。
package anddd7.springboot.configuration;import anddd7.springboot.filter.LoginFilter;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.web.servlet.FilterRegistrationBean;import org.springframework.context.annotation.Bean;import org.springframework.web.servlet.DispatcherServlet;import javax.servlet.Filter;/** * 对应web.xml中的所有设置 */public class WebXmlConfiguration {    @Bean(name = "LoginFilter")    public Filter getLoginFilter() {        return new LoginFilter();    }    @Autowired    DispatcherServlet dispatcherServlet;    /*    新的springboot不需要再设置servlet -> DispatcherServlet ,默认会拦截请求交给DispatcherServlet    @Bean    public ServletRegistrationBean defaultServletRegistration() {        ServletRegistrationBean registrationBean = new ServletRegistrationBean();        registrationBean.setServlet(dispatcherServlet);        registrationBean.addUrlMappings("*.ajax");        return registrationBean;    }    */    @Bean    public FilterRegistrationBean loginFilterRegistration() {        FilterRegistrationBean registrationBean = new FilterRegistrationBean();        registrationBean.setFilter(getLoginFilter());        registrationBean.setName("LoginFilter");        registrationBean.addUrlPatterns("*.html", "*.ajax");        return registrationBean;    }}

 从上面文件可以看到 ,通过@Configuration+@Import将xml转化成了容易理解的Java 。所以不是不需要配置,而是规范化、简单化的配置,而且启动方式上也简便不少。
 SpringBoot 将原来一些固定的启动方式打包在了一起 ,包含了很多自动化的配置 (@Enable*注解系列); 采用易读写的yaml和Java,摒弃xml(真的头晕)。

运行

Application.main()

总结

GitHub示例 Anddd7/SSM-SpringBoot-Starter`

 如果要添加webapp(网页静态资源),重命名为resources放在源目录下 (SpringBoot默认查找resources/static/public作为静态目录)。熟练过后 ,配置一个可用的Spring要比之前快得多 ,而且配置文件减少 ,项目目录结构清晰不少 。
 不过对Spring不熟悉 ,没有一条一条配过xml的入门者 ,这种一键式配置推荐使用不推荐学习 。封装太深 ,很难理解每一步的意义 ,所以使用过后还是对照xml一步步探究Spring所做的事 ,共勉

 Next ,SpringBoot原理和Spring源码

0 0
原创粉丝点击