剑客
关注科技互联网

从空Pom文件用最少依赖配置SSM框架

从头开始

好多Web开发者都没有从头开始部署过SSM框架,网上一些教程总是加了一堆 常用但不是必须
的配置

本文旨在最少配置和依赖的情况下,构建起一个基于SpringMVC+Spring+MyBatis的Maven工程。

基于Maven的Web工程

当我们新建一个空的Maven工程的时候,仅有一个pom文件,一个source目录,一个resource目录,参考Java工程目录文章

加入Web目录

此时我们要使得这个工程变成Web工程,所以在source和resource同级的地方加入webapp目录

---main
    ---java
    ---resource
    ---webapp
---WEB-INF
    ---web.xml

其中根据文章Web.xml是什么可知,WEB-INF 和 web.xml 是由J2EE工程规定的,不能随意更改,web.xml是Servlet的配置,如何从头开始写呢?应该使用哪个版本呢?

这个可以去你下载的Servlet服务器容器的 /etc
目录中找到 webdefault.xml

该文件的xml命名空间里说明了该版本容器支持哪个版本的Servlet

例如Jetty8支持的是Servlet2.5 而 Jetty9则是3.0,此时我们得到了两个空的配置文件pom.xml和web.xml

空配置文件

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>person.test</groupId>
    <artifactId>spring</artifactId>
    <version>1.0</version>


</project>

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
 metadata-complete="false"
 version="3.1">


</web-app>

加入工程Target

完成了Web工程配置,此时我们要在pom.xml告诉Maven我们要 编译——汇编——链接
成什么东西,也就是Target叫什么和用什么格式

<project ...>

    .....

    <packaging>war</packaging> <==该模块打包成war包即WebApp的程序

    <build>
      <finalName>spring</finalName>  <==最后程序名叫spring
    </build>

</project>

SpringMVC+Spring

在完成了Web工程的配置之后,我们开始引入SpringMVC+Spring

修改依赖

在pom.xml文件中加入SpringMVC的依赖,不用添加spring-core因为SpringMVC会自己引用spring-core

<project ...>

    ....

    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>4.3.3.RELEASE</version>
        </dependency>
    </dependencies>

</project>

配置SpringMVC作ServletDispatch转发器

修改web.xml 原理参考Servlet原理把SpringMVC作为主入口的转发器,
org.springframework.web.servlet
包属于spring-webmvc这个Jar包

<servlet>
    <servlet-name>springMVC</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
<param-name>contextConfigLocation</param-name><==配置文件
<param-value>classpath:spring-mvc.xml</param-value>
    </init-param>
</servlet>

<servlet-mapping>
    <servlet-name>springMVC</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

此处的 contextConfigLocation
位于 DispatcherServlet的父类FrameworkServlet的第65行 private String contextConfigLocation
所以说spring-mvc.xml是对DispatcherServlet的配置

配置Spring作为Servlet的监听器

在搭建基于SpringMVC的Web服务时,Spring本身并不是必须添加的也就是说applicationContext.xml和listener也不是必须存在,具体原因我们在后边讨论


org.springframework.web.context
包属于spring-web这个Jar包

也就是说我们常说的SSH或SSM中的spring配置其实是指的配置spring-web服务而不是spring-core这个IOC容器

<context-param>
    <param-name>contextConfigLocation</param-name>       <==配置文件
    <param-value>classpath:applicationContext.xml</param-value>
</context-param>


<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

此处的 contextConfigLocation
位于 ContextLoaderListener的父类ContextLoader的第176行 configLocationParam = sc.getInitParameter(“contextConfigLocation”)
通过同名字符串获取到的configLocationParam 所以说applicationContext.xml是对ContextLoaderListener的配置

配置spring-mvc.xml

如果想让SpringMVC正式提供Web服务,需要以下几个 必要配置
注意在加入mvc命名空间后,需要有对应的xmlns,一般来讲intelliJ IDEA会自动补全

<beans ......>
    <mvc:default-servlet-handler/>   <==让SpringMVC作为默认的Servlet处理器
    <mvc:annotation-driven/>         <==让SpringMVC使用注解驱动,即可用RequestMap一类的注解
    <context:component-scan base-package="person.zhuojia.learn.spring"/>    <==让SpringMVC的Java文件基础包名

</beans>

配置applicationContext.xml

由于我们没有任何需要Spring控制的Class,所以applicationContext文件内容可以留空

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd">


</beans>

Mybatis

首先明确,Mybatis是JDBC的一个封装,所以说其本身无法离开JDBC,所以说我们要准备一些依赖,其配置可以放在任意一个Context里

依赖的准备

依赖名称 作用
spring-jdbc Spring的jdbc集成组件
mysql-connector-java MySQL数据库的jdbc组件
commons-dbcp 连接池,用来做数据源dataSource
mybatis mybatis核心类,提供mybatis的sqlSessionManage
mybatis-spring mybatis与Spring集成的组件
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jdbc</artifactId>
    <version>${spring.version}</version>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>${mysql.version}</version>
</dependency>
<dependency>
    <groupId>commons-dbcp</groupId>
    <artifactId>commons-dbcp</artifactId>
    <version>${dbcp.version}</version>
</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>

连接池配置

首先我们需要在Spring中启动连接池作为dataSource,而驱动(Driver)就是使用由spring-jdbc和mysql-connector一起提供的 com.mysql.jdbc.Driver
当我们输入数据库和账号密码,一个默认的连接池就启动好了

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
    <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
    <property name="url" value="jdbc:mysql://127.0.0.1:3306/psas?useUnicode=true&characterEncoding=utf8"/>
    <property name="username" value="root"/>
    <property name="password" value="root"/>
</bean>

MybatisSpring配置

配置好连接池后,参照MyBatisSpring的配置进行如下配置

配置完毕后就可以使用 DOMapper.java DO.java 和DOMapper.xml进行持久层封装

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
    <property name="dataSource" ref="dataSource"/>
    <property name="mapperLocations">
        <list>
            <value>classpath:*Mapper.xml</value>
        </list>
    </property>
</bean>

<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
    <property name="basePackage" value="person.zhuojia.learn.spring.dal"/>
    <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
</bean>

结语

以上是用最少的配置来实现SSM框架,其中很多优化参数都给省去了,具体优化设置请参考其它文章

『重中之重』

applicationContext和spring-mvc配置文件的区别

Spring本身可以提供多个Context,根据 StackOverflow的回答
回答,当我们需要多个Servlet而不是一个的时候,可以针对不同的Servlet设置不同的配置文件servlet-1.xml、servlet-2.xml,这是在SpringMVC的DispatcherServlet

如果有servlet1和servlet2公用的部分,可以通过配置ContextLoaderListener作为Root Context以供所有servlet使用,其由Jar包spring-web来实现

Root Context和Servlet Context的区别

由于Root Context是作为公用区域存在的,所以说就导致一个重要的特性Root Context的Beans可以被不同的Servlet的Bean引用(Reference),但其本身的Bean却不能引用Servlet的Bean

为什么大家都写Root Context

在早先的SSH框架时,准确的说指的是 Struts2 + SpringWeb + Hibernate,由于不能Struts2不能配置ServletContext,所以需要applicationContext配置文件

而使用了 SSM (SpringMVC SpringWeb Mybatis) 之后,为什么不能继续使用applicationContext,还要spring-mvc或者说servletContext这个配置呢?因为SpringMVC的Controller必须配置在servletContext中,加上好多人并不知道 在单一Servlet下Root Context也就是applicationContext是多余的

由此产生的一系列问题

这个问题坑过我好多回,当时不明白为什么现在可以意义解释了

  1. SpringMVC和Spring配置导致事务失效
    : 因为事务管理器transactionManager是声明在Root Context,而不区分包名导致ServletContext拿到了所有@Service的Bean,为什么是ServletContext拿到,是因为Servlet作为子Context优先级高啊,那么transactionManager就没办法引用@Service导致事务失效

  2. Shiro的注解配置位置不对
    : 如果想用Shiro的注解对Controller控制,那么必须能对Controller加动态代理,如果按照官方文档放在applicationContext里,自然没办法引用在子Context的@Controller的Class

分享到:更多 ()

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址