ssm框架_ssm框架整合 - CSDN
精华内容
参与话题
  • 小疯手把手带你整合SpringMVC+Spring+MyBatis三大框架,俗称SSM,用它完全代替传统的SSH框架,把它们最优雅的一面发挥出来。整合配置结束后,会有一个应用实例“图书管理系统”带给大家,希望能快速上手这个框架

    本文发表于2016年6月,写于作者学生时期。文中使用到的技术和框架可能不是当下最佳实践,甚至很不“优雅”。但对于刚接触JavaEE和Spring的同学来说,还是能有很多收获的,大牛轻拍= =

    我们看招聘信息的时候,经常会看到这一点,需要具备SSH框架的技能;而且在大部分教学课堂中,也会把SSH作为最核心的教学内容。
    但是,我们在实际应用中发现,SpringMVC可以完全替代Struts,配合注解的方式,编程非常快捷,而且通过restful风格定义url,让地址看起来非常优雅。
    另外,MyBatis也可以替换Hibernate,正因为MyBatis的半自动特点,我们程序猿可以完全掌控SQL,这会让有数据库经验的程序猿能开发出高效率的SQL语句,而且XML配置管理起来也非常方便。
    好了,如果你也认同我的看法,那么下面我们一起来做整合吧!

    在写代码之前我们先了解一下这三个框架分别是干什么的?
    相信大以前也看过不少这些概念,我这就用大白话来讲,如果之前有了解过可以跳过这一大段,直接看代码!

    1. SpringMVC:它用于web层,相当于controller(等价于传统的servlet和struts的action),用来处理用户请求。举个例子,用户在地址栏输入http://网站域名/login,那么springmvc就会拦截到这个请求,并且调用controller层中相应的方法,(中间可能包含验证用户名和密码的业务逻辑,以及查询数据库操作,但这些都不是springmvc的职责),最终把结果返回给用户,并且返回相应的页面(当然也可以只返回json/xml等格式数据)。springmvc就是做前面和后面过程的活,与用户打交道!!

    2. Spring:太强大了,以至于我无法用一个词或一句话来概括它。但与我们平时开发接触最多的估计就是IOC容器,它可以装载bean(也就是我们java中的类,当然也包括service dao里面的),有了这个机制,我们就不用在每次使用这个类的时候为它初始化,很少看到关键字new。另外spring的aop,事务管理等等都是我们经常用到的。

    3. MyBatis:如果你问我它跟鼎鼎大名的Hibernate有什么区别?我只想说,他更符合我的需求。第一,它能自由控制sql,这会让有数据库经验的人(当然不是说我啦捂脸)编写的代码能搞提升数据库访问的效率。第二,它可以使用xml的方式来组织管理我们的sql,因为一般程序出错很多情况下是sql出错,别人接手代码后能快速找到出错地方,甚至可以优化原来写的sql。


    SSM框架整合配置

    好了,前面bb那么多,下面我们真正开始敲代码了~

    首先我们打开IED,我这里用的是eclipse(你们应该也是用的这个,对吗?),创建一个动态web项目,建立好相应的目录结构(重点!)

    项目结构图

    (打了马赛克是因为这里还用不到,你们不要那么污好不好?)

    我说一下每个目录都有什么用吧(第一次画表格,我发现markdown的表格语法很不友好呀~)
    这个目录结构同时也遵循maven的目录规范~

    文件名 作用
    src 根目录,没什么好说的,下面有main和test。
    - main 主要目录,可以放java代码和一些资源文件。
    - - java 存放我们的java代码,这个文件夹要使用Build Path -> Use as Source Folder,这样看包结构会方便很多,新建的包就相当于在这里新建文件夹咯。
    - - resources 存放资源文件,譬如各种的spring,mybatis,log配置文件。
    - - - mapper 存放dao中每个方法对应的sql,在这里配置,无需写daoImpl。
    - - - spring 这里当然是存放spring相关的配置文件,有dao service web三层。
    - - - sql 其实这个可以没有,但是为了项目完整性还是加上吧。
    - - - webapp 这个貌似是最熟悉的目录了,用来存放我们前端的静态资源,如jsp js css。
    - - - - resources 这里的资源是指项目的静态资源,如js css images等。
    - - - - WEB-INF 很重要的一个目录,外部浏览器无法访问,只有羡慕内部才能访问,可以把jsp放在这里,另外就是web.xml了。你可能有疑问了,为什么上面java中的resources里面的配置文件不妨在这里,那么是不是会被外部窃取到?你想太多了,部署时候基本上只有webapp里的会直接输出到根目录,其他都会放入WEB-INF里面,项目内部依然可以使用classpath:XXX来访问,好像IDE里可以设置部署输出目录,这里扯远了~
    - test 这里是测试分支。
    - - java 测试java代码,应遵循包名相同的原则,这个文件夹同样要使用Build Path -> Use as Source Folder,这样看包结构会方便很多。
    - - resources 没什么好说的,好像也很少用到,但这个是maven的规范。

    我先新建好几个必要的,并为大家讲解一下每个包的作用,顺便理清一下后台的思路~

    包结构图

    包名 名称 作用
    dao 数据访问层(接口) 与数据打交道,可以是数据库操作,也可以是文件读写操作,甚至是redis缓存操作,总之与数据操作有关的都放在这里,也有人叫做dal或者数据持久层都差不多意思。为什么没有daoImpl,因为我们用的是mybatis,所以可以直接在配置文件中实现接口的每个方法。
    entity 实体类 一般与数据库的表相对应,封装dao层取出来的数据为一个对象,也就是我们常说的pojo,一般只在dao层与service层之间传输。
    dto 数据传输层 刚学框架的人可能不明白这个有什么用,其实就是用于service层与web层之间传输,为什么不直接用entity(pojo)?其实在实际开发中发现,很多时间一个entity并不能满足我们的业务需求,可能呈现给用户的信息十分之多,这时候就有了dto,也相当于vo,记住一定不要把这个混杂在entity里面,答应我好吗?
    service 业务逻辑(接口) 写我们的业务逻辑,也有人叫bll,在设计业务接口时候应该站在“使用者”的角度。额,不要问我为什么这里没显示!IDE调皮我也拿它没办法~
    serviceImpl 业务逻辑(实现) 实现我们业务接口,一般事务控制是写在这里,没什么好说的。
    web 控制器 springmvc就是在这里发挥作用的,一般人叫做controller控制器,相当于struts中的action。

    还有最后一步基础工作,导入我们相应的jar包,我使用的是maven来管理我们的jar,所以只需要在pom.xml中加入相应的依赖就好了,如果不使用maven的可以自己去官网下载相应的jar,放到项目WEB-INF/lib目录下。关于maven的学习大家可以看慕课网的视频教程,这里就不展开了。我把项目用到的jar都写在下面,版本都不是最新的,大家有经验的话可以自己调整版本号。另外,所有jar都会与项目一起打包放到我的github上,喜欢的给个star吧~

    pom.xml

    <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/maven-v4_0_0.xsd">
    	<modelVersion>4.0.0</modelVersion>
    	<groupId>com.soecode.ssm</groupId>
    	<artifactId>ssm</artifactId>
    	<packaging>war</packaging>
    	<version>0.0.1-SNAPSHOT</version>
    	<name>ssm Maven Webapp</name>
    	<url>http://github.com/liyifeng1994/ssm</url>
    	<dependencies>
    		<!-- 单元测试 -->
    		<dependency>
    			<groupId>junit</groupId>
    			<artifactId>junit</artifactId>
    			<version>4.11</version>
    		</dependency>
    
    		<!-- 1.日志 -->
    		<!-- 实现slf4j接口并整合 -->
    		<dependency>
    			<groupId>ch.qos.logback</groupId>
    			<artifactId>logback-classic</artifactId>
    			<version>1.1.1</version>
    		</dependency>
    
    		<!-- 2.数据库 -->
    		<dependency>
    			<groupId>mysql</groupId>
    			<artifactId>mysql-connector-java</artifactId>
    			<version>5.1.37</version>
    			<scope>runtime</scope>
    		</dependency>
    		<dependency>
    			<groupId>c3p0</groupId>
    			<artifactId>c3p0</artifactId>
    			<version>0.9.1.2</version>
    		</dependency>
    
    		<!-- DAO: MyBatis -->
    		<dependency>
    			<groupId>org.mybatis</groupId>
    			<artifactId>mybatis</artifactId>
    			<version>3.3.0</version>
    		</dependency>
    		<dependency>
    			<groupId>org.mybatis</groupId>
    			<artifactId>mybatis-spring</artifactId>
    			<version>1.2.3</version>
    		</dependency>
    
    		<!-- 3.Servlet web -->
    		<dependency>
    			<groupId>taglibs</groupId>
    			<artifactId>standard</artifactId>
    			<version>1.1.2</version>
    		</dependency>
    		<dependency>
    			<groupId>jstl</groupId>
    			<artifactId>jstl</artifactId>
    			<version>1.2</version>
    		</dependency>
    		<dependency>
    			<groupId>com.fasterxml.jackson.core</groupId>
    			<artifactId>jackson-databind</artifactId>
    			<version>2.5.4</version>
    		</dependency>
    		<dependency>
    			<groupId>javax.servlet</groupId>
    			<artifactId>javax.servlet-api</artifactId>
    			<version>3.1.0</version>
    		</dependency>
    
    		<!-- 4.Spring -->
    		<!-- 1)Spring核心 -->
    		<dependency>
    			<groupId>org.springframework</groupId>
    			<artifactId>spring-core</artifactId>
    			<version>4.1.7.RELEASE</version>
    		</dependency>
    		<dependency>
    			<groupId>org.springframework</groupId>
    			<artifactId>spring-beans</artifactId>
    			<version>4.1.7.RELEASE</version>
    		</dependency>
    		<dependency>
    			<groupId>org.springframework</groupId>
    			<artifactId>spring-context</artifactId>
    			<version>4.1.7.RELEASE</version>
    		</dependency>
    		<!-- 2)Spring DAO层 -->
    		<dependency>
    			<groupId>org.springframework</groupId>
    			<artifactId>spring-jdbc</artifactId>
    			<version>4.1.7.RELEASE</version>
    		</dependency>
    		<dependency>
    			<groupId>org.springframework</groupId>
    			<artifactId>spring-tx</artifactId>
    			<version>4.1.7.RELEASE</version>
    		</dependency>
    		<!-- 3)Spring web -->
    		<dependency>
    			<groupId>org.springframework</groupId>
    			<artifactId>spring-web</artifactId>
    			<version>4.1.7.RELEASE</version>
    		</dependency>
    		<dependency>
    			<groupId>org.springframework</groupId>
    			<artifactId>spring-webmvc</artifactId>
    			<version>4.1.7.RELEASE</version>
    		</dependency>
    		<!-- 4)Spring test -->
    		<dependency>
    			<groupId>org.springframework</groupId>
    			<artifactId>spring-test</artifactId>
    			<version>4.1.7.RELEASE</version>
    		</dependency>
    
    		<!-- redis客户端:Jedis -->
    		<dependency>
    			<groupId>redis.clients</groupId>
    			<artifactId>jedis</artifactId>
    			<version>2.7.3</version>
    		</dependency>
    		<dependency>
    			<groupId>com.dyuproject.protostuff</groupId>
    			<artifactId>protostuff-core</artifactId>
    			<version>1.0.8</version>
    		</dependency>
    		<dependency>
    			<groupId>com.dyuproject.protostuff</groupId>
    			<artifactId>protostuff-runtime</artifactId>
    			<version>1.0.8</version>
    		</dependency>
    
    		<!-- Map工具类 -->
    		<dependency>
    			<groupId>commons-collections</groupId>
    			<artifactId>commons-collections</artifactId>
    			<version>3.2</version>
    		</dependency>
    	</dependencies>
    	<build>
    		<finalName>ssm</finalName>
    	</build>
    </project>
    
    

    下面真的要开始进行编码工作了,坚持到这里辛苦大家了~

    第一步:我们先在spring文件夹里新建spring-dao.xml文件,因为spring的配置太多,我们这里分三层,分别是dao service web。

    1. 读入数据库连接相关参数(可选)
    2. 配置数据连接池
    3. 配置连接属性,可以不读配置项文件直接在这里写死
    4. 配置c3p0,只配了几个常用的
    5. 配置SqlSessionFactory对象(mybatis)
    6. 扫描dao层接口,动态实现dao接口,也就是说不需要daoImpl,sql和参数都写在xml文件上

    spring-dao.xml

    <?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: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/context
    	http://www.springframework.org/schema/context/spring-context.xsd">
    	<!-- 配置整合mybatis过程 -->
    	<!-- 1.配置数据库相关参数properties的属性:${url} -->
    	<context:property-placeholder location="classpath:jdbc.properties" />
    
    	<!-- 2.数据库连接池 -->
    	<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
    		<!-- 配置连接池属性 -->
    		<property name="driverClass" value="${jdbc.driver}" />
    		<property name="jdbcUrl" value="${jdbc.url}" />
    		<property name="user" value="${jdbc.username}" />
    		<property name="password" value="${jdbc.password}" />
    
    		<!-- c3p0连接池的私有属性 -->
    		<property name="maxPoolSize" value="30" />
    		<property name="minPoolSize" value="10" />
    		<!-- 关闭连接后不自动commit -->
    		<property name="autoCommitOnClose" value="false" />
    		<!-- 获取连接超时时间 -->
    		<property name="checkoutTimeout" value="10000" />
    		<!-- 当获取连接失败重试次数 -->
    		<property name="acquireRetryAttempts" value="2" />
    	</bean>
    
    	<!-- 3.配置SqlSessionFactory对象 -->
    	<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
    		<!-- 注入数据库连接池 -->
    		<property name="dataSource" ref="dataSource" />
    		<!-- 配置MyBaties全局配置文件:mybatis-config.xml -->
    		<property name="configLocation" value="classpath:mybatis-config.xml" />
    		<!-- 扫描entity包 使用别名 -->
    		<property name="typeAliasesPackage" value="com.soecode.lyf.entity" />
    		<!-- 扫描sql配置文件:mapper需要的xml文件 -->
    		<property name="mapperLocations" value="classpath:mapper/*.xml" />
    	</bean>
    
    	<!-- 4.配置扫描Dao接口包,动态实现Dao接口,注入到spring容器中 -->
    	<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
    		<!-- 注入sqlSessionFactory -->
    		<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />
    		<!-- 给出需要扫描Dao接口包 -->
    		<property name="basePackage" value="com.soecode.lyf.dao" />
    	</bean>
    </beans>
    

    因为数据库配置相关参数是读取配置文件,所以在resources文件夹里新建一个jdbc.properties文件,存放我们4个最常见的数据库连接属性,这是我本地的,大家记得修改呀~还有喜欢传到github上“大头虾们”记得删掉密码,不然别人就很容易得到你服务器的数据库配置信息,然后干一些羞羞的事情,你懂的!!

    jdbc.properties

    jdbc.driver=com.mysql.jdbc.Driver
    jdbc.url=jdbc:mysql://localhost:3307/ssm?useUnicode=true&characterEncoding=utf8
    jdbc.username=root
    jdbc.password=
    

    友情提示:配置文件中的jdbc.username,如果写成username,可能会与系统环境中的username变量冲突,所以到时候真正连接数据库的时候,用户名就被替换成系统中的用户名(有得可能是administrator),那肯定是连接不成功的,这里有个小坑,我被坑了一晚上!!

    因为这里用到了mybatis,所以需要配置mybatis核心文件,在recources文件夹里新建mybatis-config.xml文件。

    1. 使用自增主键
    2. 使用列别名
    3. 开启驼峰命名转换 create_time -> createTime

    mybatis-config.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的getGeneratedKeys获取数据库自增主键值 -->
    		<setting name="useGeneratedKeys" value="true" />
    
    		<!-- 使用列别名替换列名 默认:true -->
    		<setting name="useColumnLabel" value="true" />
    
    		<!-- 开启驼峰命名转换:Table{create_time} -> Entity{createTime} -->
    		<setting name="mapUnderscoreToCamelCase" value="true" />
    	</settings>
    </configuration>
    

    第二步:刚弄好dao层,接下来到service层了。在spring文件夹里新建spring-service.xml文件。

    1. 扫描service包所有注解 @Service
    2. 配置事务管理器,把事务管理交由spring来完成
    3. 配置基于注解的声明式事务,可以直接在方法上@Transaction

    spring-service.xml

    <?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:context="http://www.springframework.org/schema/context"
    	xmlns:tx="http://www.springframework.org/schema/tx"
    	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/tx
    	http://www.springframework.org/schema/tx/spring-tx.xsd">
    	<!-- 扫描service包下所有使用注解的类型 -->
    	<context:component-scan base-package="com.soecode.lyf.service" />
    
    	<!-- 配置事务管理器 -->
    	<bean id="transactionManager"
    		class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    		<!-- 注入数据库连接池 -->
    		<property name="dataSource" ref="dataSource" />
    	</bean>
    
    	<!-- 配置基于注解的声明式事务 -->
    	<tx:annotation-driven transaction-manager="transactionManager" />
    </beans>
    

    第三步:配置web层,在spring文件夹里新建spring-web.xml文件。

    1. 开启SpringMVC注解模式,可以使用@RequestMapping,@PathVariable,@ResponseBody等
    2. 对静态资源处理,如js,css,jpg等
    3. 配置jsp 显示ViewResolver,例如在controller中某个方法返回一个string类型的"login",实际上会返回"/WEB-INF/login.jsp"
    4. 扫描web层 @Controller

    spring-web.xml

    <?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:context="http://www.springframework.org/schema/context"
    	xmlns:mvc="http://www.springframework.org/schema/mvc" 
    	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-3.0.xsd">
    	<!-- 配置SpringMVC -->
    	<!-- 1.开启SpringMVC注解模式 -->
    	<!-- 简化配置: 
    		(1)自动注册DefaultAnootationHandlerMapping,AnotationMethodHandlerAdapter 
    		(2)提供一些列:数据绑定,数字和日期的format @NumberFormat, @DateTimeFormat, xml,json默认读写支持 
    	-->
    	<mvc:annotation-driven />
    	
    	<!-- 2.静态资源默认servlet配置
    		(1)加入对静态资源的处理:js,gif,png
    		(2)允许使用"/"做整体映射
    	 -->
    	 <mvc:default-servlet-handler/>
    	 
    	 <!-- 3.配置jsp 显示ViewResolver -->
    	 <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    	 	<property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
    	 	<property name="prefix" value="/WEB-INF/jsp/" />
    	 	<property name="suffix" value=".jsp" />
    	 </bean>
    	 
    	 <!-- 4.扫描web相关的bean -->
    	 <context:component-scan base-package="com.soecode.lyf.web" />
    </beans>
    

    第四步:最后就是修改web.xml文件了,它在webappWEB-INF下。

    web.xml

    <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"
    	version="3.1" metadata-complete="true">
    	<!-- 如果是用mvn命令生成的xml,需要修改servlet版本为3.1 -->
    	<!-- 配置DispatcherServlet -->
    	<servlet>
    		<servlet-name>seckill-dispatcher</servlet-name>
    		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    		<!-- 配置springMVC需要加载的配置文件
    			spring-dao.xml,spring-service.xml,spring-web.xml
    			Mybatis - > spring -> springmvc
    		 -->
    		<init-param>
    			<param-name>contextConfigLocation</param-name>
    			<param-value>classpath:spring/spring-*.xml</param-value>
    		</init-param>
    	</servlet>
    	<servlet-mapping>
    		<servlet-name>seckill-dispatcher</servlet-name>
    		<!-- 默认匹配所有的请求 -->
    		<url-pattern>/</url-pattern>
    	</servlet-mapping>
    </web-app>
    
    

    我们在项目中经常会使用到日志,所以这里还有配置日志xml,在resources文件夹里新建logback.xml文件,所给出的日志输出格式也是最基本的控制台s呼出,大家有兴趣查看logback官方文档

    logback.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <configuration debug="true">
    	<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    		<!-- encoders are by default assigned the type ch.qos.logback.classic.encoder.PatternLayoutEncoder -->
    		<encoder>
    			<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
    		</encoder>
    	</appender>
    
    	<root level="debug">
    		<appender-ref ref="STDOUT" />
    	</root>
    </configuration>
    

    到目前为止,我们一共写了7个配置文件,我们一起来看下最终的配置文件结构图

    配置文件结构图


    SSM框架应用实例(图书管理系统)

    一开始想就这样结束教程,但是发现其实很多人都还不会把这个SSM框架用起来,特别是mybatis部分。那我现在就以最常见的“图书管理系统”中【查询图书】和【预约图书】业务来做一个demo吧!

    首先新建数据库名为ssm,再创建两张表:图书表book和预约图书表appointment,并且为book表初始化一些数据,sql如下。

    schema.sql

    -- 创建图书表
    CREATE TABLE `book` (
      `book_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '图书ID',
      `name` varchar(100) NOT NULL COMMENT '图书名称',
      `number` int(11) NOT NULL COMMENT '馆藏数量',
      PRIMARY KEY (`book_id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=1000 DEFAULT CHARSET=utf8 COMMENT='图书表'
    
    -- 初始化图书数据
    INSERT INTO `book` (`book_id`, `name`, `number`)
    VALUES
    	(1000, 'Java程序设计', 10),
    	(1001, '数据结构', 10),
    	(1002, '设计模式', 10),
    	(1003, '编译原理', 10)
    
    -- 创建预约图书表
    CREATE TABLE `appointment` (
      `book_id` bigint(20) NOT NULL COMMENT '图书ID',
      `student_id` bigint(20) NOT NULL COMMENT '学号',
      `appoint_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '预约时间' ,
      PRIMARY KEY (`book_id`, `student_id`),
      INDEX `idx_appoint_time` (`appoint_time`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='预约图书表'
    

    entity包中添加两个对应的实体,图书实体Book.java和预约图书实体Appointment.java

    Book.java

    package com.soecode.lyf.entity;
    
    public class Book {
    
    	private long bookId;// 图书ID
    
    	private String name;// 图书名称
    
    	private int number;// 馆藏数量
    
    	// 省略构造方法,getter和setter方法,toString方法
    
    }
    

    Appointment.java

    package com.soecode.lyf.entity;
    
    import java.util.Date;
    
    /**
     * 预约图书实体
     */
    public class Appointment {
    
    	private long bookId;// 图书ID
    
    	private long studentId;// 学号
    
    	private Date appointTime;// 预约时间
    
    	// 多对一的复合属性
    	private Book book;// 图书实体
    	
    	// 省略构造方法,getter和setter方法,toString方法
    
    }
    

    dao包新建接口BookDao.javaAppointment.java

    BookDao.java

    package com.soecode.lyf.dao;
    
    import java.util.List;
    
    import com.soecode.lyf.entity.Book;
    
    public interface BookDao {
    
    	/**
    	 * 通过ID查询单本图书
    	 * 
    	 * @param id
    	 * @return
    	 */
    	Book queryById(long id);
    
    	/**
    	 * 查询所有图书
    	 * 
    	 * @param offset 查询起始位置
    	 * @param limit 查询条数
    	 * @return
    	 */
    	List<Book> queryAll(@Param("offset") int offset, @Param("limit") int limit);
    
    	/**
    	 * 减少馆藏数量
    	 * 
    	 * @param bookId
    	 * @return 如果影响行数等于>1,表示更新的记录行数
    	 */
    	int reduceNumber(long bookId);
    }
    
    

    AppointmentDao.java

    package com.soecode.lyf.dao;
    
    import org.apache.ibatis.annotations.Param;
    
    import com.soecode.lyf.entity.Appointment;
    
    public interface AppointmentDao {
    
    	/**
    	 * 插入预约图书记录
    	 * 
    	 * @param bookId
    	 * @param studentId
    	 * @return 插入的行数
    	 */
    	int insertAppointment(@Param("bookId") long bookId, @Param("studentId") long studentId);
    
    	/**
    	 * 通过主键查询预约图书记录,并且携带图书实体
    	 * 
    	 * @param bookId
    	 * @param studentId
    	 * @return
    	 */
    	Appointment queryByKeyWithBook(@Param("bookId") long bookId, @Param("studentId") long studentId);
    
    }
    

    提示:这里为什么要给方法的参数添加@Param注解呢?是因为该方法有两个或以上的参数,一定要加,不然mybatis识别不了。上面的BookDao接口的queryById方法和reduceNumber方法只有一个参数book_id,所以可以不用加 @Param注解,当然加了也无所谓~


    注意,这里不需要实现dao接口不用编写daoImpl, mybatis会给我们动态实现,但是我们需要编写相应的mapper。
    mapper目录里新建两个文件BookDao.xmlAppointmentDao.xml,分别对应上面两个dao接口,代码如下。

    BookDao.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="com.soecode.lyf.dao.BookDao">
    	<!-- 目的:为dao接口方法提供sql语句配置 -->
    	<select id="queryById" resultType="Book" parameterType="long">
    		<!-- 具体的sql -->
    		SELECT
    			book_id,
    			name,
    			number
    		FROM
    			book
    		WHERE
    			book_id = #{bookId}
    	</select>
    	
    	<select id="queryAll" resultType="Book">
    		SELECT
    			book_id,
    			name,
    			number
    		FROM
    			book
    		ORDER BY
    			book_id
    		LIMIT #{offset}, #{limit}
    	</select>
    	
    	<update id="reduceNumber">
    		UPDATE book
    		SET number = number - 1
    		WHERE
    			book_id = #{bookId}
    		AND number > 0
    	</update>
    </mapper>
    

    AppointmentDao.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="com.soecode.lyf.dao.AppointmentDao">
    	<insert id="insertAppointment">
    		<!-- ignore 主键冲突,报错 -->
    		INSERT ignore INTO appointment (book_id, student_id)
    		VALUES (#{bookId}, #{studentId})
    	</insert>
    	
    	<select id="queryByKeyWithBook" resultType="Appointment">
    		<!-- 如何告诉MyBatis把结果映射到Appointment同时映射book属性 -->
    		<!-- 可以自由控制SQL -->
    		SELECT
    			a.book_id,
    			a.student_id,
    			a.appoint_time,
    			b.book_id "book.book_id",
    			b.`name` "book.name",
    			b.number "book.number"
    		FROM
    			appointment a
    		INNER JOIN book b ON a.book_id = b.book_id
    		WHERE
    			a.book_id = #{bookId}
    		AND a.student_id = #{studentId}
    	</select>
    </mapper>
    

    mapper总结namespace是该xml对应的接口全名,selectupdate中的id对应方法名,resultType是返回值类型,parameterType是参数类型(这个其实可选),最后#{...}中填写的是方法的参数,看懂了是不是很简单!!我也这么觉得~ 还有一个小技巧要交给大家,就是在返回Appointment对象包含了一个属性名为book的Book对象,那么可以使用"book.属性名"的方式来取值,看上面queryByKeyWithBook方法的sql。


    dao层写完了,接下来test对应的package写我们测试方法吧。
    因为我们之后会写很多测试方法,在测试前需要让程序读入spring-dao和mybatis等配置文件,所以我这里就抽离出来一个BaseTest类,只要是测试方法就继承它,这样那些繁琐的重复的代码就不用写那么多了~

    BaseTest.java

    package com.soecode.lyf;
    
    import org.junit.runner.RunWith;
    import org.springframework.test.context.ContextConfiguration;
    import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
    
    /**
     * 配置spring和junit整合,junit启动时加载springIOC容器 spring-test,junit
     */
    @RunWith(SpringJUnit4ClassRunner.class)
    // 告诉junit spring配置文件
    @ContextConfiguration({ "classpath:spring/spring-dao.xml", "classpath:spring/spring-service.xml" })
    public class BaseTest {
    
    }
    
    

    因为spring-serviceservice层的测试中会时候到,这里也一起引入算了!

    新建BookDaoTest.javaAppointmentDaoTest.java两个dao测试文件。

    BookDaoTest.java

    package com.soecode.lyf.dao;
    
    import java.util.List;
    
    import org.junit.Test;
    import org.springframework.beans.factory.annotation.Autowired;
    
    import com.soecode.lyf.BaseTest;
    import com.soecode.lyf.entity.Book;
    
    public class BookDaoTest extends BaseTest {
    
    	@Autowired
    	private BookDao bookDao;
    
    	@Test
    	public void testQueryById() throws Exception {
    		long bookId = 1000;
    		Book book = bookDao.queryById(bookId);
    		System.out.println(book);
    	}
    
    	@Test
    	public void testQueryAll() throws Exception {
    		List<Book> books = bookDao.queryAll(0, 4);
    		for (Book book : books) {
    			System.out.println(book);
    		}
    	}
    
    	@Test
    	public void testReduceNumber() throws Exception {
    		long bookId = 1000;
    		int update = bookDao.reduceNumber(bookId);
    		System.out.println("update=" + update);
    	}
    
    }
    

    BookDaoTest测试结果

    testQueryById
    testQueryById

    testQueryAll
    testQueryAll

    testReduceNumber
    testReduceNumber

    AppointmentDaoTest.java

    package com.soecode.lyf.dao;
    
    import org.junit.Test;
    import org.springframework.beans.factory.annotation.Autowired;
    
    import com.soecode.lyf.BaseTest;
    import com.soecode.lyf.entity.Appointment;
    
    public class AppointmentDaoTest extends BaseTest {
    
    	@Autowired
    	private AppointmentDao appointmentDao;
    
    	@Test
    	public void testInsertAppointment() throws Exception {
    		long bookId = 1000;
    		long studentId = 12345678910L;
    		int insert = appointmentDao.insertAppointment(bookId, studentId);
    		System.out.println("insert=" + insert);
    	}
    
    	@Test
    	public void testQueryByKeyWithBook() throws Exception {
    		long bookId = 1000;
    		long studentId = 12345678910L;
    		Appointment appointment = appointmentDao.queryByKeyWithBook(bookId, studentId);
    		System.out.println(appointment);
    		System.out.println(appointment.getBook());
    	}
    
    }
    

    AppointmentDaoTest测试结果

    testInsertAppointment
    testInsertAppointment

    testQueryByKeyWithBook
    testQueryByKeyWithBook


    嗯,到这里一切到很顺利那么我们继续service层的编码吧可能下面开始信息里比较大,大家要做好心理准备~

    首先,在写我们的控制器之前,我们先定义几个预约图书操作返回码的数据字典,也就是我们要返回给客户端的信息。我们这类使用枚举类,没听过的小伙伴要好好恶补一下了(我也是最近才学到的= =)

    预约业务操作返回码说明

    返回码 说明
    1 预约成功
    0 库存不足
    -1 重复预约
    -2 系统异常

    新建一个包叫enums,在里面新建一个枚举类AppointStateEnum.java,用来定义预约业务的数据字典,没听懂没关系,我们直接看代码吧~是不是感觉有模有样了!

    AppointStateEnum.java

    package com.soecode.lyf.enums;
    
    /**
     * 使用枚举表述常量数据字典
     */
    public enum AppointStateEnum {
    
    	SUCCESS(1, "预约成功"), NO_NUMBER(0, "库存不足"), REPEAT_APPOINT(-1, "重复预约"), INNER_ERROR(-2, "系统异常");
    
    	private int state;
    
    	private String stateInfo;
    
    	private AppointStateEnum(int state, String stateInfo) {
    		this.state = state;
    		this.stateInfo = stateInfo;
    	}
    
    	public int getState() {
    		return state;
    	}
    
    	public String getStateInfo() {
    		return stateInfo;
    	}
    
    	public static AppointStateEnum stateOf(int index) {
    		for (AppointStateEnum state : values()) {
    			if (state.getState() == index) {
    				return state;
    			}
    		}
    		return null;
    	}
    
    }
    

    接下来,在dto包下新建AppointExecution.java用来存储我们执行预约操作的返回结果。

    AppointExecution.java

    package com.soecode.lyf.dto;
    
    import com.soecode.lyf.entity.Appointment;
    import com.soecode.lyf.enums.AppointStateEnum;
    
    /**
     * 封装预约执行后结果
     */
    public class AppointExecution {
    
    	// 图书ID
    	private long bookId;
    
    	// 秒杀预约结果状态
    	private int state;
    
    	// 状态标识
    	private String stateInfo;
    
    	// 预约成功对象
    	private Appointment appointment;
    
    	public AppointExecution() {
    	}
    
    	// 预约失败的构造器
    	public AppointExecution(long bookId, AppointStateEnum stateEnum) {
    		this.bookId = bookId;
    		this.state = stateEnum.getState();
    		this.stateInfo = stateEnum.getStateInfo();
    	}
    
    	// 预约成功的构造器
    	public AppointExecution(long bookId, AppointStateEnum stateEnum, Appointment appointment) {
    		this.bookId = bookId;
    		this.state = stateEnum.getState();
    		this.stateInfo = stateEnum.getStateInfo();
    		this.appointment = appointment;
    	}
    	
    	// 省略getter和setter方法,toString方法
    
    }
    
    

    接着,在exception包下新建三个文件
    NoNumberException.java
    RepeatAppointException.java
    AppointException.java
    预约业务异常类(都需要继承RuntimeException),分别是无库存异常、重复预约异常、预约未知错误异常,用于业务层非成功情况下的返回(即成功返回结果,失败抛出异常)。

    NoNumberException.java

    package com.soecode.lyf.exception;
    
    /**
     * 库存不足异常
     */
    public class NoNumberException extends RuntimeException {
    
    	public NoNumberException(String message) {
    		super(message);
    	}
    
    	public NoNumberException(String message, Throwable cause) {
    		super(message, cause);
    	}
    
    }
    
    

    RepeatAppointException.java

    package com.soecode.lyf.exception;
    
    /**
     * 重复预约异常
     */
    public class RepeatAppointException extends RuntimeException {
    
    	public RepeatAppointException(String message) {
    		super(message);
    	}
    
    	public RepeatAppointException(String message, Throwable cause) {
    		super(message, cause);
    	}
    
    }
    
    

    AppointException.java

    package com.soecode.lyf.exception;
    
    /**
     * 预约业务异常
     */
    public class AppointException extends RuntimeException {
    
    	public AppointException(String message) {
    		super(message);
    	}
    
    	public AppointException(String message, Throwable cause) {
    		super(message, cause);
    	}
    
    }
    
    

    咱们终于可以编写业务代码了,在service包下新建BookService.java图书业务接口。

    BookService.java

    package com.soecode.lyf.service;
    
    import java.util.List;
    
    import com.soecode.lyf.dto.AppointExecution;
    import com.soecode.lyf.entity.Book;
    
    /**
     * 业务接口:站在"使用者"角度设计接口 三个方面:方法定义粒度,参数,返回类型(return 类型/异常)
     */
    public interface BookService {
    
    	/**
    	 * 查询一本图书
    	 * 
    	 * @param bookId
    	 * @return
    	 */
    	Book getById(long bookId);
    
    	/**
    	 * 查询所有图书
    	 * 
    	 * @return
    	 */
    	List<Book> getList();
    
    	/**
    	 * 预约图书
    	 * 
    	 * @param bookId
    	 * @param studentId
    	 * @return
    	 */
    	AppointExecution appoint(long bookId, long studentId);
    
    }
    

    service.impl包下新建BookServiceImpl.java使用BookService接口,并实现里面的方法。

    BookServiceImpl

    package com.soecode.lyf.service.impl;
    
    import java.util.List;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    import org.springframework.transaction.annotation.Transactional;
    
    import com.soecode.lyf.dao.AppointmentDao;
    import com.soecode.lyf.dao.BookDao;
    import com.soecode.lyf.dto.AppointExecution;
    import com.soecode.lyf.entity.Appointment;
    import com.soecode.lyf.entity.Book;
    import com.soecode.lyf.enums.AppointStateEnum;
    import com.soecode.lyf.exception.AppointException;
    import com.soecode.lyf.exception.NoNumberException;
    import com.soecode.lyf.exception.RepeatAppointException;
    import com.soecode.lyf.service.BookService;
    
    @Service
    public class BookServiceImpl implements BookService {
    
    	private Logger logger = LoggerFactory.getLogger(this.getClass());
    
    	// 注入Service依赖
    	@Autowired
    	private BookDao bookDao;
    
    	@Autowired
    	private AppointmentDao appointmentDao;
    
    
    	@Override
    	public Book getById(long bookId) {
    		return bookDao.queryById(bookId);
    	}
    
    	@Override
    	public List<Book> getList() {
    		return bookDao.queryAll(0, 1000);
    	}
    
    	@Override
    	@Transactional
    	/**
    	 * 使用注解控制事务方法的优点: 1.开发团队达成一致约定,明确标注事务方法的编程风格
    	 * 2.保证事务方法的执行时间尽可能短,不要穿插其他网络操作,RPC/HTTP请求或者剥离到事务方法外部
    	 * 3.不是所有的方法都需要事务,如只有一条修改操作,只读操作不需要事务控制
    	 */
    	public AppointExecution appoint(long bookId, long studentId) {
    		try {
    			// 减库存
    			int update = bookDao.reduceNumber(bookId);
    			if (update <= 0) {// 库存不足
    				//return new AppointExecution(bookId, AppointStateEnum.NO_NUMBER);//错误写法				
    				throw new NoNumberException("no number");
    			} else {
    				// 执行预约操作
    				int insert = appointmentDao.insertAppointment(bookId, studentId);
    				if (insert <= 0) {// 重复预约
    					//return new AppointExecution(bookId, AppointStateEnum.REPEAT_APPOINT);//错误写法
    					throw new RepeatAppointException("repeat appoint");
    				} else {// 预约成功
    					Appointment appointment = appointmentDao.queryByKeyWithBook(bookId, studentId);
    					return new AppointExecution(bookId, AppointStateEnum.SUCCESS, appointment);
    				}
    			}
    		// 要先于catch Exception异常前先catch住再抛出,不然自定义的异常也会被转换为AppointException,导致控制层无法具体识别是哪个异常
    		} catch (NoNumberException e1) {
    			throw e1;
    		} catch (RepeatAppointException e2) {
    			throw e2;
    		} catch (Exception e) {
    			logger.error(e.getMessage(), e);
    			// 所有编译期异常转换为运行期异常
    			//return new AppointExecution(bookId, AppointStateEnum.INNER_ERROR);//错误写法
    			throw new AppointException("appoint inner error:" + e.getMessage());
    		}
    	}
    
    }
    
    

    下面我们来测试一下我们的业务代码吧~因为查询图书的业务不复杂,所以这里只演示我们最重要的预约图书业务!!

    BookServiceImplTest.java

    package com.soecode.lyf.service.impl;
    
    import static org.junit.Assert.fail;
    
    import org.junit.Test;
    import org.springframework.beans.factory.annotation.Autowired;
    
    import com.soecode.lyf.BaseTest;
    import com.soecode.lyf.dto.AppointExecution;
    import com.soecode.lyf.service.BookService;
    
    public class BookServiceImplTest extends BaseTest {
    
    	@Autowired
    	private BookService bookService;
    
    	@Test
    	public void testAppoint() throws Exception {
    		long bookId = 1001;
    		long studentId = 12345678910L;
    		AppointExecution execution = bookService.appoint(bookId, studentId);
    		System.out.println(execution);
    	}
    
    }
    
    

    BookServiceImplTest测试结果

    testAppointtestAppoint

    首次执行是“预约成功”,如果再次执行的话,应该会出现“重复预约”,哈哈,我们所有的后台代码都通过单元测试啦~~是不是很开心~


    咱们还需要在dto包里新建一个封装json返回结果的类Result.java,设计成泛型。

    Result.java

    package com.soecode.lyf.dto;
    
    /**
     * 封装json对象,所有返回结果都使用它
     */
    public class Result<T> {
    
    	private boolean success;// 是否成功标志
    
    	private T data;// 成功时返回的数据
    
    	private String error;// 错误信息
    
    	public Result() {
    	}
    
    	// 成功时的构造器
    	public Result(boolean success, T data) {
    		this.success = success;
    		this.data = data;
    	}
    
    	// 错误时的构造器
    	public Result(boolean success, String error) {
    		this.success = success;
    		this.error = error;
    	}
    
    	// 省略getter和setter方法
    }
    
    

    最后,我们写web层,也就是controller,我们在web包下新建BookController.java文件。

    BookController.java

    package com.soecode.lyf.web;
    
    import java.util.List;
    
    import org.apache.ibatis.annotations.Param;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Controller;
    import org.springframework.ui.Model;
    import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    import org.springframework.web.bind.annotation.ResponseBody;
    
    import com.soecode.lyf.dto.AppointExecution;
    import com.soecode.lyf.dto.Result;
    import com.soecode.lyf.entity.Book;
    import com.soecode.lyf.enums.AppointStateEnum;
    import com.soecode.lyf.exception.NoNumberException;
    import com.soecode.lyf.exception.RepeatAppointException;
    import com.soecode.lyf.service.BookService;
    
    @Controller
    @RequestMapping("/book") // url:/模块/资源/{id}/细分 /seckill/list
    public class BookController {
    
    	private Logger logger = LoggerFactory.getLogger(this.getClass());
    
    	@Autowired
    	private BookService bookService;
    
    	@RequestMapping(value = "/list", method = RequestMethod.GET)
    	private String list(Model model) {
    		List<Book> list = bookService.getList();
    		model.addAttribute("list", list);
    		// list.jsp + model = ModelAndView
    		return "list";// WEB-INF/jsp/"list".jsp
    	}
    
    	@RequestMapping(value = "/{bookId}/detail", method = RequestMethod.GET)
    	private String detail(@PathVariable("bookId") Long bookId, Model model) {
    		if (bookId == null) {
    			return "redirect:/book/list";
    		}
    		Book book = bookService.getById(bookId);
    		if (book == null) {
    			return "forward:/book/list";
    		}
    		model.addAttribute("book", book);
    		return "detail";
    	}
    
    	//ajax json
    	@RequestMapping(value = "/{bookId}/appoint", method = RequestMethod.POST, produces = {
    			"application/json; charset=utf-8" })
    	@ResponseBody
    	private Result<AppointExecution> appoint(@PathVariable("bookId") Long bookId, @RequestParam("studentId") Long studentId) {
    		if (studentId == null || studentId.equals("")) {
    			return new Result<>(false, "学号不能为空");
    		}
    		//AppointExecution execution = bookService.appoint(bookId, studentId);//错误写法,不能统一返回,要处理异常(失败)情况
    		AppointExecution execution = null;
    		try {
    			execution = bookService.appoint(bookId, studentId);
    		} catch (NoNumberException e1) {
    			execution = new AppointExecution(bookId, AppointStateEnum.NO_NUMBER);
    		} catch (RepeatAppointException e2) {
    			execution = new AppointExecution(bookId, AppointStateEnum.REPEAT_APPOINT);
    		} catch (Exception e) {
    			execution = new AppointExecution(bookId, AppointStateEnum.INNER_ERROR);
    		}
    		return new Result<AppointExecution>(true, execution);
    	}
    
    }
    
    

    因为我比较懒,所以我们就不测试controller了,好讨厌写前端,呜呜呜~

    到此,我们的SSM框架整合配置,与应用实例部分已经结束了,我把所有源码和jar包一起打包放在了我的GitHub上,需要的可以去下载,喜欢就给个star吧,这篇东西写了两个晚上也不容易啊。

    完整代码下载地址:https://github.com/liyifeng1994/ssm


    2017-02-28更新(感谢网友EchoXml发现):
    修改预约业务代码,失败时抛异常,成功时才返回结果,控制层根据捕获的异常返回相应信息给客户端,而不是业务层直接返回错误结果。上面的代码已经作了修改,而且错误示范也注释保留着,之前误人子弟了,还好有位网友前几天提出质疑,我也及时做了修改。

    2017-03-30更新(感谢网友ergeerge1建议):
    修改BookController几处错误
    1.detail方法不是返回json的,故不用加@ResponseBody注解
    2.appoint方法应该加上@ResponseBody注解
    3.另外studentId参数注解应该是@RequestParam
    4.至于controller测试,测试appoint方法可不必写jsp,用curl就行,比如
    curl -H “Accept: application/json; charset=utf-8” -d “studentId=1234567890” localhost:8080/book/1003/appoint

    展开全文
  • SSM框架——详细整合教程(Spring+SpringMVC+MyBatis)

    万次阅读 多人点赞 2015-03-19 11:45:00
    使用SSM(Spring、SpringMVC和Mybatis)已经有三个多月了,项目在技术上已经没有什么难点了,基于现有的技术就可以实现想要的功能,当然肯定有很多可以改进的地方。之前没有记录SSM整合的过程,这次刚刚好基于自己的...

    使用SSMSpringSpringMVCMybatis)已经有三个多月了,项目在技术上已经没有什么难点了,基于现有的技术就可以实现想要的功能,当然肯定有很多可以改进的地方。之前没有记录SSM整合的过程,这次刚刚好基于自己的一个小项目重新搭建了一次,而且比项目搭建的要更好一些。以前解决问题的过程和方法并没有及时记录,以后在自己的小项目中遇到我再整理分享一下。这次先说说三大框架整合过程。个人认为使用框架并不是很难,关键要理解其思想,这对于我们提高编程水平很有帮助。不过,如果用都不会,谈思想就变成纸上谈兵了!!!先技术,再思想。实践出真知。(可通过图片水印查看博客地址)


    1、基本概念


    1.1、Spring


            Spring是一个开源框架,Spring是于2003 年兴起的一个轻量级的Java 开发框架,由Rod Johnson 在其著作Expert One-On-One J2EE Development and Design中阐述的部分理念和原型衍生而来。它是为了解决企业应用开发的复杂性而创建的。Spring使用基本的JavaBean来完成以前只可能由EJB完成的事情。然而,Spring的用途不仅限于服务器端的开发。从简单性、可测试性和松耦合的角度而言,任何Java应用都可以从Spring中受益。 简单来说,Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架。


    1.2、SpringMVC

         

            Spring MVC属于SpringFrameWork的后续产品,已经融合在Spring Web Flow里面。Spring MVC 分离了控制器、模型对象、分派器以及处理程序对象的角色,这种分离让它们更容易进行定制。


    1.3、MyBatis


           MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis MyBatis是一个基于Java持久层框架。iBATIS提供的持久层框架包括SQL MapsData Access ObjectsDAOMyBatis 消除了几乎所有的JDBC代码和参数的手工设置以及结果集的检索。MyBatis 使用简单的 XML或注解用于配置和原始映射,将接口和 Java POJOsPlain Old Java Objects,普通的 Java对象)映射成数据库中的记录。



    2、开发环境搭建



    如果需要,参看之前的博文:http://blog.csdn.net/zhshulin/article/details/30779873



    3、Maven Web项目创建


    如果需要,参看之前的博文:http://blog.csdn.net/zhshulin/article/details/37921705



    4、SSM整合

          

            下面主要介绍三大框架的整合,至于环境的搭建以及项目的创建,参看上面的博文。这次整合我分了2个配置文件,分别是spring-mybatis.xml,包含springmybatis的配置文件,还有个是spring-mvc的配置文件,此外有2个资源文件jdbc.propertislog4j.properties。完整目录结构如下(最后附上源码下载地址,不建议直接使用源码,因为此教程已经有了全部代码):


    使用框架都是较新的版本

           Spring 4.0.2 RELEASE

           Spring MVC 4.0.2 RELEASE

           MyBatis 3.2.6


    4.1、Maven引入需要的JAR包

             为了方便后面说的时候不需要引入JAR包,我这里直接给出所有需要的JAR包,这都是基本的JAR包,每个包的是干什么的都有注释,就不再多说了。

    pom.xml

    1. <properties>  
    2.         <!-- spring版本号 -->  
    3.         <spring.version>4.0.2.RELEASE</spring.version>  
    4.         <!-- mybatis版本号 -->  
    5.         <mybatis.version>3.2.6</mybatis.version>  
    6.         <!-- log4j日志文件管理包版本 -->  
    7.         <slf4j.version>1.7.7</slf4j.version>  
    8.         <log4j.version>1.2.17</log4j.version>  
    9.     </properties>  
    10.   
    11.     <dependencies>  
    12.         <dependency>  
    13.             <groupId>junit</groupId>  
    14.             <artifactId>junit</artifactId>  
    15.             <version>4.11</version>  
    16.             <!-- 表示开发的时候引入,发布的时候不会加载此包 -->  
    17.             <scope>test</scope>  
    18.         </dependency>  
    19.         <!-- spring核心包 -->  
    20.         <dependency>  
    21.             <groupId>org.springframework</groupId>  
    22.             <artifactId>spring-core</artifactId>  
    23.             <version>${spring.version}</version>  
    24.         </dependency>  
    25.   
    26.         <dependency>  
    27.             <groupId>org.springframework</groupId>  
    28.             <artifactId>spring-web</artifactId>  
    29.             <version>${spring.version}</version>  
    30.         </dependency>  
    31.         <dependency>  
    32.             <groupId>org.springframework</groupId>  
    33.             <artifactId>spring-oxm</artifactId>  
    34.             <version>${spring.version}</version>  
    35.         </dependency>  
    36.         <dependency>  
    37.             <groupId>org.springframework</groupId>  
    38.             <artifactId>spring-tx</artifactId>  
    39.             <version>${spring.version}</version>  
    40.         </dependency>  
    41.   
    42.         <dependency>  
    43.             <groupId>org.springframework</groupId>  
    44.             <artifactId>spring-jdbc</artifactId>  
    45.             <version>${spring.version}</version>  
    46.         </dependency>  
    47.   
    48.         <dependency>  
    49.             <groupId>org.springframework</groupId>  
    50.             <artifactId>spring-webmvc</artifactId>  
    51.             <version>${spring.version}</version>  
    52.         </dependency>  
    53.         <dependency>  
    54.             <groupId>org.springframework</groupId>  
    55.             <artifactId>spring-aop</artifactId>  
    56.             <version>${spring.version}</version>  
    57.         </dependency>  
    58.   
    59.         <dependency>  
    60.             <groupId>org.springframework</groupId>  
    61.             <artifactId>spring-context-support</artifactId>  
    62.             <version>${spring.version}</version>  
    63.         </dependency>  
    64.   
    65.         <dependency>  
    66.             <groupId>org.springframework</groupId>  
    67.             <artifactId>spring-test</artifactId>  
    68.             <version>${spring.version}</version>  
    69.         </dependency>  
    70.         <!-- mybatis核心包 -->  
    71.         <dependency>  
    72.             <groupId>org.mybatis</groupId>  
    73.             <artifactId>mybatis</artifactId>  
    74.             <version>${mybatis.version}</version>  
    75.         </dependency>  
    76.         <!-- mybatis/spring包 -->  
    77.         <dependency>  
    78.             <groupId>org.mybatis</groupId>  
    79.             <artifactId>mybatis-spring</artifactId>  
    80.             <version>1.2.2</version>  
    81.         </dependency>  
    82.         <!-- 导入java ee jar 包 -->  
    83.         <dependency>  
    84.             <groupId>javax</groupId>  
    85.             <artifactId>javaee-api</artifactId>  
    86.             <version>7.0</version>  
    87.         </dependency>  
    88.         <!-- 导入Mysql数据库链接jar包 -->  
    89.         <dependency>  
    90.             <groupId>mysql</groupId>  
    91.             <artifactId>mysql-connector-java</artifactId>  
    92.             <version>5.1.30</version>  
    93.         </dependency>  
    94.         <!-- 导入dbcp的jar包,用来在applicationContext.xml中配置数据库 -->  
    95.         <dependency>  
    96.             <groupId>commons-dbcp</groupId>  
    97.             <artifactId>commons-dbcp</artifactId>  
    98.             <version>1.2.2</version>  
    99.         </dependency>  
    100.         <!-- JSTL标签类 -->  
    101.         <dependency>  
    102.             <groupId>jstl</groupId>  
    103.             <artifactId>jstl</artifactId>  
    104.             <version>1.2</version>  
    105.         </dependency>  
    106.         <!-- 日志文件管理包 -->  
    107.         <!-- log start -->  
    108.         <dependency>  
    109.             <groupId>log4j</groupId>  
    110.             <artifactId>log4j</artifactId>  
    111.             <version>${log4j.version}</version>  
    112.         </dependency>  
    113.           
    114.           
    115.         <!-- 格式化对象,方便输出日志 -->  
    116.         <dependency>  
    117.             <groupId>com.alibaba</groupId>  
    118.             <artifactId>fastjson</artifactId>  
    119.             <version>1.1.41</version>  
    120.         </dependency>  
    121.   
    122.   
    123.         <dependency>  
    124.             <groupId>org.slf4j</groupId>  
    125.             <artifactId>slf4j-api</artifactId>  
    126.             <version>${slf4j.version}</version>  
    127.         </dependency>  
    128.   
    129.         <dependency>  
    130.             <groupId>org.slf4j</groupId>  
    131.             <artifactId>slf4j-log4j12</artifactId>  
    132.             <version>${slf4j.version}</version>  
    133.         </dependency>  
    134.         <!-- log end -->  
    135.         <!-- 映入JSON -->  
    136.         <dependency>  
    137.             <groupId>org.codehaus.jackson</groupId>  
    138.             <artifactId>jackson-mapper-asl</artifactId>  
    139.             <version>1.9.13</version>  
    140.         </dependency>  
    141.         <!-- 上传组件包 -->  
    142.         <dependency>  
    143.             <groupId>commons-fileupload</groupId>  
    144.             <artifactId>commons-fileupload</artifactId>  
    145.             <version>1.3.1</version>  
    146.         </dependency>  
    147.         <dependency>  
    148.             <groupId>commons-io</groupId>  
    149.             <artifactId>commons-io</artifactId>  
    150.             <version>2.4</version>  
    151.         </dependency>  
    152.         <dependency>  
    153.             <groupId>commons-codec</groupId>  
    154.             <artifactId>commons-codec</artifactId>  
    155.             <version>1.9</version>  
    156.         </dependency>  
    157.           
    158.           
    159.     </dependencies>  

    4.2、Spring与MyBatis的整合

    所有需要的JAR包都引入以后,首先进行SpringMyBatis的整合,然后再进行JUnit测试,先看一个项目结构图:


    4.2.1、建立JDBC属性文件

    jdbc.properties(文件编码修改为utf-8

    1. driver=com.mysql.jdbc.Driver  
    2. url=jdbc:mysql://10.221.10.111:8080/db_zsl  
    3. username=demao  
    4. password=demao  
    5. #定义初始连接数  
    6. initialSize=0  
    7. #定义最大连接数  
    8. maxActive=20  
    9. #定义最大空闲  
    10. maxIdle=20  
    11. #定义最小空闲  
    12. minIdle=1  
    13. #定义最长等待时间  
    14. maxWait=60000  

    4.2.2、建立spring-mybatis.xml配置文件

            这个文件就是用来完成spring和mybatis的整合的。这里面也没多少行配置,主要的就是自动扫描,自动注入,配置数据库。注释也很详细,大家看看就明白了。

    spring-mybatis.xml

    1. <?xml version="1.0" encoding="UTF-8"?>  
    2. <beans xmlns="http://www.springframework.org/schema/beans"  
    3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"  
    4.     xmlns:context="http://www.springframework.org/schema/context"  
    5.     xmlns:mvc="http://www.springframework.org/schema/mvc"  
    6.     xsi:schemaLocation="http://www.springframework.org/schema/beans    
    7.                         http://www.springframework.org/schema/beans/spring-beans-3.1.xsd    
    8.                         http://www.springframework.org/schema/context    
    9.                         http://www.springframework.org/schema/context/spring-context-3.1.xsd    
    10.                         http://www.springframework.org/schema/mvc    
    11.                         http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd">  
    12.     <!-- 自动扫描 -->  
    13.     <context:component-scan base-package="com.cn.hnust" />  
    14.     <!-- 引入配置文件 -->  
    15.     <bean id="propertyConfigurer"  
    16.         class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">  
    17.         <property name="location" value="classpath:jdbc.properties" />  
    18.     </bean>  
    19.   
    20.     <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"  
    21.         destroy-method="close">  
    22.         <property name="driverClassName" value="${driver}" />  
    23.         <property name="url" value="${url}" />  
    24.         <property name="username" value="${username}" />  
    25.         <property name="password" value="${password}" />  
    26.         <!-- 初始化连接大小 -->  
    27.         <property name="initialSize" value="${initialSize}"></property>  
    28.         <!-- 连接池最大数量 -->  
    29.         <property name="maxActive" value="${maxActive}"></property>  
    30.         <!-- 连接池最大空闲 -->  
    31.         <property name="maxIdle" value="${maxIdle}"></property>  
    32.         <!-- 连接池最小空闲 -->  
    33.         <property name="minIdle" value="${minIdle}"></property>  
    34.         <!-- 获取连接最大等待时间 -->  
    35.         <property name="maxWait" value="${maxWait}"></property>  
    36.     </bean>  
    37.   
    38.     <!-- spring和MyBatis完美整合,不需要mybatis的配置映射文件 -->  
    39.     <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">  
    40.         <property name="dataSource" ref="dataSource" />  
    41.         <!-- 自动扫描mapping.xml文件 -->  
    42.         <property name="mapperLocations" value="classpath:com/cn/hnust/mapping/*.xml"></property>  
    43.     </bean>  
    44.   
    45.     <!-- DAO接口所在包名,Spring会自动查找其下的类 -->  
    46.     <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">  
    47.         <property name="basePackage" value="com.cn.hnust.dao" />  
    48.         <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>  
    49.     </bean>  
    50.   
    51.     <!-- (事务管理)transaction manager, use JtaTransactionManager for global tx -->  
    52.     <bean id="transactionManager"  
    53.         class="org.springframework.jdbc.datasource.DataSourceTransactionManager">  
    54.         <property name="dataSource" ref="dataSource" />  
    55.     </bean>  
    56.   
    57. </beans>  


    4.2.3、Log4j的配置


          为了方便调试,一般都会使用日志来输出信息,Log4j是Apache的一个开放源代码项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控制台、文件、GUI组件,甚至是套接口服务器、NT的事件记录器、UNIX Syslog守护进程等;我们也可以控制每一条日志的输出格式;通过定义每一条日志信息的级别,我们能够更加细致地控制日志的生成过程。

          Log4j的配置很简单,而且也是通用的,下面给出一个基本的配置,换到其他项目中也无需做多大的调整,如果想做调整或者想了解Log4j的各种配置,参看我转载的一篇博文,很详细:

    http://blog.csdn.net/zhshulin/article/details/37937365

    下面给出配置文件目录:


    log4j.properties

    1. #定义LOG输出级别  
    2. log4j.rootLogger=INFO,Console,File  
    3. #定义日志输出目的地为控制台  
    4. log4j.appender.Console=org.apache.log4j.ConsoleAppender  
    5. log4j.appender.Console.Target=System.out  
    6. #可以灵活地指定日志输出格式,下面一行是指定具体的格式  
    7. log4j.appender.Console.layout = org.apache.log4j.PatternLayout  
    8. log4j.appender.Console.layout.ConversionPattern=[%c] - %m%n  
    9.   
    10. #文件大小到达指定尺寸的时候产生一个新的文件  
    11. log4j.appender.File = org.apache.log4j.RollingFileAppender  
    12. #指定输出目录  
    13. log4j.appender.File.File = logs/ssm.log  
    14. #定义文件最大大小  
    15. log4j.appender.File.MaxFileSize = 10MB  
    16. # 输出所以日志,如果换成DEBUG表示输出DEBUG以上级别日志  
    17. log4j.appender.File.Threshold = ALL  
    18. log4j.appender.File.layout = org.apache.log4j.PatternLayout  
    19. log4j.appender.File.layout.ConversionPattern =[%p] [%d{yyyy-MM-dd HH\:mm\:ss}][%c]%m%n  

    4.2.4、JUnit测试


          经过以上步骤(到4.2.2,log4j不配也没影响),我们已经完成了Spring和mybatis的整合,这样我们就可以编写一段测试代码来试试是否成功了。



    4.2.4.1、创建测试用表

    既然我们需要测试,那么我们就需要建立在数据库中建立一个测试表,这个表建的很简单,SQL语句为:

    1. DROP TABLE IF EXISTS `user_t`;  
    2.   
    3. CREATE TABLE `user_t` (  
    4.   `id` int(11) NOT NULL AUTO_INCREMENT,  
    5.   `user_name` varchar(40) NOT NULL,  
    6.   `passwordvarchar(255) NOT NULL,  
    7.   `age` int(4) NOT NULL,  
    8.   PRIMARY KEY (`id`)  
    9. ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;  
    10.   
    11. /*Data for the table `user_t` */  
    12.   
    13. insert  into `user_t`(`id`,`user_name`,`password`,`age`) values (1,'测试','sfasgfaf',24);  

    4.2.4.2、利用MyBatis Generator自动创建代码

    参考博文:http://blog.csdn.net/zhshulin/article/details/23912615


           这个可根据表自动创建实体类、MyBatis映射文件以及DAO接口,当然,我习惯将生成的接口名改为IUserDao,而不是直接用它生成的UserMapper。如果不想麻烦就可以不改。完成后将文件复制到工程中。如图:

    4.2.4.3、建立Service接口和实现类

    目录结构:


    下面给出具体的内容:

    IUserService.jave

    1. package com.cn.hnust.service;  
    2.   
    3. import com.cn.hnust.pojo.User;  
    4.   
    5. public interface IUserService {  
    6.     public User getUserById(int userId);  
    7. }  

    UserServiceImpl.java

    1. package com.cn.hnust.service.impl;  
    2.   
    3. import javax.annotation.Resource;  
    4.   
    5. import org.springframework.stereotype.Service;  
    6.   
    7. import com.cn.hnust.dao.IUserDao;  
    8. import com.cn.hnust.pojo.User;  
    9. import com.cn.hnust.service.IUserService;  
    10.   
    11. @Service("userService")  
    12. public class UserServiceImpl implements IUserService {  
    13.     @Resource  
    14.     private IUserDao userDao;  
    15.     @Override  
    16.     public User getUserById(int userId) {  
    17.         // TODO Auto-generated method stub  
    18.         return this.userDao.selectByPrimaryKey(userId);  
    19.     }  
    20.   
    21. }  

    4.2.4.4、建立测试类

           测试类在src/test/java中建立,下面测试类中注释掉的部分是不使用Spring时,一般情况下的一种测试方法;如果使用了Spring那么就可以使用注解的方式来引入配置文件和类,然后再将service接口对象注入,就可以进行测试了。

           如果测试成功,表示SpringMybatis已经整合成功了。输出信息使用的是Log4j打印到控制台。


    1. package org.zsl.testmybatis;  
    2.   
    3. import javax.annotation.Resource;  
    4.   
    5. import org.apache.log4j.Logger;  
    6. import org.junit.Before;  
    7. import org.junit.Test;  
    8. import org.junit.runner.RunWith;  
    9. import org.springframework.context.ApplicationContext;  
    10. import org.springframework.context.support.ClassPathXmlApplicationContext;  
    11. import org.springframework.test.context.ContextConfiguration;  
    12. import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;  
    13.   
    14. import com.alibaba.fastjson.JSON;  
    15. import com.cn.hnust.pojo.User;  
    16. import com.cn.hnust.service.IUserService;  
    17.   
    18. @RunWith(SpringJUnit4ClassRunner.class)     //表示继承了SpringJUnit4ClassRunner类  
    19. @ContextConfiguration(locations = {"classpath:spring-mybatis.xml"})  
    20.   
    21. public class TestMyBatis {  
    22.     private static Logger logger = Logger.getLogger(TestMyBatis.class);  
    23. //  private ApplicationContext ac = null;  
    24.     @Resource  
    25.     private IUserService userService = null;  
    26.   
    27. //  @Before  
    28. //  public void before() {  
    29. //      ac = new ClassPathXmlApplicationContext("applicationContext.xml");  
    30. //      userService = (IUserService) ac.getBean("userService");  
    31. //  }  
    32.   
    33.     @Test  
    34.     public void test1() {  
    35.         User user = userService.getUserById(1);  
    36.         // System.out.println(user.getUserName());  
    37.         // logger.info("值:"+user.getUserName());  
    38.         logger.info(JSON.toJSONString(user));  
    39.     }  
    40. }  

    测试结果:



    至此,完成Spring和mybatis这两大框架的整合,下面在继续进行SpringMVC的整合。


    4.3、整合SpringMVC

             上面已经完成了2大框架的整合,SpringMVC的配置文件单独放,然后在web.xml中配置整合。

    4.3.1、配置spring-mvc.xml

    配置里面的注释也很详细,在此就不说了,主要是自动扫描控制器,视图模式,注解的启动这三个。

    1. <?xml version="1.0" encoding="UTF-8"?>  
    2. <beans xmlns="http://www.springframework.org/schema/beans"  
    3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"  
    4.     xmlns:context="http://www.springframework.org/schema/context"  
    5.     xmlns:mvc="http://www.springframework.org/schema/mvc"  
    6.     xsi:schemaLocation="http://www.springframework.org/schema/beans    
    7.                         http://www.springframework.org/schema/beans/spring-beans-3.1.xsd    
    8.                         http://www.springframework.org/schema/context    
    9.                         http://www.springframework.org/schema/context/spring-context-3.1.xsd    
    10.                         http://www.springframework.org/schema/mvc    
    11.                         http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd">  
    12.     <!-- 自动扫描该包,使SpringMVC认为包下用了@controller注解的类是控制器 -->  
    13.     <context:component-scan base-package="com.cn.hnust.controller" />  
    14.     <!--避免IE执行AJAX时,返回JSON出现下载文件 -->  
    15.     <bean id="mappingJacksonHttpMessageConverter"  
    16.         class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">  
    17.         <property name="supportedMediaTypes">  
    18.             <list>  
    19.                 <value>text/html;charset=UTF-8</value>  
    20.             </list>  
    21.         </property>  
    22.     </bean>  
    23.     <!-- 启动SpringMVC的注解功能,完成请求和注解POJO的映射 -->  
    24.     <bean  
    25.         class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">  
    26.         <property name="messageConverters">  
    27.             <list>  
    28.                 <ref bean="mappingJacksonHttpMessageConverter" /> <!-- JSON转换器 -->  
    29.             </list>  
    30.         </property>  
    31.     </bean>  
    32.     <!-- 定义跳转的文件的前后缀 ,视图模式配置-->  
    33.     <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">  
    34.         <!-- 这里的配置我的理解是自动给后面action的方法return的字符串加上前缀和后缀,变成一个 可用的url地址 -->  
    35.         <property name="prefix" value="/WEB-INF/jsp/" />  
    36.         <property name="suffix" value=".jsp" />  
    37.     </bean>  
    38.       
    39.     <!-- 配置文件上传,如果没有使用文件上传可以不用配置,当然如果不配,那么配置文件中也不必引入上传组件包 -->  
    40.     <bean id="multipartResolver"    
    41.         class="org.springframework.web.multipart.commons.CommonsMultipartResolver">    
    42.         <!-- 默认编码 -->  
    43.         <property name="defaultEncoding" value="utf-8" />    
    44.         <!-- 文件大小最大值 -->  
    45.         <property name="maxUploadSize" value="10485760000" />    
    46.         <!-- 内存中的最大值 -->  
    47.         <property name="maxInMemorySize" value="40960" />    
    48.     </bean>   
    49.   
    50. </beans>  

    4.3.2、配置web.xml文件

             这里面对spring-mybatis.xml的引入以及配置的spring-mvc的Servlet就是为了完成SSM整合,之前2框架整合不需要在此处进行任何配置。配置一样有详细注释,不多解释了。


    web.xml

    1. <?xml version="1.0" encoding="UTF-8"?>  
    2. <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
    3.     xmlns="http://java.sun.com/xml/ns/javaee"  
    4.     xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"  
    5.     version="3.0">  
    6.     <display-name>Archetype Created Web Application</display-name>  
    7.     <!-- Spring和mybatis的配置文件 -->  
    8.     <context-param>  
    9.         <param-name>contextConfigLocation</param-name>  
    10.         <param-value>classpath:spring-mybatis.xml</param-value>  
    11.     </context-param>  
    12.     <!-- 编码过滤器 -->  
    13.     <filter>  
    14.         <filter-name>encodingFilter</filter-name>  
    15.         <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>  
    16.         <async-supported>true</async-supported>  
    17.         <init-param>  
    18.             <param-name>encoding</param-name>  
    19.             <param-value>UTF-8</param-value>  
    20.         </init-param>  
    21.     </filter>  
    22.     <filter-mapping>  
    23.         <filter-name>encodingFilter</filter-name>  
    24.         <url-pattern>/*</url-pattern>  
    25.     </filter-mapping>  
    26.     <!-- Spring监听器 -->  
    27.     <listener>  
    28.         <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>  
    29.     </listener>  
    30.     <!-- 防止Spring内存溢出监听器 -->  
    31.     <listener>  
    32.         <listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class>  
    33.     </listener>  
    34.   
    35.     <!-- Spring MVC servlet -->  
    36.     <servlet>  
    37.         <servlet-name>SpringMVC</servlet-name>  
    38.         <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>  
    39.         <init-param>  
    40.             <param-name>contextConfigLocation</param-name>  
    41.             <param-value>classpath:spring-mvc.xml</param-value>  
    42.         </init-param>  
    43.         <load-on-startup>1</load-on-startup>  
    44.         <async-supported>true</async-supported>  
    45.     </servlet>  
    46.     <servlet-mapping>  
    47.         <servlet-name>SpringMVC</servlet-name>  
    48.         <!-- 此处可以可以配置成*.do,对应struts的后缀习惯 -->  
    49.         <url-pattern>/</url-pattern>  
    50.     </servlet-mapping>  
    51.     <welcome-file-list>  
    52.         <welcome-file>/index.jsp</welcome-file>  
    53.     </welcome-file-list>  
    54.   
    55. </web-app>  

    4.3.3、测试

            至此已经完成了SSM三大框架的整合了,接下来测试一下,如果成功了,那么恭喜你,如果失败了,继续调试吧,作为程序员就是不停的与BUG做斗争


    4.3.3.1、新建jsp页面


    showUser.jsp   此页面仅输出一下用户名,完成一个完整的简单流程

    1. <%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>  
    2. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">  
    3. <html>  
    4.   <head>  
    5.     <title>测试</title>  
    6.   </head>  
    7.     
    8.   <body>  
    9.     ${user.userName}  
    10.   </body>  
    11. </html>  

    4.3.3.2、建立UserController类

    UserController.java  控制器

    1. package com.cn.hnust.controller;  
    2.   
    3. import javax.annotation.Resource;  
    4. import javax.servlet.http.HttpServletRequest;  
    5.   
    6. import org.springframework.stereotype.Controller;  
    7. import org.springframework.ui.Model;  
    8. import org.springframework.web.bind.annotation.RequestMapping;  
    9.   
    10. import com.cn.hnust.pojo.User;  
    11. import com.cn.hnust.service.IUserService;  
    12.   
    13. @Controller  
    14. @RequestMapping("/user")  
    15. public class UserController {  
    16.     @Resource  
    17.     private IUserService userService;  
    18.       
    19.     @RequestMapping("/showUser")  
    20.     public String toIndex(HttpServletRequest request,Model model){  
    21.         int userId = Integer.parseInt(request.getParameter("id"));  
    22.         User user = this.userService.getUserById(userId);  
    23.         model.addAttribute("user", user);  
    24.         return "showUser";  
    25.     }  
    26. }  

    4.3.3.3、部署项目

    输入地址:localhost:8080/项目名称/user/showUser?id=1

    至此,SSM三大框架的整合就完成了,在此基础上可再添加其他功能。


    源码下载地址:http://download.csdn.net/detail/u012909091/7658611


     (转载注明出处:http://blog.csdn.net/zhshulin

    展开全文
  • SSM框架原理,作用及使用方法

    万次阅读 多人点赞 2017-10-22 19:55:28
    SSM框架是spring MVC ,spring和mybatis框架的整合,是标准的MVC模式,将整个系统划分为表现层,controller层,service层,DAO层四层 使用spring MVC负责请求的转发和视图管理 spring实现业务对象管理,mybatis作为...

    作用

    SSM框架是spring MVC ,spring和mybatis框架的整合,是标准的MVC模式,将整个系统划分为表现层,controller层,service层,DAO层四层

    使用spring MVC负责请求的转发和视图管理

    spring实现业务对象管理,mybatis作为数据对象的持久化引擎


    原理

    SpringMVC:

    1.客户端发送请求到DispacherServlet(分发器)

    2.由DispacherServlet控制器查询HanderMapping,找到处理请求的Controller

    3.Controller调用业务逻辑处理后,返回ModelAndView

    4.DispacherSerclet查询视图解析器,找到ModelAndView指定的视图

    5.视图负责将结果显示到客户端


    Spring:我们平时开发接触最多的估计就是IOC容器,它可以装载bean(也就是我们Java中的类,当然也包括service dao里面的),有了这个机制,我们就不用在每次使用这个类的时候为它初始化,很少看到关键字new。另外spring的aop,事务管理等等都是我们经常用到的。


    Mybatis:mybatis是对jdbc的封装,它让数据库底层操作变的透明。mybatis的操作都是围绕一个sqlSessionFactory实例展开的。mybatis通过配置文件关联到各实体类的Mapper文件,Mapper文件中配置了每个类对数据库所需进行的sql语句映射。在每次与数据库交互时,通过sqlSessionFactory拿到一个sqlSession,再执行sql命令。



    使用方法

    要完成一个功能:

    1. 先写实体类entity,定义对象的属性,(可以参照数据库中表的字段来设置,数据库的设计应该在所有编码开始之前)。
    2. 写Mapper.xml(Mybatis),其中定义你的功能,对应要对数据库进行的那些操作,比如 insert、selectAll、selectByKey、delete、update等。
    3. 写Mapper.java,将Mapper.xml中的操作按照id映射成Java函数。
    4. 写Service.java,为控制层提供服务,接受控制层的参数,完成相应的功能,并返回给控制层。
    5. 写Controller.java,连接页面请求和服务层,获取页面请求的参数,通过自动装配,映射不同的URL到相应的处理函数,并获取参数,对参数进行处理,之后传给服务层。
    6. 写JSP页面调用,请求哪些参数,需要获取什么数据。

    DataBase ===> Entity ===> Mapper.xml ===> Mapper.Java ===> Service.java ===> Controller.java ===> Jsp.  


    ====================================================================================================================================

    Spring MVC  拥有控制器,作用跟Struts类似,接收外部请求,解析参数传给服务层
    Spring 容器属于协调上下文,管理对象间的依赖,提供事务机制
    mybatis 属于orm持久层框架,将业务实体 与数据表联合 起来


    Spring MVC  控制层,想当与 Struts的作用
    Spring 控制反转和依赖注入  创建对象交由容器管理,达到了解耦的作用
    mybatis 主要用来操作数据库(数据库的增删改查)


    IOC:控制反转,是一种降低对象之间耦合关系的设计思想,面试的时候最好能说出来个例子,加深理解。例子:租房子,以前租房子需要一个房子一个房子找,费时费力,然后现在加入一个房屋中介,把你需要的房型告诉中介,就可以直接选到需要的房子,中介就相当于spring容器。


    AOP:面向切面编程,是面向对象开发的一种补充,它允许开发人员在不改变原来模型的基础上动态的修改模型以满足新的需求,如:动态的增加日志、安全或异常处理等。AOP使业务逻辑各部分间的耦合度降低,提高程序可重用性,提高开发效率。

    持久层:DAO层(mapper)

    • DAO层:DAO层主要是做数据持久层的工作,负责与数据库进行联络的一些任务都封装在此,
      • DAO层的设计首先是设计DAO的接口,
      • 然后在Spring的配置文件中定义此接口的实现类,
      • 然后就可在模块中调用此接口来进行数据业务的处理,而不用关心此接口的具体实现类是哪个类,显得结构非常清晰,
      • DAO层的数据源配置,以及有关数据库连接的参数都在Spring的配置文件中进行配置。

    业务层:Service层

    • Service层:Service层主要负责业务模块的逻辑应用设计。
      • 首先设计接口,再设计其实现的类
      • 接着再在Spring的配置文件中配置其实现的关联。这样我们就可以在应用中调用Service接口来进行业务处理。
      • Service层的业务实现,具体要调用到已定义的DAO层的接口,
      • 封装Service层的业务逻辑有利于通用的业务逻辑的独立性和重复利用性,程序显得非常简洁。

    表现层:Controller层(Handler层)

    • Controller层:Controller层负责具体的业务模块流程的控制
      • 在此层里面要调用Service层的接口来控制业务流程,
      • 控制的配置也同样是在Spring的配置文件里面进行,针对具体的业务流程,会有不同的控制器,我们具体的设计过程中可以将流程进行抽象归纳,设计出可以重复利用的子单元流程模块,这样不仅使程序结构变得清晰,也大大减少了代码量。

    View层

    • View层 此层与控制层结合比较紧密,需要二者结合起来协同工发。View层主要负责前台jsp页面的表示.

    各层联系

    • DAO层,Service层这两个层次都可以单独开发,互相的耦合度很低,完全可以独立进行,这样的一种模式在开发大项目的过程中尤其有优势
    • Controller,View层因为耦合度比较高,因而要结合在一起开发,但是也可以看作一个整体独立于前两个层进行开发。这样,在层与层之前我们只需要知道接口的定义,调用接口即可完成所需要的逻辑单元应用,一切显得非常清晰简单。

    • Service逻辑层设计

      • Service层是建立在DAO层之上的,建立了DAO层后才可以建立Service层,而Service层又是在Controller层之下的,因而Service层应该既调用DAO层的接口,又要提供接口给Controller层的类来进行调用,它刚好处于一个中间层的位置。每个模型都有一个Service接口,每个接口分别封装各自的业务处理方法。



    ====================================================================================================================================

       最近在学习Spring+SpringMVC+MyBatis的整合。以下是参考网上的资料自己实践操作的详细步骤。

     

    1、基本概念

     

    1.1、Spring 

            Spring是一个开源框架,Spring是于2003 年兴起的一个轻量级的Java 开发框架,由Rod Johnson 在其著作Expert One-On-One J2EE Development and Design中阐述的部分理念和原型衍生而来。它是为了解决企业应用开发的复杂性而创建的。Spring使用基本的JavaBean来完成以前只可能由EJB完成的事情。然而,Spring的用途不仅限于服务器端的开发。从简单性、可测试性和松耦合的角度而言,任何Java应用都可以从Spring中受益。 简单来说,Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架。

     

    1.2、SpringMVC     

            Spring MVC属于SpringFrameWork的后续产品,已经融合在Spring Web Flow里面。Spring MVC 分离了控制器、模型对象、分派器以及处理程序对象的角色,这种分离让它们更容易进行定制。

     

    1.3、MyBatis

           MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis 。MyBatis是一个基于Java的持久层框架。iBATIS提供的持久层框架包括SQL Maps和Data Access Objects(DAO)MyBatis 消除了几乎所有的JDBC代码和参数的手工设置以及结果集的检索。MyBatis 使用简单的 XML或注解用于配置和原始映射,将接口和 Java 的POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录。

     

     

    2、开发环境搭建以及创建Maven Web项目

    参看之前的博文:http://www.cnblogs.com/zyw-205520/p/4767633.html

     

    3、SSM整合

     下面主要介绍三大框架的整合,至于环境的搭建以及项目的创建,参看上面的博文。这次整合我分了2个配置文件,分别是spring-mybatis.xml,包含spring和mybatis的配置文件,还有个是spring-mvc的配置文件,此外有2个资源文件:jdbc.propertis和log4j.properties。完整目录结构如下(最后附上源码下载地址):

                                                                            

    使用框架的版本:

           Spring 4.0.2 RELEASE

           Spring MVC 4.0.2 RELEASE

           MyBatis 3.2.6

     

    3.1、Maven引入需要的JAR包

        在pom.xml中引入jar包

    复制代码
    <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/maven-v4_0_0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <groupId>com.javen.maven01</groupId>
        <artifactId>maven01</artifactId>
        <packaging>war</packaging>
        <version>0.0.1-SNAPSHOT</version>
        <name>maven01 Maven Webapp</name>
        <url>http://maven.apache.org</url>
        
        <properties>  
            <!-- spring版本号 -->  
            <spring.version>4.0.2.RELEASE</spring.version>  
            <!-- mybatis版本号 -->  
            <mybatis.version>3.2.6</mybatis.version>  
            <!-- log4j日志文件管理包版本 -->  
            <slf4j.version>1.7.7</slf4j.version>  
            <log4j.version>1.2.17</log4j.version>  
        </properties> 
        
        <dependencies>
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>3.8.1</version>
                 <!-- 表示开发的时候引入,发布的时候不会加载此包 -->  
                <scope>test</scope>
            </dependency>
            <!-- <dependency>
                <groupId>javax.servlet</groupId>
                <artifactId>javax.servlet-api</artifactId>
                <version>3.1.0</version>
            </dependency> -->
            
             <!-- spring核心包 -->  
            <dependency>  
                <groupId>org.springframework</groupId>  
                <artifactId>spring-core</artifactId>  
                <version>${spring.version}</version>  
            </dependency>  
      
            <dependency>  
                <groupId>org.springframework</groupId>  
                <artifactId>spring-web</artifactId>  
                <version>${spring.version}</version>  
            </dependency>  
            <dependency>  
                <groupId>org.springframework</groupId>  
                <artifactId>spring-oxm</artifactId>  
                <version>${spring.version}</version>  
            </dependency>  
            <dependency>  
                <groupId>org.springframework</groupId>  
                <artifactId>spring-tx</artifactId>  
                <version>${spring.version}</version>  
            </dependency>  
      
            <dependency>  
                <groupId>org.springframework</groupId>  
                <artifactId>spring-jdbc</artifactId>  
                <version>${spring.version}</version>  
            </dependency>  
      
            <dependency>  
                <groupId>org.springframework</groupId>  
                <artifactId>spring-webmvc</artifactId>  
                <version>${spring.version}</version>  
            </dependency>  
            <dependency>  
                <groupId>org.springframework</groupId>  
                <artifactId>spring-aop</artifactId>  
                <version>${spring.version}</version>  
            </dependency>  
      
            <dependency>  
                <groupId>org.springframework</groupId>  
                <artifactId>spring-context-support</artifactId>  
                <version>${spring.version}</version>  
            </dependency>  
      
            <dependency>  
                <groupId>org.springframework</groupId>  
                <artifactId>spring-test</artifactId>  
                <version>${spring.version}</version>  
            </dependency>  
            <!-- mybatis核心包 -->  
            <dependency>  
                <groupId>org.mybatis</groupId>  
                <artifactId>mybatis</artifactId>  
                <version>${mybatis.version}</version>  
            </dependency>  
             <!-- mybatis/spring包 -->  
            <dependency>  
                <groupId>org.mybatis</groupId>  
                <artifactId>mybatis-spring</artifactId>  
                <version>1.2.2</version>  
            </dependency>  
            
             <!-- 导入java ee jar 包 -->  
            <dependency>  
                <groupId>javax</groupId>  
                <artifactId>javaee-api</artifactId>  
                <version>7.0</version>  
            </dependency>  
            
             <!-- 导入Mysql数据库链接jar包 -->  
            <dependency>  
                <groupId>mysql</groupId>  
                <artifactId>mysql-connector-java</artifactId>  
                <version>5.1.36</version>  
            </dependency>  
            <!-- 导入dbcp的jar包,用来在applicationContext.xml中配置数据库 -->  
            <dependency>  
                <groupId>commons-dbcp</groupId>  
                <artifactId>commons-dbcp</artifactId>  
                <version>1.2.2</version>  
            </dependency>  
            
            <!-- JSTL标签类 -->  
            <dependency>  
                <groupId>jstl</groupId>  
                <artifactId>jstl</artifactId>  
                <version>1.2</version>  
            </dependency>  
            <!-- 日志文件管理包 -->  
            <!-- log start -->  
            <dependency>  
                <groupId>log4j</groupId>  
                <artifactId>log4j</artifactId>  
                <version>${log4j.version}</version>  
            </dependency>  
              
              
            <!-- 格式化对象,方便输出日志 -->  
            <dependency>  
                <groupId>com.alibaba</groupId>  
                <artifactId>fastjson</artifactId>  
                <version>1.1.41</version>  
            </dependency>  
      
      
            <dependency>  
                <groupId>org.slf4j</groupId>  
                <artifactId>slf4j-api</artifactId>  
                <version>${slf4j.version}</version>  
            </dependency>  
      
            <dependency>  
                <groupId>org.slf4j</groupId>  
                <artifactId>slf4j-log4j12</artifactId>  
                <version>${slf4j.version}</version>  
            </dependency>  
            <!-- log end -->  
            <!-- 映入JSON -->  
            <dependency>  
                <groupId>org.codehaus.jackson</groupId>  
                <artifactId>jackson-mapper-asl</artifactId>  
                <version>1.9.13</version>  
            </dependency>  
            <!-- 上传组件包 -->  
            <dependency>  
                <groupId>commons-fileupload</groupId>  
                <artifactId>commons-fileupload</artifactId>  
                <version>1.3.1</version>  
            </dependency>  
            <dependency>  
                <groupId>commons-io</groupId>  
                <artifactId>commons-io</artifactId>  
                <version>2.4</version>  
            </dependency>  
            <dependency>  
                <groupId>commons-codec</groupId>  
                <artifactId>commons-codec</artifactId>  
                <version>1.9</version>  
            </dependency>  
    
        </dependencies>
        
        <build>
            <finalName>maven01</finalName>
            <plugins>
                <plugin>
                    <groupId>org.eclipse.jetty</groupId>
                    <artifactId>jetty-maven-plugin</artifactId>
                    <version>9.2.8.v20150217</version>
                    <configuration>
                        <httpConnector>
                            <port>80</port>
                        </httpConnector>
                        <stopKey>shutdown</stopKey>
                        <stopPort>9966</stopPort>
                    </configuration>
                </plugin>
            </plugins>
        </build>
    
    </project>
    复制代码

    3.2、整合SpringMVC

    3.2.1、配置spring-mvc.xml

    配置里面的注释也很详细,主要是自动扫描控制器,视图模式,注解的启动这三个。

    复制代码
    <?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:mvc="http://www.springframework.org/schema/mvc"  
        xsi:schemaLocation="http://www.springframework.org/schema/beans    
                            http://www.springframework.org/schema/beans/spring-beans-3.1.xsd    
                            http://www.springframework.org/schema/context    
                            http://www.springframework.org/schema/context/spring-context-3.1.xsd    
                            http://www.springframework.org/schema/mvc    
                            http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd">  
        <!-- 自动扫描该包,使SpringMVC认为包下用了@controller注解的类是控制器 -->  
        <context:component-scan base-package="com.javen.controller" />  
        <!-- 扩充了注解驱动,可以将请求参数绑定到控制器参数 -->
        <mvc:annotation-driven/>
        <!-- 静态资源处理  css js imgs -->
        <mvc:resources location="/resources/**" mapping="/resources"/>
        
        <!--避免IE执行AJAX时,返回JSON出现下载文件 -->  
        <bean id="mappingJacksonHttpMessageConverter"  
            class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">  
            <property name="supportedMediaTypes">  
                <list>  
                    <value>text/html;charset=UTF-8</value>  
                </list>  
            </property>  
        </bean>  
        <!-- 启动SpringMVC的注解功能,完成请求和注解POJO的映射 -->  
        <bean  
            class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">  
            <property name="messageConverters">  
                <list>  
                    <ref bean="mappingJacksonHttpMessageConverter" /> <!-- JSON转换器 -->  
                </list>  
            </property>  
        </bean>  
          
        <!-- 配置文件上传,如果没有使用文件上传可以不用配置,当然如果不配,那么配置文件中也不必引入上传组件包 -->  
        <bean id="multipartResolver"    
            class="org.springframework.web.multipart.commons.CommonsMultipartResolver">    
            <!-- 默认编码 -->  
            <property name="defaultEncoding" value="utf-8" />    
            <!-- 文件大小最大值 -->  
            <property name="maxUploadSize" value="10485760000" />    
            <!-- 内存中的最大值 -->  
            <property name="maxInMemorySize" value="40960" />    
            <!-- 启用是为了推迟文件解析,以便捕获文件大小异常 -->
            <property name="resolveLazily" value="true"/>
        </bean>   
        
        <!-- 配置ViewResolver 。可用多个ViewResolver 。使用order属性排序。   InternalResourceViewResolver 放在最后-->
        <bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
        <property name="order" value="1"></property>
            <property name="mediaTypes">
                <map>
                    <!-- 告诉视图解析器,返回的类型为json格式 -->
                    <entry key="json" value="application/json" />
                    <entry key="xml" value="application/xml" />
                    <entry key="htm" value="text/htm" />
                </map>
            </property>
            <property name="defaultViews">
                <list>
                    <!-- ModelAndView里的数据变成JSON -->
                    <bean class="org.springframework.web.servlet.view.json.MappingJacksonJsonView" />
                </list>
            </property>
            <property name="ignoreAcceptHeader" value="true"></property>
        </bean>
        
       <!-- 定义跳转的文件的前后缀 ,视图模式配置-->  
        <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">  
            <!-- 这里的配置我的理解是自动给后面action的方法return的字符串加上前缀和后缀,变成一个 可用的url地址 -->  
            <property name="prefix" value="/WEB-INF/jsp/" />  
            <property name="suffix" value=".jsp" />  
        </bean>  
    </beans>  
    复制代码

     

    3.2.2、配置web.xml文件

     配置的spring-mvc的Servlet就是为了完成SpringMVC+MAVEN的整合。

    web.xml  

     

    复制代码
    <?xml version="1.0" encoding="UTF-8"?>  
    <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
        xmlns="http://java.sun.com/xml/ns/javaee"  
        xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"  
        version="3.0">  
        <display-name>Archetype Created Web Application</display-name>  
        <!-- Spring和mybatis的配置文件 -->  
       <!--  <context-param>  
            <param-name>contextConfigLocation</param-name>  
            <param-value>classpath:spring-mybatis.xml</param-value>  
        </context-param>   -->
        <!-- 编码过滤器 -->  
        <filter>  
            <filter-name>encodingFilter</filter-name>  
            <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>  
            <async-supported>true</async-supported>  
            <init-param>  
                <param-name>encoding</param-name>  
                <param-value>UTF-8</param-value>  
            </init-param>  
        </filter>  
        <filter-mapping>  
            <filter-name>encodingFilter</filter-name>  
            <url-pattern>/*</url-pattern>  
        </filter-mapping>  
        <!-- Spring监听器 -->  
       <!--  <listener>  
            <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>  
        </listener>   -->
        <!-- 防止Spring内存溢出监听器 -->  
        <!-- <listener>  
            <listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class>  
        </listener>  --> 
      
        <!-- Spring MVC servlet -->  
        <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>  
            <load-on-startup>1</load-on-startup>  
            <async-supported>true</async-supported>  
        </servlet>  
        <servlet-mapping>  
            <servlet-name>SpringMVC</servlet-name>  
            <!-- 此处可以可以配置成*.do,对应struts的后缀习惯 -->  
            <url-pattern>/</url-pattern>  
        </servlet-mapping>  
        <welcome-file-list>  
            <welcome-file>/index.jsp</welcome-file>  
        </welcome-file-list>  
      
    </web-app>  
    复制代码

     

     

    3.2.3、Log4j的配置

       为了方便调试,一般都会使用日志来输出信息,Log4j是Apache的一个开放源代码项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控制台、文件、GUI组件,甚至是套接口服务器、NT的事件记录器、UNIX Syslog守护进程等;我们也可以控制每一条日志的输出格式;通过定义每一条日志信息的级别,我们能够更加细致地控制日志的生成过程。

     

          Log4j的配置很简单,而且也是通用的,下面给出一个基本的配置,换到其他项目中也无需做多大的调整,如果想做调整或者想了解Log4j的各种配置,参看我转载的一篇博文,很详细:http://blog.csdn.net/zhshulin/article/details/37937365

    下面给出配置文件目录:

     

    log4j.properties

    复制代码
    log4j.rootLogger=INFO,Console,File  
    #定义日志输出目的地为控制台  
    log4j.appender.Console=org.apache.log4j.ConsoleAppender  
    log4j.appender.Console.Target=System.out  
    #可以灵活地指定日志输出格式,下面一行是指定具体的格式  
    log4j.appender.Console.layout = org.apache.log4j.PatternLayout  
    log4j.appender.Console.layout.ConversionPattern=[%c] - %m%n  
      
    #文件大小到达指定尺寸的时候产生一个新的文件  
    log4j.appender.File = org.apache.log4j.RollingFileAppender  
    #指定输出目录  
    log4j.appender.File.File = logs/ssm.log  
    #定义文件最大大小  
    log4j.appender.File.MaxFileSize = 10MB  
    # 输出所以日志,如果换成DEBUG表示输出DEBUG以上级别日志  
    log4j.appender.File.Threshold = ALL  
    log4j.appender.File.layout = org.apache.log4j.PatternLayout  
    log4j.appender.File.layout.ConversionPattern =[%p] [%d{yyyy-MM-dd HH\:mm\:ss}][%c]%m%n  
    复制代码

     

     

    3.2.4、使用Jetty测试

     

     

    复制代码
    package com.javen.model;
    
    public class User {
        private Integer id;
    
        private String userName;
    
        private String password;
    
        private Integer age;
    
        public Integer getId() {
            return id;
        }
    
        public void setId(Integer id) {
            this.id = id;
        }
    
        public String getUserName() {
            return userName;
        }
    
        public void setUserName(String userName) {
            this.userName = userName == null ? null : userName.trim();
        }
    
        public String getPassword() {
            return password;
        }
    
        public void setPassword(String password) {
            this.password = password == null ? null : password.trim();
        }
    
        public Integer getAge() {
            return age;
        }
    
        public void setAge(Integer age) {
            this.age = age;
        }
    
        @Override
        public String toString() {
            return "User [id=" + id + ", userName=" + userName + ", password="
                    + password + ", age=" + age + "]";
        }
        
        
    }
    复制代码
    复制代码
    package com.javen.controller;
    import javax.servlet.http.HttpServletRequest;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.stereotype.Controller;  
    import org.springframework.ui.Model;  
    import org.springframework.web.bind.annotation.RequestMapping;  
    import org.springframework.web.bind.annotation.RequestMethod;
    import com.javen.model.User;
      
      
    @Controller  
    @RequestMapping("/user")  
    // /user/**
    public class UserController {  
        private static Logger log=LoggerFactory.getLogger(UserController.class);
          
        
        // /user/test?id=1
        @RequestMapping(value="/test",method=RequestMethod.GET)  
        public String test(HttpServletRequest request,Model model){  
            int userId = Integer.parseInt(request.getParameter("id"));  
            System.out.println("userId:"+userId);
            User user=null;
            if (userId==1) {
                 user = new User();  
                 user.setAge(11);
                 user.setId(1);
                 user.setPassword("123");
                 user.setUserName("javen");
            }
           
            log.debug(user.toString());
            model.addAttribute("user", user);  
            return "index";  
        }  
    }  
    复制代码

     

     

                                   

     

    在浏览器中输入:http://localhost/user/test?id=1

    到此 SpringMVC+Maven 整合完毕

     

     

     


    3.3 Spring与MyBatis的整合

       取消3.2.2 web.xml中注释的代码 

     

     

    3.3.1、建立JDBC属性文件

     

     

     

    jdbc.properties(文件编码修改为utf-8)

    复制代码
    driver=com.mysql.jdbc.Driver
    url=jdbc:mysql://localhost:3306/maven
    username=root
    password=root
    #定义初始连接数  
    initialSize=0  
    #定义最大连接数  
    maxActive=20  
    #定义最大空闲  
    maxIdle=20  
    #定义最小空闲  
    minIdle=1  
    #定义最长等待时间  
    maxWait=60000  
    复制代码

    此时的目录结构为 

     

     

                                                                  

    3.3.2、建立spring-mybatis.xml配置文件

        这个文件就是用来完成spring和mybatis的整合的。这里面也没多少行配置,主要的就是自动扫描,自动注入,配置数据库。注释也很详细,大家看看就明白了。

    spring-mybatis.xml

     

    复制代码
    <?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:mvc="http://www.springframework.org/schema/mvc"  
        xsi:schemaLocation="http://www.springframework.org/schema/beans    
                            http://www.springframework.org/schema/beans/spring-beans-3.1.xsd    
                            http://www.springframework.org/schema/context    
                            http://www.springframework.org/schema/context/spring-context-3.1.xsd    
                            http://www.springframework.org/schema/mvc    
                            http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd">  
        <!-- 自动扫描 -->  
        <context:component-scan base-package="com.javen" />  
        
        <!-- 引入配置文件 -->  
        <bean id="propertyConfigurer"  
            class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">  
            <property name="location" value="classpath:jdbc.properties" />  
        </bean>  
      
        <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"  
            destroy-method="close">  
            <property name="driverClassName" value="${driver}" />  
            <property name="url" value="${url}" />  
            <property name="username" value="${username}" />  
            <property name="password" value="${password}" />  
            <!-- 初始化连接大小 -->  
            <property name="initialSize" value="${initialSize}"></property>  
            <!-- 连接池最大数量 -->  
            <property name="maxActive" value="${maxActive}"></property>  
            <!-- 连接池最大空闲 -->  
            <property name="maxIdle" value="${maxIdle}"></property>  
            <!-- 连接池最小空闲 -->  
            <property name="minIdle" value="${minIdle}"></property>  
            <!-- 获取连接最大等待时间 -->  
            <property name="maxWait" value="${maxWait}"></property>  
        </bean>  
      
        <!-- spring和MyBatis完美整合,不需要mybatis的配置映射文件 -->  
        <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">  
            <property name="dataSource" ref="dataSource" />  
            <!-- 自动扫描mapping.xml文件 -->  
            <property name="mapperLocations" value="classpath:com/javen/mapping/*.xml"></property>  
        </bean>  
      
        <!-- DAO接口所在包名,Spring会自动查找其下的类 -->  
        <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">  
            <property name="basePackage" value="com.javen.dao" />  
            <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>  
        </bean>  
      
        <!-- (事务管理)transaction manager, use JtaTransactionManager for global tx -->  
        <bean id="transactionManager"  
            class="org.springframework.jdbc.datasource.DataSourceTransactionManager">  
            <property name="dataSource" ref="dataSource" />  
        </bean>  
      
    </beans>  
    复制代码

    3.4、JUnit测试

      经过以上步骤,我们已经完成了Spring和mybatis的整合,这样我们就可以编写一段测试代码来试试是否成功了。

     

    3.4.1、创建测试用表

    既然我们需要测试,那么我们就需要建立在数据库中建立一个测试表,这个表建的很简单,SQL语句为:

    复制代码
    -- ----------------------------
    -- Table structure for `user_t`
    -- ----------------------------
    DROP TABLE IF EXISTS `user_t`;
    CREATE TABLE `user_t` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `user_name` varchar(40) NOT NULL,
      `password` varchar(255) NOT NULL,
      `age` int(4) NOT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
    
    -- ----------------------------
    -- Records of user_t
    -- ----------------------------
    INSERT INTO `user_t` VALUES ('1', '测试', '345', '24');
    INSERT INTO `user_t` VALUES ('2', 'javen', '123', '10');
    复制代码

     

    3.4.2、利用MyBatis Generator自动创建代码

     

    参考博文:http://blog.csdn.net/zhshulin/article/details/23912615

     

     这个可根据表自动创建实体类、MyBatis映射文件以及DAO接口,当然,我习惯将生成的接口名改为IUserDao,而不是直接用它生成的UserMapper。如果不想麻烦就可以不改。完成后将文件复制到工程中。如图:

                                                                      

    3.4.3、建立Service接口和实现类

                                                                     

    下面给出具体的内容:

    IUserService.jave

    复制代码
    package com.javen.service;  
    
    import com.javen.model.User;
      
      
    public interface IUserService {  
        public User getUserById(int userId);  
    }  
    复制代码

    UserServiceImpl.java

    复制代码
    package com.javen.service.impl;
    import javax.annotation.Resource;  
    
    import org.springframework.stereotype.Service;  
    import com.javen.dao.IUserDao;
    import com.javen.model.User;
    import com.javen.service.IUserService;
      
      
    @Service("userService")  
    public class UserServiceImpl implements IUserService {  
        @Resource  
        private IUserDao userDao;  
        
        public User getUserById(int userId) {  
            // TODO Auto-generated method stub  
            return this.userDao.selectByPrimaryKey(userId);  
        }  
      
    }  
    复制代码

     

     

    3.4.4、建立测试类

     测试类在src/test/java中建立,下面测试类中注释掉的部分是不使用Spring时,一般情况下的一种测试方法;如果使用了Spring那么就可以使用注解的方式来引入配置文件和类,然后再将service接口对象注入,就可以进行测试了。

           如果测试成功,表示Spring和Mybatis已经整合成功了。输出信息使用的是Log4j打印到控制台。

     

    复制代码
    package com.javen.testmybatis;
    
    import javax.annotation.Resource;  
    
    import org.apache.log4j.Logger;  
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.test.context.ContextConfiguration;  
    import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;  
    import com.alibaba.fastjson.JSON;  
    import com.javen.model.User;
    import com.javen.service.IUserService;
      
    @RunWith(SpringJUnit4ClassRunner.class)     //表示继承了SpringJUnit4ClassRunner类  
    @ContextConfiguration(locations = {"classpath:spring-mybatis.xml"})  
      
    public class TestMyBatis {  
        private static Logger logger = Logger.getLogger(TestMyBatis.class);  
    //  private ApplicationContext ac = null;  
        @Resource  
        private IUserService userService = null;  
      
    //  @Before  
    //  public void before() {  
    //      ac = new ClassPathXmlApplicationContext("applicationContext.xml");  
    //      userService = (IUserService) ac.getBean("userService");  
    //  }  
      
        @Test  
        public void test1() {  
            User user = userService.getUserById(1);  
            // System.out.println(user.getUserName());  
            // logger.info("值:"+user.getUserName());  
            logger.info(JSON.toJSONString(user));  
        }  
    }  
    复制代码

    测试结果 

     

    3.4.5、建立UserController类

    UserController.java  控制器   

     

    复制代码
    package com.javen.controller;
    import java.io.File;
    import java.io.IOException;
    import java.util.Map;
    
    import javax.annotation.Resource;
    import javax.servlet.http.HttpServletRequest;
    
    import org.apache.commons.io.FileUtils;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.http.HttpStatus;
    import org.springframework.http.ResponseEntity;
    import org.springframework.stereotype.Controller;  
    import org.springframework.ui.Model;  
    import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.RequestMapping;  
    import org.springframework.web.bind.annotation.RequestMethod;
    import org.springframework.web.bind.annotation.RequestParam;
    import org.springframework.web.bind.annotation.ResponseBody;
    import org.springframework.web.multipart.MultipartFile;
    
    import com.javen.model.User;
    import com.javen.service.IUserService;
      
      
    @Controller  
    @RequestMapping("/user")  
    // /user/**
    public class UserController {  
        private static Logger log=LoggerFactory.getLogger(UserController.class);
         @Resource  
         private IUserService userService;     
        
        // /user/test?id=1
        @RequestMapping(value="/test",method=RequestMethod.GET)  
        public String test(HttpServletRequest request,Model model){  
            int userId = Integer.parseInt(request.getParameter("id"));  
            System.out.println("userId:"+userId);
            User user=null;
            if (userId==1) {
                 user = new User();  
                 user.setAge(11);
                 user.setId(1);
                 user.setPassword("123");
                 user.setUserName("javen");
            }
           
            log.debug(user.toString());
            model.addAttribute("user", user);  
            return "index";  
        }  
        
        
        // /user/showUser?id=1
        @RequestMapping(value="/showUser",method=RequestMethod.GET)  
        public String toIndex(HttpServletRequest request,Model model){  
            int userId = Integer.parseInt(request.getParameter("id"));  
            System.out.println("userId:"+userId);
            User user = this.userService.getUserById(userId);  
            log.debug(user.toString());
            model.addAttribute("user", user);  
            return "showUser";  
        }  
        
     // /user/showUser2?id=1
        @RequestMapping(value="/showUser2",method=RequestMethod.GET)  
        public String toIndex2(@RequestParam("id") String id,Model model){  
            int userId = Integer.parseInt(id);  
            System.out.println("userId:"+userId);
            User user = this.userService.getUserById(userId);  
            log.debug(user.toString());
            model.addAttribute("user", user);  
            return "showUser";  
        }  
        
        
        // /user/showUser3/{id}
        @RequestMapping(value="/showUser3/{id}",method=RequestMethod.GET)  
        public String toIndex3(@PathVariable("id")String id,Map<String, Object> model){  
            int userId = Integer.parseInt(id);  
            System.out.println("userId:"+userId);
            User user = this.userService.getUserById(userId);  
            log.debug(user.toString());
            model.put("user", user);  
            return "showUser";  
        }  
        
     // /user/{id}
        @RequestMapping(value="/{id}",method=RequestMethod.GET)  
        public @ResponseBody User getUserInJson(@PathVariable String id,Map<String, Object> model){  
            int userId = Integer.parseInt(id);  
            System.out.println("userId:"+userId);
            User user = this.userService.getUserById(userId);  
            log.info(user.toString());
            return user;  
        }  
        
        // /user/{id}
        @RequestMapping(value="/jsontype/{id}",method=RequestMethod.GET)  
        public ResponseEntity<User>  getUserInJson2(@PathVariable String id,Map<String, Object> model){  
            int userId = Integer.parseInt(id);  
            System.out.println("userId:"+userId);
            User user = this.userService.getUserById(userId);  
            log.info(user.toString());
            return new ResponseEntity<User>(user,HttpStatus.OK);  
        } 
        
        //文件上传、
        @RequestMapping(value="/upload")
        public String showUploadPage(){
            return "user_admin/file";
        }
        
        @RequestMapping(value="/doUpload",method=RequestMethod.POST)
        public String doUploadFile(@RequestParam("file")MultipartFile file) throws IOException{
            if (!file.isEmpty()) {
                log.info("Process file:{}",file.getOriginalFilename());
            }
            FileUtils.copyInputStreamToFile(file.getInputStream(), new File("E:\\",System.currentTimeMillis()+file.getOriginalFilename()));
            return "succes";
        }
    }  
    复制代码

     

    3.4.6、新建jsp页面

    file.jsp

    复制代码
    <%@ page language="java" contentType="text/html; charset=utf-8"
        pageEncoding="utf-8"%>
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <title>Insert title here</title>
    </head>
    <body>
        <h1>上传文件</h1>
        <form method="post" action="/user/doUpload" enctype="multipart/form-data">
            <input type="file" name="file"/>
            <input type="submit" value="上传文件"/>
            
        </form>
    </body>
    </html>
    复制代码

    index.jsp

    <html>
    <body>
    <h2>Hello World!</h2>
    </body>
    </html>

    showUser.jsp

    复制代码
    <%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>  
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">  
    <html>  
      <head>  
        <title>测试</title>  
      </head>  
        
      <body>  
        ${user.userName}  
      </body>  
    </html>  
    复制代码

     

    至此,完成Spring+SpingMVC+mybatis这三大框架整合完成。

     

    3.4.7、部署项目

     

    输入地址:http://localhost/user/jsontype/2

      项目下载地址:https://github.com/Javen205/SSM

     

        参考博客:http://blog.csdn.net/gebitan505/article/details/44455235


    展开全文
  • SSM框架介绍

    万次阅读 多人点赞 2018-10-30 14:07:53
    1、SSM框架简介 SSM框架是Spring MVC ,Spring和Mybatis框架的整合,是标准的MVC模式,将整个系统划分为表现层,Controller层,Service层,DAO层四层,使用Spring MVC负责请求的转发和视图管理,Spring实现业务对象...

    1、SSM框架简介

    SSM框架是Spring MVC ,Spring和Mybatis框架的整合,是标准的MVC模式,将整个系统划分为View层,Controller层,Service层,DAO层四层,使用Spring MVC负责请求的转发和视图管理,Spring实现业务对象管理,Mybatis作为数据对象的持久化引擎。

    2、SSM框架各层介绍

    2.1、持久层(Mybatis):Dao层(mapper)
    DAO层:DAO层主要是做数据持久层的工作,负责与数据库进行联络的一些任务都封装在此。

    • DAO层的设计首先是设计DAO的接口。
    • 然后在Spring的配置文件中定义此接口的实现类。
    • 然后就可在模块中调用此接口来进行数据业务的处理,而不用关心此接口的具体实现类是哪个类,显得结构非常清晰。
    • DAO层的数据源配置,以及有关数据库连接的参数都在Spring的配置文件中进行配置。

    2.2、业务层(Spring):Service层
    Service层:Service层主要负责业务模块的逻辑应用设计。

    • 首先设计接口,再设计其实现的类。
    • 接着再在Spring的配置文件中配置其实现的关联。这样我们就可以在应用中调用Service接口来进行业务处理。
    • Service层的业务实现,具体要调用到已定义的DAO层的接口。
    • 封装Service层的业务逻辑有利于通用的业务逻辑的独立性和重复利用性,程序显得非常简洁。

    2.3、表现层(springMVC):Controller层(Handler层)
    Controller层:Controller层负责具体的业务模块流程的控制。

    • 在此层里面要调用Service层的接口来控制业务流程。
    • 控制的配置也同样是在Spring的配置文件里面进行,针对具体的业务流程,会有不同的控制器,我们具体的设计过程中可以将流程进行抽象归纳,设计出可以重复利用的子单元流程模块,这样不仅使程序结构变得清晰,也大大减少了代码量。

    2.4、视图层:View层
    View层:View层与控制层结合比较紧密,需要二者结合起来协同工发。View层主要负责前台jsp页面的表示。

    3、SSM框架各层关系

    • DAO层、Service层这两个层次都可以单独开发,互相的耦合度很低,完全可以独立进行,这样的一种模式在开发大项目的过程中尤其有优势。
    • Controller,View层因为耦合度比较高,因而要结合在一起开发,但是也可以看作一个整体独立于前两个层进行开发。这样,在层与层之前我们只需要知道接口的定义,调用接口即可完成所需要的逻辑单元应用,一切显得非常清晰简单。
    • Service层是建立在DAO层之上的,建立了DAO层后才可以建立Service层,而Service层又是在Controller层之下的,因而Service层应该既调用DAO层的接口,又要提供接口给Controller层的类来进行调用,它刚好处于一个中间层的位置。每个模型都有一个Service接口,每个接口分别封装各自的业务处理方法。

    4、SSM原理及流程

    1. 客户端发送请求到DispacherServlet(分发器)
    2. 由DispacherServlet控制器查询HanderMapping,找到处理请求的Controller
    3. Controller调用Service业务逻辑层处理后返回结果
      在这里插入图片描述
    展开全文
  • SSM框架简介

    万次阅读 多人点赞 2018-09-17 16:59:51
    SSM框架简介 SSM框架,是Spring + Spring MVC + MyBatis的缩写,这个是继SSH之后,目前比较主流的Java EE企业级框架,适用于搭建各种大型的企业级应用系统。 1.Spring简介 &amp;nbsp;&amp;nbsp;&amp;...
  • SSM框架概念

    2018-11-18 12:50:31
    1.IoC IoC:某一接口具体实现类(ZhangSan)的选择控制权从调用的类(JavaWork)中移除, 转交给第三方决定,即Spring容器借由Bean配置来进行控制。 依赖注入:让调用类对某一接口实现类的依赖关系由第三方注入,以...
  • SSM框架的一些常见问题

    千次阅读 2018-03-09 12:15:13
    SSM常见问题? mybatis 1.mybatis中#{}和${}的区别? 1.1 #{}会将参数转换为字符串(String)形式进行处理,${}不会,${}会以原格式进行处理 1.2 #{}会进行预编译,可以有效的防止sql注入,而${}不会 1.3 在排序(order ...
  • 网上很多整合SSM博客文章并不能让初探ssm的同学思路完全的清晰,可以试着关掉整合教程,摇两下头骨,哈一大口气,就在万事具备的时候,开整,这个时候你可能思路全无 ~中招了咩~ ,还有一些同学依旧在使用eclipse...
  • SSM框架的高并发和商品秒杀项目

    万次阅读 2019-12-22 14:19:46
    SSM框架的高并发和商品秒杀项目 【1】一阶段,项目搭建:https://mp.weixin.qq.com/s/XROxKW-jmh8xF5NCqiGwgA 【2】二阶段,Java高并发秒杀API之Service层:https://mp.weixin.qq.com/s/YABll0Sf0Tb_-zJhs...
  • SSM第一篇 最简单的SSM框架搭建过程--SSM简单整合

    万次阅读 多人点赞 2019-06-13 08:35:02
    SSM(Spring、Spring MVC和Mybatis)是...许多童鞋现在开始学习这个流行的框架来进行Java开发,想要寻找一个最简单的SSM框架搭建方法,这里我不说什么废话,直接上手开始搭建,代码部分都做了详细的注释,可以快速...
  • 相信很多小伙伴在学习完SSM三大架构以后,不知道该如何找到一个简单容易上手的项目进行实战训练,经常在博客上看到一个不错的项目下载下来以后全部都是代码,无处下手。因此本文力求以最简单易懂的项目结构和代码...
  • 我的毕业设计就叫毕业设计管理系统的设计与实现,哈哈 目录 1.摘要 2.需求分析 3.数据库设计 ...毕业设计是本科教育的最后一个环节,整个过程包括课题拟定与审核、师生双选、开题报告、文档审核、中期检查、毕业...
  • SSM框架——使用MyBatis Generator自动创建代码

    万次阅读 多人点赞 2015-01-26 12:18:58
    这两天需要用到MyBatis的代码自动生成的功能,由于MyBatis属于一种半自动的ORM框架,所以主要的工作就是配置Mapping映射文件,但是由于手写映射文件很容易出错,所以可利用MyBatis生成器自动生成实体类、DAO接口和...
  • SSM框架概念(什么是SSM框架

    千次阅读 多人点赞 2019-08-21 13:36:53
    SSM框架 全称为Spring+SpringMVC+MyBatis ,这个是继SSH之后,目前比较主流的Java EE企业级框架,适用于搭建各种大型的企业级应用系统。 由Spring、MyBatis两个开源框架整合而成(SpringMVC是Spring中的部分内容...
  • SSM框架搭建(spring+springmvc+mybatis)

    万次阅读 多人点赞 2018-11-08 11:45:49
    自己配置了一个SSM框架,打算做个小网站,这里把SSM的配置流程详细的写了出来,方便很少接触这个框架的朋友使用,文中各个资源均免费提供!(后续读写分离:https://blog.csdn.net/dwhdome/article/details/83380149...
  • SSM框架

    千次阅读 2017-12-05 16:12:05
    SSM框架由于它的优势在近一段时间很流行,本文力图用最简单的例子和语言讲解SSM框架SSM框架简介首先我们看一下SSM框架指的是什么? SSM框架指使用Spring,SpringMVC和Mybatis三大框架完成java web项目的开发,...
  • Java SSM框架简介

    万次阅读 多人点赞 2020-06-19 19:57:40
    前言:在学习Java SSM框架前,我提前学习了反射、注解和MVC模式,因为它们频繁在SSM框架中被用到,建议大家先弄明白了这些基础知识,再学习SSM框架就很简单了。 Java进阶知识1:反射机制 Java进阶知识2:注解 ...
  • 2018_03_14 ssm框架整合

    千次阅读 2018-03-14 16:33:28
    ssm框架整合代码github地址:https://github.com/liujiaxin1314/ssm_demossm框架整合思路:Dao层:1、SqlMapConfig.xml,空文件即可。需要文件头。2、applicationContext-dao.xml。a)数据库连接池b)...
  • SSM框架简单实例

    千次阅读 多人点赞 2018-05-28 13:44:17
    1、SSM框架SSM(Spring+SpringMVC+MyBatis)框架集由Spring、SpringMVC、MyBatis三个开源框架整合而成,常作为数据源较简单的web项目的框架。2、简单实例(1)项目结构(2)PageBean.javapackage cn.hwd.paging.bean...
  • 选用SSM框架的原因 在目前的企业级Java应用中,Spring框架是必须的。Struts2框架与Spring的整合问题日益凸显,而Spring MVC作为新一代的MVC框架,因其可以与Spring框架无缝整合的特性收到了越来越多的欢迎。...
1 2 3 4 5 ... 20
收藏数 67,717
精华内容 27,086
关键字:

ssm框架