Java-SSM框架各层的整合

转载自:https://blog.csdn.net/u012453843/article/details/65936721

项目采用的是SSM框架(即Spring、SpringMVC、Mybatis)

Spring项目中有三层:Dao层、Service层、Web层;

taotao-manager层包含了Dao层和Service层(它们都是Jar工程),而Web层是一个独立的war工程;(这个和.net中的类库和程序类似的概念)

因此我们需要将它们三个整合一起。

1. Dao层整合:

  Dao层的整合也是框架的整合;

    Spring和Mybatis的整合:放在服务层,因为Mybatis的主要职责主要是和数据库打交道,不建议将Spring和Mybatis的整合放在taotao-manager-dao工程当中,因为dao工程是个jar工程,将来会被打包成一个jar包,配置文件也会被打包进去,再进行调用的话会比较麻烦,所以建议将Spring和Mybatis的整合放在taotao-manager-service工程中(因为该工程是war工程,taotao-manager聚合工程最终都会打包成一个war包,war包整合了聚合工程的所有内容,因此更适合来进行框架整合)。

  mybatis: SqlMapConfig.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>
 
</configuration>

  暂时不用向里面添加任何配置,像数据库连接池、事务之类的配置会交给Spring来管理,别名可配可不配,因此我们这里就放一个只有头的空文件就可以了(文件虽然没有配置任何内容,但是不能没有)。

  spring: applicationContext-dao.xml文件

  此文件配置数据库连接池、SqlSessionFactory(Mybatis的连接工厂)、Mybatis映射文件的包扫描器,配置内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
    xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
    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-4.2.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd
    http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd
    http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.2.xsd">
    
    <!-- 配置数据库连接池 -->
    <!-- 加载配置文件 -->
    <context:property-placeholder location="classpath:properties/db.properties" />
    <!-- 数据库连接池 -->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
        destroy-method="close">
        <property name="url" value="${jdbc.url}" />
        <property name="username" value="${jdbc.username}" />
        <property name="password" value="${jdbc.password}" />
        <property name="driverClassName" value="${jdbc.driver}" />
        <property name="maxActive" value="10" />
        <property name="minIdle" value="5" />
    </bean>
    <!-- SqlSessionFactory -->
    <!-- 让spring管理sqlsessionfactory 使用mybatis和spring整合包中的 -->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <!-- 数据库连接池 -->
        <property name="dataSource" ref="dataSource" />
        <!-- 加载mybatis的全局配置文件 -->
        <property name="configLocation" value="classpath:mybatis/SqlMapConfig.xml" />
    </bean>
    <!-- Mapper映射文件的包扫描器 -->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.taotao.mapper" />
    </bean>
    
</beans>

  从中可以看到我们配置数据库连接池配置的是druid连接池,Druid是目前最好的数据库连接池,在功能、性能、扩展性方面,都超过其他数据库连接池,包括DBCP、C3P0、BoneCP、Proxool、JBoss DataSource。Druid已经在阿里巴巴部署了超过600个应用,经过多年多生产环境大规模部署的严苛考验。

   数据库的配置直接读取的是配置文件db.properties文件,如下所示:

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/taotao?characterEncoding=utf-8
jdbc.username=root
jdbc.password=root

  taotao-manager-dao工程会被打包成jar包放到war工程下的WEB-INF/lib目录下,我们的 applicationContext-dao.xml 文件就是在war工程中,因此扫描是没有问题的。

Dao层整合完毕!

2. Service层整合

  spring: applicationContext-service.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
    xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
    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-4.2.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd
    http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd
    http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.2.xsd">
    
    <!-- 配置包扫描器,扫描所有带@Service注解的类 -->
    <context:component-scan base-package="com.taotao.service"/>
    
</beans>

  service层由接口和实现类组成;

  事务配置:把事务单独提出来进行配置,applicationContext-trans.xml文件:

  事务的传播行为:当接口以save、insert、add、create、delete、update开头时spring会自动帮我们开启事务(前提是我们已经配置了事务传播行为),而find、select、get开头的接口是查询,不涉及更改数据库,因此不需要事务,spring不会为查询接口自动开启事务;

  切面:事务的作用范围,execution(* com.taotao.service.*.*(..)) 的意思是,com.taotao.service下的任意类的任意方法的任意参数以及任意返回值都是事务的切入点。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
    xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
    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-4.2.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd
    http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd
    http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.2.xsd">
    
    <!-- 事务管理器 -->
    <bean id="transactionManager"
        class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <!-- 数据源 -->
        <property name="dataSource" ref="dataSource" />
    </bean>
    <!-- 通知 -->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <!-- 传播行为 -->
            <tx:method name="save*" propagation="REQUIRED" />
            <tx:method name="insert*" propagation="REQUIRED" />
            <tx:method name="add*" propagation="REQUIRED" />
            <tx:method name="create*" propagation="REQUIRED" />
            <tx:method name="delete*" propagation="REQUIRED" />
            <tx:method name="update*" propagation="REQUIRED" />
            <tx:method name="find*" propagation="SUPPORTS" read-only="true" />
            <tx:method name="select*" propagation="SUPPORTS" read-only="true" />
            <tx:method name="get*" propagation="SUPPORTS" read-only="true" />
        </tx:attributes>
    </tx:advice>
    <!-- 切面 -->
    <aop:config>
        <aop:advisor advice-ref="txAdvice"
            pointcut="execution(* com.taotao.service.*.*(..))" />
    </aop:config>
    
</beans>

  服务层spring下的三个配置文件是如何被知道的呢?这就需要在服务层初始化spring容器,方法是在taotao-manager-service工程下的web.xml文件中进行配置。

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" 
 id="WebApp_ID"
 xmlns="http://java.sun.com/xml/ns/javaee"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
 http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
 <display-name>taotao-manager</display-name>
 <welcome-file-list>
     <welcome-file>index.jsp</welcome-file>
 </welcome-file-list>
 
     <!-- 初始化spring容器 -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring/applicationContext-*.xml</param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
 
</web-app>

  Service层配置完成!

3. web层整合 

  spring:springmvc.xml文件:

  在springmvc.xml文件中需要配置的是扫描包:com.taotao.controller

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.2.xsd
        http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd">
        
    <!-- 配置注解驱动 -->
    <mvc:annotation-driven />
    <!-- 视图解析器 -->
    <bean
        class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/jsp/" />
        <property name="suffix" value=".jsp" />
    </bean>
    <!-- 配置包扫描器,扫描@Controller注解的类 -->
    <context:component-scan base-package="com.taotao.controller"/>
</beans>

  配置编码和前端控制器:在web.xml文件:

  web.xml文件配置内容如下,其中前端控制器配置中<load-on-startup>1</load-on-startup>这句话的意思是tomcat启动之后便加载DispatcherServlet,如果不配置的话,需要等请求访问的时候才会加载DispatcherServlet。另外可以看到,我们并没有配置父容器(ContextLoaderListener),这是因为我们在taotao-manager工程中已经配置过了,而且配置了Dao和Service。因此我们表现层不需要再配置一遍父容器了。

  DispatcherServlet:DispatcherServlet是前置控制器,配置在web.xml文件中的。拦截匹配的请求,Servlet拦截匹配规则要自己定义,把拦截下来的请求,依据相应的规则分发到目标Controller来处理,是配置spring MVC的第一步。

  DispatcherServlet是前端控制器设计模式的实现,提供Spring Web MVC的集中访问点,而且负责职责的分派,而且与Spring IoC容器无缝集成,从而可以获得Spring的所有好处。

  DispatcherServlet主要用作职责调度工作,本身主要用于控制流程,主要职责如下:

  1、文件上传解析,如果请求类型是 multipart 将通过 MultipartResolver 进行文件上传解析;
  2、通过 HandlerMapping,将请求映射到处理器(返回一个HandlerExecutionChain,它包括一个处理器、多个HandlerInterceptor拦截器);
  3、通过 HandlerAdapter 支持多种类型的 处理器(HandlerExecutionChain中的处理器);
  4、通过 ViewResolver 解析 逻辑视图名到具体视图实现;
  5、本地化解析;
  6、渲染具体的视图等;
  7、如果执行过程中遇到异常将交给HandlerExceptionResolver来解析。
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" 
     id="WebApp_ID"
     xmlns="http://java.sun.com/xml/ns/javaee"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
     http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
     <display-name>taotao-manager</display-name>
     <welcome-file-list>
         <welcome-file>index.jsp</welcome-file>
     </welcome-file-list>
     <!-- post乱码过滤器 -->
    <filter>
        <filter-name>CharacterEncodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>utf-8</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>CharacterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    <!-- 前端控制器 -->
    <servlet>
        <servlet-name>taotao-manager-web</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!-- contextConfigLocation不是必须的, 如果不配置contextConfigLocation, springmvc的配置文件默认在:WEB-INF/servlet的name+"-servlet.xml" -->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:spring/springmvc.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>taotao-manager-web</servlet-name>
        <!-- 拦截所有请求jsp除外 -->
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>

  说到这里,我们一般会对父子容器(同一个工程下)比较感兴趣,想知道是怎么回事,请看下面这张图。Spring父容器一般配置的是Dao层和Service层,而Spring子容器一般配置的是Controller层,父子容器的访问关系是,子容器可以访问父容器中的对象,但是父容器无法访问子容器中的对象。比如controller可以把Dao和Service注入进来,但是Dao和Service无法把Controller注进来。

  我们在service配置扫描包的时候配置的扫描范围是"com.taotao.service",如果我们配置成com.taotao,那么就会把com.taotao.controller也扫描到父容器中,这样父子容器中就都有controller层了,但是在父容器中扫进来controller是没有用的,我们在表现层访问的时候,访问的还是子容器的controller。同理,如果把子容器的扫描范围扩大,变为com.taotao,那么它便会把Dao和Service也扫描到子容器当中,这样当我们访问表现层的时候,访问的便是子容器中的Dao和Service,子容器中的Dao和Service是没有事务的,但是父容器中的Dao和Service是有事务的,这样就会导致虽然我们在父容器中配置了事务,但由于子容器扫描范围太大,而导致访问子容器中的Dao和Service没有事务的问题。

  由于子容器可以直接访问父容器中的对象,因此我们在子容器中不用配置Dao和Service便可以直接使用它们。

   子容器其实也可以完全当父容器使用,之所以搞出父子容器,是为了让父容器有更好的扩展性,子容器只需要消费父容器就可以了。

猜你喜欢

转载自www.cnblogs.com/luoshengjie/p/10489119.html