DragonCave

一个没有黄段子的无聊小站

纯注解整合 Spring SpringMVC MyBatis Druid

前言

9102 年的今天再折腾 SSM 这一套似乎已经过时了,Spring Boot 是更优雅的解决方案。但既然是学习,不妨手动试一试如何通过注解方式将  SSM 整合在一起,这对 Spring Boot 的学习和理解自动配置的过程也有帮助。

本文将采用纯注解的方式整合 Spring SpringMVC MyBatis ,使用 Druid 作为数据库连接池,使用 FastJson 作为消息转换器,最终实现一个极简的 RESTFul Api 后端示例。

开发工具: IDEA 2019.2.3

建立 Maven 项目

首先建立一个空的 Maven 项目,不使用任何原型,具体过程不表。

修改 pom.xml 文件:

设置打包方式为 war:

<packaging>war</packaging>

设置项目 Java 版本为 1.8:

<properties>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
</properties>

引入依赖:

<dependencies>
       <dependency>
           <groupId>org.springframework</groupId>
           <artifactId>spring-core</artifactId>
           <version>5.2.0.RELEASE</version>
       </dependency>
       <dependency>
           <groupId>org.springframework</groupId>
           <artifactId>spring-beans</artifactId>
           <version>5.2.0.RELEASE</version>
       </dependency>
       <dependency>
           <groupId>org.springframework</groupId>
           <artifactId>spring-context</artifactId>
           <version>5.2.0.RELEASE</version>
       </dependency>

       <dependency>
           <groupId>org.springframework</groupId>
           <artifactId>spring-web</artifactId>
           <version>5.2.0.RELEASE</version>
       </dependency>
       <dependency>
           <groupId>org.springframework</groupId>
           <artifactId>spring-webmvc</artifactId>
           <version>5.2.0.RELEASE</version>
       </dependency>
       <dependency>
           <groupId>javax.servlet</groupId>
           <artifactId>javax.servlet-api</artifactId>
           <version>4.0.1</version>
           <scope>provided</scope>
       </dependency>

       <dependency>
           <groupId>org.springframework</groupId>
           <artifactId>spring-jdbc</artifactId>
           <version>5.2.0.RELEASE</version>
       </dependency>
       <dependency>
           <groupId>mysql</groupId>
           <artifactId>mysql-connector-java</artifactId>
           <version>8.0.18</version>
       </dependency>

       <dependency>
           <groupId>org.mybatis</groupId>
           <artifactId>mybatis</artifactId>
           <version>3.5.3</version>
       </dependency>
       <dependency>
           <groupId>org.mybatis</groupId>
           <artifactId>mybatis-spring</artifactId>
           <version>2.0.3</version>
       </dependency>

       <dependency>
           <groupId>com.alibaba</groupId>
           <artifactId>fastjson</artifactId>
           <version>1.2.62</version>
       </dependency>
       <dependency>
           <groupId>com.alibaba</groupId>
           <artifactId>druid</artifactId>
           <version>1.1.21</version>
       </dependency>
   </dependencies>

整合 Spring SpringMVC

具体说明参照《从零开始构建 Spring Web 项目配置 SpringMVC(基于注解)部分,这里考虑篇幅只贴出源代码。

根据需要在 /src/main/java 下建包,在 config 中创建类 WebConfig:

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "me.loong.ssm.controller")
public class WebConfig implements WebMvcConfigurer {

}

在 config 中创建类 RootConfig:

@Configuration
@ComponentScan(basePackages = "me.loong.ssm", excludeFilters = @ComponentScan.Filter(type = FilterType.ANNOTATION, value = EnableWebMvc.class))
public class RootConfig {
}

在 config 中创建类 WebAppInitializer :

public class WebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class[]{RootConfig.class};
    }
    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class[]{WebConfig.class};
    }
    @Override
    protected String[] getServletMappings() {
        return new String[]{"/"};
    }

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

整合 MyBatis Druid

在 src/main/resource 下建立 jdbc.properties 并写入数据库连接相关信息

jdbc.driverClass=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://xxx/xxx?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8
jdbc.username=xxx
jdbc.password=xxx

在 config 中创建 MyBatisConfig 类:

@Configuration
@MapperScan(basePackages = "me.loong.ssm.mapper")
@PropertySource("classpath:jdbc.properties")
public class MyBatisConfig {

    @Value("${jdbc.driverClass}")
    private String driver;

    @Value("${jdbc.url}")
    private String url;

    @Value("${jdbc.username}")
    private String user;

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

    @Bean
    public DruidDataSource dataSource() {
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setDriverClassName(driver);
        dataSource.setUrl(url);
        dataSource.setUsername(user);
        dataSource.setPassword(password);
        return dataSource;
    }

    @Bean
    public SqlSessionFactory sqlSessionFactory() throws Exception {
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(dataSource());
        PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
//        sqlSessionFactoryBean.setConfigLocation(resolver.getResource("classpath:mybatis-config.xml"));
//        sqlSessionFactoryBean.setMapperLocations(resolver.getResources("classpath*:**/mapper/*Mapper.xml"));
        return sqlSessionFactoryBean.getObject();
    }


}

本类中,@Configuration 接口表明是一个配置类,@MapperScan 指定扫描 Mapper 接口文件,@PropertySource 引入创建的数据库配置文件。

不想额外创建配置文件的话也可以直接写在 dataSource() 中的相应位置。

dataSource() 用于创建 Druid 数据源 Bean,sqlSessionFactory() 用于创建 MyBatis  会话工厂 Bean。注释的两句分别是引入外部 MyBatis 配置文件和扫描 Mapper.xml 文件。如果想要使用配置文件配置MyBatis 也是可以的。有相应 Mapper 接口的 Mapper.xml 不需要再配置扫描。

注意

Mapper 接口类均需要加上 @Mapper 注解以便能够被扫描

数据库操作部分就不详细写了,能用就对了。

整合 FastJson

作为 RESTFul API 后端,通常是以 json 数据进行交互,相比 Spring 默认的 Jackson,来自阿里巴巴的 FastJson 在效率和功能上更占优势,所以本例配置 FastJson 作为消息转换器。

修改 WebConfig 类:

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "me.loong.ssm.controller")
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        FastJsonHttpMessageConverter fastJsonConverter = new FastJsonHttpMessageConverter();
        List<MediaType> supportedMediaTypes = new ArrayList<>();
        supportedMediaTypes.add(MediaType.APPLICATION_JSON);
        supportedMediaTypes.add(MediaType.APPLICATION_ATOM_XML);
        supportedMediaTypes.add(MediaType.APPLICATION_FORM_URLENCODED);
        supportedMediaTypes.add(MediaType.APPLICATION_OCTET_STREAM);
        supportedMediaTypes.add(MediaType.APPLICATION_PDF);
        supportedMediaTypes.add(MediaType.APPLICATION_RSS_XML);
        supportedMediaTypes.add(MediaType.APPLICATION_XHTML_XML);
        supportedMediaTypes.add(MediaType.APPLICATION_XML);
        supportedMediaTypes.add(MediaType.IMAGE_GIF);
        supportedMediaTypes.add(MediaType.IMAGE_JPEG);
        supportedMediaTypes.add(MediaType.IMAGE_PNG);
        supportedMediaTypes.add(MediaType.TEXT_EVENT_STREAM);
        supportedMediaTypes.add(MediaType.TEXT_HTML);
        supportedMediaTypes.add(MediaType.TEXT_MARKDOWN);
        supportedMediaTypes.add(MediaType.TEXT_PLAIN);
        supportedMediaTypes.add(MediaType.TEXT_XML);
        fastJsonConverter.setSupportedMediaTypes(supportedMediaTypes);
        FastJsonConfig fastJsonConfig = new FastJsonConfig();
        fastJsonConfig.setSerializerFeatures(SerializerFeature.WriteMapNullValue);
        fastJsonConverter.setFastJsonConfig(fastJsonConfig);
        converters.add(0, fastJsonConverter);
    }
}

通过重写 configureMessageConverters() 将 fastJsonConverter 设为默认消息转换器。

java.lang.IllegalArgumentException: Content-Type cannot contain wildcard type ‘*’

在 FastJson 1.2.28 及更高的版本中,FastJson 设置的MediaType为’/’,但 Spring 在 org.springframework.http.converter.AbstractHttpMessageConverter.write 过程中要求Content-Type不能含有通配符,所以引起了这个错误。

解决方法如代码所示设置 supportedMediaTypes。

如果是旧版的 FastJson 就不需要此操作。

编写 RestController

在 controller 中创建 HelloController 类:

@RestController
public class HelloController {

    @RequestMapping(path = "/", method = RequestMethod.GET)
    public Map<String, String> hello(){
        Map<String, String> map = new HashMap();
        map.put("Hello ","World! ");
        return map;
    }
}

@RestController 注解表明此控制器方法返回的对象经消息转换器转换后直接写入到输出流,而不会走视图处理器。

在本例中,就是对象经 FastJSON 转换为 JSON 字符串后被直接输出给客户端。

测试结果

此时完整的项目结构如下:《纯注解整合 Spring SpringMVC MyBatis Druid》

根据《从零开始构建 Spring Web 项目》中的步骤部署和启动项目后,使用浏览器或者 Postman 就可以对接口进行测试:

《纯注解整合 Spring SpringMVC MyBatis Druid》

点赞

发表评论

电子邮件地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据