Spring 使用配置类 搭建SSM框架及部分源码解析

1. 创建maven 项目工程(略)

2. 创建如下演示目录:

在这里插入图片描述

3. 创建 AbstractAnnotationConfigDispatcherServletInitializer 的实现类

在Servlet3.0中,容器在启动时会在类路径中查找javax.servlet.ServletContainerInitializer 的实现类,如果能发现则会用它来配置Servlet容器。在Spring中Spring提供了其实现: SpringServletContainerInitializer。 而SpringServletContainerInitializer又会查找WebApplicationInitializer的类并将配置的任务交给他们来完成。Spring 3.2 为其引入了一个便利的基础实现类即 AbstractAnnotationConfigDispatcherServletInitializer 。即 当 部署到Servlet3.0容器中的时候,容器会发现AbstractAnnotationConfigDispatcherServletInitializer 具体实现类,并使用该类来配置Servlet上下文。
(字符编码过滤器配置的两种方式 : https://blog.csdn.net/dgeek/article/details/70545338
在这里插入图片描述

(1) 配置DispatcherServlet上下文的过程

查看 AbstractDispatcherServletInitializer 类可以发现里面的方法。其中有一个onStartup 方法和 createDispatcherServlet 方法。
在这里插入图片描述
onStartup 中注册了DispatcherServet, registerDispatcherServlet方法调用了 createDispatcherServlet ,并进行了一些启动项的配置
在这里插入图片描述
在这里插入图片描述
找到 createServletApplicationContext() 方法的实现后发现 。其调用 getServletConfigClasses() 方法正是我们所实现的抽象方法
在这里插入图片描述
在这里插入图片描述

(2) 配置配置ContextLoaderListener上下文的过程

配置DispatcherServlet上下文是通过 onStartup 方法中 的 registerDispatcherServlet 。但是我们并没有在onStartup中看到注册
ContextLoaderListener 的方法。 答案在super.onStartup方法中。对ContextLoaderListener进行注册的方法放在了其父类AbstractContextLoaderInitializer中。
在这里插入图片描述
registerContextLoaderListener 又调用了 createRootApplicationContext 方法。

在这里插入图片描述
查看 createRootApplicationContext 的实现方法发现和上面DispatcherServlet 类似。获取配置类并注册

在这里插入图片描述

注:

  • DispatcherServlet启动时会创建Spring应用上下文,并加载配置文件或配置类中所声明的bean, 如控制器、视图解析器以以及处理器映射。
  • ContextLoaderListener也会创建一个上下文 则用来加载应用中的一些其他bean。这些bean通常是驱动应用后端的中间层和数据层组件。

4. 启动Spring MVC配置 : 前端视图解析器(DispatcherServlet)配置

web.xml中的配置方式:
在这里插入图片描述

DispatcherServletConfig中的配置

  1. 通过注解 @EnableWebMvc 启动webmvc(), 并配置扫描目录。
    在这里插入图片描述

这种配置方式存在以下一些问题:

  • 没有配置视图解析器: Spring使用默认的BeanNameViewResolver 视图解析器,这个解析器会查找ID与视图名称匹配的bean,并且查找的Bean要实现View接口。
  • 若不使用@ComponentScan注解,则Spring只能找到显式声明在配置类中的控制器。
  • DispatcherServlet 会映射为应用的默认Servlet。所以对于静态资源文件的请求也会进行映射。
  • <mvc:annotation-driven /> is also @EnableWebMvc
    <tx:annotation-driven /> is @EnableTransactionManagement.
    <context:component-scan /> is @ComponentScan

因此,实际使用中需要进行一些扩展如下

@Configuration
@EnableWebMvc               // 启用Spring Mvc
@ComponentScan("com.kingfish")  // 启用组件扫描
public class ServletConfig extends WebMvcConfigurerAdapter {
    /**
     * 配置视图解析器
     *
     * @return
     */
    @Bean
    public ViewResolver viewResolver() {
        InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
        viewResolver.setPrefix("/WEB-INF/view/");   // 配置前缀
        viewResolver.setSuffix(".jsp");            // 配置后缀
        viewResolver.setExposeContextBeansAsAttributes(true); // 设置是否让应用程序上下文中的所有Spring bean都可访问*作为请求属性,
        return viewResolver;
    }

    /**
     * 配置文件解析器
     *
     * @return
     */
    @Bean
    public MultipartResolver multipartResolver() {
        CommonsMultipartResolver commonsMultipartResolver = new CommonsMultipartResolver();
        commonsMultipartResolver.setMaxUploadSize(10000000);
        commonsMultipartResolver.setDefaultEncoding("UTF-8");
        return commonsMultipartResolver;
    }

    /**
     * 配置静态资源文件的处理
     *
     * @param configurer
     */
    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
        configurer.enable();    // 使DispatcherServlet对静态资源的请求转发到Servlet容器中默认的Servlet上,而不是使用DispatcherServlet本身处理
    }

    /**
     * 添加拦截器
     *
     * @param registry
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {

    }

    /**
     *  配置消息转换器的编码,解决后台传输json回前台时,中文乱码问题
     *  如果客户端发送的消息是json格式,则调用 StringHttpMessageConverter 来进行 消息转换,而StringHttpMessageConverter 默认转换格式是ISO_8859_1
     * @param converters
     */
    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        // 消息转换器 -  默认支持所有类型    返回使用 text/plain, 这里写出来是将其编码转换为utf-8。 因为其默认编码是 ISO_8859_1 前端中文乱码
        StringHttpMessageConverter stringHttpMessageConverter = new StringHttpMessageConverter(Charset.forName("UTF-8"));   // 消息转换器
        // 消息转换器 - 将JSON对象装转换为java对象,支持 application/json 格式
        MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter();
        converters.add(stringHttpMessageConverter);
        converters.add(mappingJackson2HttpMessageConverter);
    }

这里解释一下 关于消息转换器 MessageConverters 的问题:
在请求中 @ResponseBody@RequestBody 注解都会告诉Spring,让Spring查找一个消息转换器来将客户端资源表述转换为对象。当我们将字符串对象通过springmvc传回浏览器时,也会调用消息转换器进行资源转换。
默认情况下,如果返回的是对象,则会调用 MappingJackson2HttpMessageConverter ,这里没什么好说的,直接添加就可以了。
如果返回的格式是String,则会使用 StringHttpMessageConverter 消息转换器。根据其注释可以看出其返回的 Content-Typetext/plain 。而默认编码格式是 ISO-8859-1。这就是造成返回前段时中文乱码的罪魁祸首。

在这里插入图片描述
为了解决上述问题,我们需要自己配置消息转换器,即如下:

    /**
     *  配置消息转换器的编码,解决后台传输json回前台时,中文乱码问题
     *  如果客户端发送的消息是json格式,则调用 StringHttpMessageConverter 来进行 消息转换,而StringHttpMessageConverter 默认转换格式是ISO_8859_1
     * @param converters
     */
    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        // 消息转换器 -  默认支持所有类型    返回使用 text/plain, 这里写出来是将其编码转换为utf-8。 因为其默认编码是 ISO_8859_1 前端中文乱码
        StringHttpMessageConverter stringHttpMessageConverter = new StringHttpMessageConverter(Charset.forName("UTF-8"));   // 消息转换器
        // 消息转换器 - 将JSON对象装转换为java对象,支持 application/json 格式
        MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter();
        converters.add(stringHttpMessageConverter);
        converters.add(mappingJackson2HttpMessageConverter);
    }

5. 添加其他Servlet、Filter

按照 AbstractAnnotationConfigDispatcherServletInitializer的定义。它会创建DispatcherServlet和ContextLoaderListener。但并未提及添加其他Servlet、Filter和Listener。
上面说到 : 在Servlet3.0中,容器会在类路径中查找javax.servlet.ServletContainerInitializer 的实现类,如果能发现则会用它来配置Servlet容器。在Spring中Spring提供了其实现: SpringServletContainerInitializer。 而SpringServletContainerInitializer又会查找WebApplicationInitializer的类并将配置的任务交给他们来完成。
而实际上,基于java的初始化器(initializer) 的一个好处就是可以定义任意数量的初始化器。所以添加自定义的Servlet、Filter 最简单的方式是可以通过实现Spring的 WebApplicationInitializer 接口。
具体如下:
在这里插入图片描述
添加自定义的过滤器。
在这里插入图片描述
在这里插入图片描述

6. 配置RootConfig — 夹杂应用中的其他bean,通常是驱动应用后端的中间层和数据层组件。配置sessionFactory、事务管理等

(1) 创建一个简单的数据库,和user表用于测试
在这里插入图片描述
(2) 配置RootConfig

@Configuration
@EnableTransactionManagement    // 启动事务管理
@ComponentScan(basePackages = {"com.kingfish"}, excludeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION, value = EnableWebMvc.class)})
public class RootConfig {

    /**
     * 配置dataSource
     *
     * @return
     */
    @Bean
    public DataSource druidDataSource() {
        DruidDataSource druidDataSource = new DruidDataSource();
        druidDataSource.setDriverClassName("com.mysql.jdbc.Driver");
        druidDataSource.setUrl("jdbc:mysql:///demo?useUnicode=true&characterEncoding=utf-8");
        druidDataSource.setUsername("root");
        druidDataSource.setPassword("123");
        return druidDataSource;
    }

    /**
     * 配置sessionFactory
     *
     * @param dataSource
     * @return
     */
    @Bean
    public SqlSessionFactoryBean sqlSessionFactoryBean(DataSource dataSource) throws IOException {
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(dataSource);
        sqlSessionFactoryBean.setTypeAliasesPackage("com.kingfish.pojo");
        sqlSessionFactoryBean.setConfigLocation(new ClassPathResource("mybatis/SqlSessionFactory.xml"));
        sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath*:mybatis/mapper/*.xml"));

        return sqlSessionFactoryBean;
    }

    /**
     * 配置事务管理器
     *
     * @param dataSource
     * @return
     */
    @Bean
    public DataSourceTransactionManager dataSourceTransactionManager(DataSource dataSource) {
        DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
        dataSourceTransactionManager.setDataSource(dataSource);
        return dataSourceTransactionManager;
    }

    /**
     * 配置事务过滤
     *
     * @param dataSourceTransactionManager
     * @return
     */
    @Bean
    public TransactionInterceptor interceptor(DataSourceTransactionManager dataSourceTransactionManager) {
        TransactionInterceptor interceptor = new TransactionInterceptor();
        interceptor.setTransactionManager(dataSourceTransactionManager);

        Properties transactionAttributes = new Properties();
        transactionAttributes.setProperty("save*", "PROPAGATION_REQUIRED");
        transactionAttributes.setProperty("del*", "PROPAGATION_REQUIRED");
        transactionAttributes.setProperty("update*", "PROPAGATION_REQUIRED");
        transactionAttributes.setProperty("get*", "PROPAGATION_REQUIRED,readOnly");
        transactionAttributes.setProperty("find*", "PROPAGATION_REQUIRED,readOnly");
        transactionAttributes.setProperty("*", "PROPAGATION_REQUIRED");

        interceptor.setTransactionAttributes(transactionAttributes);
        return interceptor;
    }

    @Bean
    public MapperScannerConfigurer mapperScannerConfigurer() {
        MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer();
        mapperScannerConfigurer.setSqlSessionFactoryBeanName("sqlSessionFactoryBean");
        mapperScannerConfigurer.setBasePackage("com.kingfish.dao");
        return mapperScannerConfigurer;
    }
}

(3). 创建相应的类进行数据库操作。目录结构如下
在这里插入图片描述

在这里插入图片描述
SqlSessionFactory.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>
        <!--使用jdbc的getGeneratekeys获取自增主键值-->
        <setting name="useGeneratedKeys" value="true"/>
        <!--使用列别名替换别名  默认true-->
        <setting name="useColumnLabel" value="true"/>
        <!--开启驼峰命名转换Table:create_time到 Entity(createTime)-->
        <setting name="mapUnderscoreToCamelCase" value="true"/>
        <!-- 打印日志 -->
        <setting name="logImpl" value="STDOUT_LOGGING" />
    </settings>
</configuration>

(3). 访问测试
在这里插入图片描述

补充: pom.xml 配置:

<?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>11</groupId>
  <artifactId>123</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>war</packaging>

  <name>123 Maven Webapp</name>
  <!-- FIXME change it to the project's website -->
  <url>http://www.example.com</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.7</maven.compiler.source>
    <maven.compiler.target>1.7</maven.compiler.target>

    <springVersion>4.3.12.RELEASE</springVersion>
    <springVersion>4.3.12.RELEASE</springVersion>
    <hibernateVersion>4.3.5.Final</hibernateVersion>

    <jstlVersion>1.2</jstlVersion>
    <taglibVersion>1.1.2</taglibVersion>
    <servletVersion>3.0-alpha-1</servletVersion>

    <jsonVersion>2.5.4</jsonVersion>

    <mysqlVersion>8.0.13</mysqlVersion>
    <c3p0Version>0.9.1.2</c3p0Version>
    <log4jVersion>1.2.17</log4jVersion>
    <fileuploadVersion>1.3.1</fileuploadVersion>
  </properties>


  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>

    <!-- spring -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-beans</artifactId>
      <version>${springVersion}</version>
    </dependency>

    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-core</artifactId>
      <version>${springVersion}</version>
    </dependency>

    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>${springVersion}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-orm</artifactId>
      <version>${springVersion}</version>
    </dependency>

    <!-- spring web + spring MVC -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-web</artifactId>
      <version>${springVersion}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>${springVersion}</version>
    </dependency>

    <!--mysql jdbc-->
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.38</version>
    </dependency>

    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis</artifactId>
      <version>3.5.1</version>
    </dependency>

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

    <dependency>
      <groupId>javax</groupId>
      <artifactId>javaee-api</artifactId>
      <version>7.0</version>
    </dependency>

    <dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>druid-spring-boot-starter</artifactId>
      <version>1.1.16</version>
    </dependency>

    <dependency>
      <groupId>org.codehaus.jackson</groupId>
      <artifactId>jackson-mapper-asl</artifactId>
      <version>1.9.13</version>
    </dependency>

    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-core</artifactId>
      <version>${jsonVersion}</version>
    </dependency>
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>${jsonVersion}</version>
    </dependency>

    <!-- 引入gson依赖 -->
    <dependency>
      <groupId>com.google.code.gson</groupId>
      <artifactId>gson</artifactId>
      <version>2.6.2</version>
    </dependency>

    <!-- file upload part -->
    <dependency>
      <groupId>commons-fileupload</groupId>
      <artifactId>commons-fileupload</artifactId>
    </dependency>

  </dependencies>

  <build>
    <finalName>123</finalName>
    <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
      <plugins>
        <plugin>
          <artifactId>maven-clean-plugin</artifactId>
          <version>3.1.0</version>
        </plugin>
        <!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging -->
        <plugin>
          <artifactId>maven-resources-plugin</artifactId>
          <version>3.0.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-compiler-plugin</artifactId>
          <version>3.8.0</version>
        </plugin>
        <plugin>
          <artifactId>maven-surefire-plugin</artifactId>
          <version>2.22.1</version>
        </plugin>
        <plugin>
          <artifactId>maven-war-plugin</artifactId>
          <version>3.2.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-install-plugin</artifactId>
          <version>2.5.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-deploy-plugin</artifactId>
          <version>2.8.2</version>
        </plugin>
      </plugins>
    </pluginManagement>
  </build>
</project>


总结: 其实我就是想记录一下,为了以后忘记了可以迅速找回。。。

项目地址:https://download.csdn.net/download/qq_36882793/11665343

以上:内容主要参考《Spring实战》、https://www.cnblogs.com/Qi1007/p/10129706.html 。如有侵扰,联系删除。 内容仅用于自我记录学习使用。如有错误,欢迎指正。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

猫吻鱼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值