文章目录
一、SSM说明
ssm(Spring、SpringMVC、mybatis)整合:
-
配置文件的整合:SpringMVC的配置文件(mvc.xml)单独一个、Spring的配置文件(applicationContext.xml)与mybatis的配置文件(mybatis-config.xml)可以选择整合成一个,也可以选择保留mybatis-config.xml,只不过其里面的数据源配置,mapper文件注册等要在applicationContext.xml里面写,仅仅保留一些< settings> < plugin>标签,不过还是建议整合成一个,
-
mvc.xml 与 applicationContext.xml 中的关于 注解扫描 的配置
- 两个工厂不能有彼此侵入,即,生产的组件不能有重合。
- 告知SpringMVC 哪些包中 存在被注解的类
use-default-filters=true凡是被@Controller @Service @Repository注解的类, 都会被扫描,
use- default- filters=false默认不扫描包内的任何类,只扫描include- filter中指定的类,只扫描被@Controller注解的类 - mvc.xml :
<!-- 注解扫描 下面这些配置是指SpringMVC在扫描com.wlw包下的注解时,只扫描有Controller注解的类(就是类名之上加了@Controller的类),其他的忽略-->
<context:component-scan base-package="com.wlw" use-default-filters="false">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"></context:include-filter>
</context:component-scan>
4. applicationContext.xml
<!--扫描注解 下面这些配置是指Spring在扫描com.wlw包下的注解时,不扫描有Controller注解的类(就是类名之上加了@Controller的类,因为这样的类被SpringMVC扫描了,区分职责关系,可以对比mvc.xml文件),其他的都要扫描-->
<context:component-scan base-package="com.wlw" use-default-filters="true">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
-
整个项目有大致三个配置文件 web.xml 、 mvc.xml (SpringMVC配置文件)、 applicationContext.xml (Spring配置文件), 在web.xml文件中会声明另外两个配置文件地址,当tomcat启动时,会加载web.xml文件,进而加载另外两个配置文件,创建springmvc工厂(子工厂)与spring工厂(父工厂);
-
xml配置文件与注解之间的选择:在我们自己写的代码中,service层(xxxServiceImpl)用注解(@Service)来声明bean、用注解(@Autowired @Qualifier(“userDao”))来自动注入dao、用注解(@Transactional 来配置事务); controller层使用注解(@Controller)来声明bean、用注解(@Autowired @Qualifier(“userServiceImpl”))来自动注入 service。
-
SpringMVC配置文件(mvc.xml)中写的是:开启注解扫描、注解驱动、视图解析器、静态资源访问、拦截器、异常解析器、文件上传解析器等
-
Spring配置文件(applicationContext.xml)中写的是: DataSource、SqlSessionFactory、DAO接口 MapperScannerConfigurer、扫描注解、事务管理器、开启事务注解等 (其中之前在mybatis所作的配置,是写在SqlSessionFactory这个bean中的)
二、实践:
-
第一步:在 pom.xml文件中导入依赖,声明打包方式,更改maven编译规则,让xxxMapper.xml文件可以被编译,之后再第一次运行时,可查看target/classes文件中是否有对应的xxxMapper.xml,看是否编译成功
-
第二步:在main文件下新建webapp文件夹,在webapp文件下新建WEB-INF文件夹,并在WEB-INF文件夹下新建web.xml文件,这是web项目的配置文件,随着tomcat服务器启动而被加载,里面配置基本都是servlet组件,基本包括SpringMVC工厂(前端(核心)控制器)和Spring工厂,以及对post请求中,中文参数乱码的处理;并且项目的前端页面组件放在webapp文件夹下
<?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_4_0.xsd"
version="4.0">
<!-- SpringMVC前端(核心)控制器
1. 前端,接收所有请求
2. 启动SpringMVC工厂 mvc.xml
3. 负责springMVC流程调度
-->
<servlet>
<servlet-name>mvc_wlw</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 局部参数,声明mvc配置文件位置-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:mvc.xml</param-value>
</init-param>
<!-- 懒汉式 饿汉式加载 可选-->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>mvc_wlw</servlet-name>
<url-pattern>/</url-pattern>
<!--<url-pattern>*.action</url-pattern>-->
</servlet-mapping>
<!-- 此过滤器会进行:request.setCharactorEncoding("utf-8"); 对post请求中,中文参数乱码有效-->
<filter>
<filter-name>encoding</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>encoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- 启动Spring工厂 -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
</web-app>
- 第三步:在src/main/resources写mvc.xml 与 applicationContext.xml;
- mvc.xml
- applicationContext.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
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
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!-- 注解扫描 下面这些配置是指SpringMVC在扫描com.wlw包下的注解时,只扫描有Controller注解的类(就是类名之上加了@Controller的类),其他的忽略-->
<context:component-scan base-package="com.wlw" use-default-filters="false">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"></context:include-filter>
</context:component-scan>
<!-- 注解驱动 -->
<mvc:annotation-driven>
<!-- 安装FastJson,转换器 -->
<mvc:message-converters>
<bean class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter">
<!-- 声明转换类型:json (将java对象转成josn)-->
<property name="supportedMediaTypes">
<list>
<value>application/json</value>
</list>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
<!-- 视图解析器
作用:1.捕获后端控制器的返回值="hello"
2.解析: 在返回值的前后 拼接 ==> "/hello.jsp"
-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!-- 前缀 -->
<property name="prefix" value="/"></property>
<!-- 后缀 -->
<property name="suffix" value=".jsp"></property>
</bean>
<!-- 处理静态资源访问-->
<mvc:default-servlet-handler/>
<!--拦截器-->
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/loger/test1"/> <!--要拦截的路径-->
<bean class="com.wlw.interceptor.MyInterceptor"></bean>
</mvc:interceptor>
</mvc:interceptors>
<!--异常解析器-->
<bean class="com.wlw.resolver.MyExceptionResolver"/>
<!--文件上传解析器-->
</beans>
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
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"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!--整合时,DAO放在工厂中(bean标签)是由MapperScannerConfigurer 来帮我们完成的 ,
而MapperScannerConfigurer 又需要sqlSessionFactory支持 , sqlSessionFactory 又需要DataSource-->
<!-- DataSource -->
<!-- 导入文件-->
<context:property-placeholder location="classpath:jdbc.properties"/>
<!--创建数据源-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
<!--基本配置-->
<property name="driverClassName" value="${jdbc.driverClass}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
<!-- 配置初始化大小、最小、最大 -->
<property name="initialSize" value="${jdbc.init}"/>
<property name="minIdle" value="${jdbc.minIdle}"/>
<property name="maxActive" value="${jdbc.maxActive}"/>
<!-- 配置获取连接等待超时的时间 ms-->
<property name="maxWait" value="60000"/>
<!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
<property name="timeBetweenEvictionRunsMillis" value="60000"/>
<!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->
<property name="minEvictableIdleTimeMillis" value="300000"/>
</bean>
<!-- SqlSessionFactory -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 注入连接池 -->
<property name="dataSource" ref="dataSource"></property>
<!-- (注册xxxDao-mapper文件)注入dao-mapper文件信息,如果映射文件和dao接口 同包且同名,则此配置可省略(要注意因为把mapper文件放在了dao文件夹下,所以要在pom.xml中更改maven编译规则)-->
<property name="mapperLocations">
<list>
<value>classpath:com/wlw/dao/*.xml</value>
</list>
</property>
<!-- 为实体类起别名 -->
<property name="typeAliasesPackage" value="com.wlw.entity"></property>
<property name="plugins">
<array>
<bean class="com.github.pagehelper.PageInterceptor">
<property name="properties">
<props>
<!-- 页号 调整到合理的值 0 max -->
<prop key="reasonable">true</prop>
</props>
</property>
</bean>
</array>
</property>
</bean>
<!-- DAO接口 MapperScannerConfigurer-->
<!-- mapperScannerConfigurer 管理DAO实现类的创建,并创建DAO对象,存入工厂管理,当执行完这个配置之后,在工厂中就会有一个id为userDAO 的bean,而这个bean就是UserDAO实现类的对象 -->
<bean id="mapperScannerConfigurer9" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!-- dao接口所在的包 如果有多个包,可以用逗号或分号分隔 <property name="basePackage" value="com.a.dao,com.b.dao"></property>-->
<property name="basePackage" value="com.wlw.dao"></property>
<!-- 如果工厂中只有一个SqlSessionFactory的bean,此配置可省略 -->
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>
</bean>
<!--扫描注解 下面这些配置是指Spring在扫描com.wlw包下的注解时,不扫描有Controller注解的类(就是类名之上加了@Controller的类,因为这样的类被SpringMVC扫描了,区分职责关系,可以对比mvc.xml文件),其他的都要扫描-->
<context:component-scan base-package="com.wlw" use-default-filters="true">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
<!-- 1. 引入一个事务管理器,其中依赖DataSource,借以获得连接,进而控制事务逻辑 -->
<bean id="tx" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--开启事务注解 只针对 这个@Transactional 事务注解-->
<tx:annotation-driven transaction-manager="tx"/>
</beans>
三、项目目录
D:\Program Files\IDEAworkspace\projects\JavaWeb_high\SSM_exam01
SSM与SSH
MyBatis与Hibernate的优劣
-
无论MyBatis或Hibernate都可以被称为ORM框架,Hibernate的设计理念是面向POJO的,而MyBatis不是。
-
Hibernate是一个标准的ORM框架,基本不需要编写SQL就可以通过映射关系来操作数据库,是一种全表映射的体现,维护关系比较复杂,sql语句自己生成,这就造成了对sql语句优化,修改比较困难。;而MyBatis需要我们提供SQL语句去运行,这就对sql修改和优化非常容易实现,程序员不必精通sql,只要懂得操作POJO就能够操作对应数据库的表。
-
在之前的时候,管理系统时代,首先是实现业务逻辑,然后才是性能,所以Hibernate在当时是主流。;而现在在移动互联网时代,MyBatis是首选,不屏蔽SQL,程序员可以自己制定SQL规则,能更加精确定义SQL,从而优化性能。更符合移动互联网高并发,大数据,高性能,高响应的要求。
-
Hibernate和MyBatis的增、删、查、改,对于业务逻辑层来说大同小异,对映射而言Hibernate的配置不需要接口和SQL,而MyBatis是需要的。对于Hibernate而言,不需要编写大量的SQL,就可以完全映射,同时提供了日志、缓存、级联(级联比MyBatis强大)等特性,此外还提供HQL (Hibernate Query Language)对POIO进行操作,使用十分方便,但是它也有**致命的缺陷:**由于无须SQL,当多表关联超过3个的时候,通过Hibernate的级联会造成太多性能的丢失,又或者我现在访问一个财 务的表,然后它会关联财产信息表,财产又分为机械、原料等.显然机械和原料的字段是不一样的,这样关联字段只能根据特定的条件 变化而变化,而Hibernate无法支持这样的变化。遇到存储过程,Hibernate只能作罢。更为关键的是性能,在管理系统的时代,对于性能的要求不是那么苛刻,但是在互联网时代性能就是系统的根本,响应过慢就会丧失客户,试想一下谁会去用一个经常需要等待超过10 秒以上的应用呢? **以上的问题MyBatis都可以解决,MyBatis 可以自由书写SQL、支持动态SQL、处理列表、动态生成表名,支持存储过程。**这样就可以灵活地定义查询语句,满足各类需求和性能优化的需要,这些在互联网系统中是十分重要的。
-
但MyBatis也有缺陷。首先,它要编写SQL和映射规则,其工作量稍微大于 Hibernate.其次,它支持的工具也很有限,不能像Hibernate那样有许多的插件可以帮助生成映射代码和关联关系,而即使使用生成工具,往往也需要开发者进一步简化, MyBatis 通过手工编码,工作量相对大些。
-
使用环境:对于性能要求不太苛刻的系统,比如管理系统、ERP 等推荐使用Hibernate;而对于性能要求高、响应快、灵活的系统则推荐使用MyBatis.
-
总1:
- Hibernate:
- 优点:面向对象开发,不需要自己写sql语句。如果进行数据库迁移不需要修改sql语句,只需要修改一下方言。使用方便
- 缺点:hibernate维护数据表关系比较复杂。完全是有hibernate来管理数据表的关系,不易维护,不易优化,不能开发比较复杂的业务。不容易写出高性能的程序。
- 适合范围:适合需求固定,对象数据模型稳定,性能要求不太苛刻的系统,中小型项目,比如:企业OA系统,管理系统
- MyBatis:
- 优点:对sql的优化,修改比较容易,可以灵活地定义查询语句,满足各类需求和性能优化的需要
- 缺点:工作量大,大型复杂系统需要写很多的sql语句
- 适合范围:适合开发需求变更频繁的系统,比如:互联网项目。
- Hibernate:
-
总2:
-
两者的相同点
-
Hibernate与MyBatis都可以是通过SessionFactoryBuider由XML配置文件生成SessionFactory,然后由SessionFactory 生成Session,最后由Session来开启执行事务和SQL语句。其中SessionFactoryBuider,SessionFactory,Session的生命周期都是差不多的。
-
Hibernate和MyBatis都支持JDBC和JTA事务处理。
-
-
两者各自优势
- MyBatis可以进行更为细致的SQL优化,可以减少查询字段。
- MyBatis容易掌握,而Hibernate门槛较高。
- Hibernate的DAO层开发比MyBatis简单,Mybatis需要维护SQL和结果映射。
- Hibernate对对象的维护和缓存要比MyBatis好,对增删改查的对象的维护要方便。
- Hibernate数据库移植性很好,MyBatis的数据库移植性不好,不同的数据库需要写不同SQL。
- Hibernate有更好的二级缓存机制,可以使用第三方缓存。MyBatis本身提供的缓存机制不佳,更新操作不能指定刷新指定记录,会清空整个表,但是也可以使用第三方缓存。
- Hibernate 封装性好,屏蔽了数据库差异,自动生成SQL语句,应对数据库变化能力较弱,SQL语句优化困难。
- MyBatis仅实现了SQL语句和对象的映射,需要针对具体的数据库写SQL语句,应对数据库变化能力较强,SQL语句优化较为方便。
-
SH和SSM对比异同点、各自优势
SSH和SSM定义
-
SSH 通常指的是 Struts2 做控制器(Action),Spring 管理各层的组件,Hibernate 负责持久化层。
-
SSM 则指的是 SpringMVC 做控制器(controller),Spring 管理各层的组件,MyBatis 负责持久化层。
共同点:
1.Spring依赖注入DI来管理各层的组件。
2.使用面向切面编程AOP管理事物、日志、权限等。
不同点:
1.Struts2 和 SpringMVC 控制器(controller)控制视图和模型的交互机制的不同,
2.Struts2是Action类级别,SpringMVC是方法级别,更容易实现RESTful风格。
SSH和SSM的实现原理
Struts2 的实现原理
Struts2框架执行步骤(Struts2使用Filter嵌入):
1、客户端初始化一个指向Servlet容器(例如Tomcat)的请求
2、这个请求经过一系列的过滤器(Filter)(这些过滤器中有一个叫做ActionContextCleanUp的可选过滤器,这个过滤器对于Struts2和其他框架的集成很有帮助
3、接着FilterDispatcher被调用,FilterDispatcher询问ActionMapper来决定这个请求是否需要调用某个Action
4、如果ActionMapper决定需要调用某个Action,FilterDispatcher把请求的处理交给ActionProxy
5、ActionProxy通过Configuration Manager询问框架的配置文件,找到需要调用的Action类
6、ActionProxy创建一个ActionInvocation的实例。
7、ActionInvocation实例使用命名模式来调用,在调用Action的过程前后,涉及到相关拦截器(Intercepter)的调用。
8、一旦Action执行完毕,ActionInvocation负责根据struts.xml中的配置找到对应的返回结果。返回结果通常是(但不总是,也可 能是另外的一个Action链)一个需要被表示的JSP或者FreeMarker的模版。
9、将处理结果返回给客户端
SpringMVC 的实现原理:
SpringMVC框架执行步骤(SpringMVC使用Servlet嵌入):
1、客户端发出一个http请求给web服务器,web服务器对http请求进行解析,如果匹配DispatcherServlet的请求映射路径(在web.xml中指定),web容器将请求转交给DispatcherServlet.
2、DipatcherServlet接收到这个请求之后将根据请求的信息(包括URL、Http方法、请求报文头和请求参数Cookie等)以及HandlerMapping的配置找到处理请求的处理器(Handler)。
3-4、DispatcherServlet根据HandlerMapping找到对应的Handler,将处理权交给Handler(Handler将具体的处理进行封装),再由具体的HandlerAdapter对Handler进行具体的调用。
5、Handler对数据处理完成以后将返回一个ModelAndView()对象给DispatcherServlet。
6、Handler返回的ModelAndView()只是一个逻辑视图并不是一个正式的视图,DispatcherSevlet通过ViewResolver将逻辑视图转化为真正的视图View。
7、Dispatcher通过model解析出ModelAndView()中的参数进行解析最终展现出完整的view并返回给客户端。
总结
SSM和SSH不同主要在MVC实现方式,以及ORM持久化方面不同(Hiibernate与Mybatis)。SSM越来越轻量级配置,将注解开发发挥到极致,且ORM实现更加灵活,SQL优化更简便;而SSH较注重配置开发,其中的Hiibernate对JDBC的完整封装更面向对象,对增删改查的数据维护更自动化,但SQL优化方面较弱,且入门门槛稍高。
Spring家族: