一、什么是SSM框架: SSM框架是Spring、SpringMVC和Mybatis框架的整合,是标准的MVC模式,将整个系统划分为View层,Controller层,Service层,DAO层四层,使用Spring MVC负责请求的转发和视图管理,Spring实现业务对象管理,Mybatis作为数据对象的持久化引擎。
二、各框架介绍
Spring
Spring就像是整个项目中装配bean的大工厂,在配置文件中可以指定使用特定的参数去调用实体类的构造方法来实例化对象。也可以称之为项目中的粘合剂。 Spring的核心思想是IoC(控制反转),即不再需要程序员去显式地new
一个对象,而是让Spring框架帮你来完成这一切。
SpringMVC
SpringMVC作用于web层,相当于controller,与struts中的action一样,都是用来处理用户请求的。同时,相比于struts2来说,更加细粒度,它是基于方法层面的,而struts是基于类层面的。Spring MVC 分离了控制器、模型对象、分派器以及处理程序对象的角色,这种分离让它们更容易进行定制。
SpringMVC在项目中拦截用户请求,它的核心Servlet即DispatcherServlet承担中介或是前台这样的职责,将用户请求通过HandlerMapping去匹配Controller,Controller就是具体对应请求所执行的操作。SpringMVC相当于SSH框架中struts。
SpringMVC具体工作流程如下
mybatis
MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录。
mybatis是对jdbc的封装,它让数据库底层操作变的透明。
mybatis的操作都是围绕一个sqlSessionFactory实例展开的。mybatis通过配置文件关联到各实体类的Mapper文件,Mapper文件中配置了每个类对数据库所需进行的sql语句映射。在每次与数据库交互时,通过sqlSessionFactory拿到一个sqlSession,再执行sql命令。
Mybatis层次图:
三、SSM框架中各层介绍 pojo层,Dao层,Mapper层,service层,controller层 DAO层: DAO层叫数据访问层,全称为data access object,某个DAO一定是和数据库的某一张表一一对应的,其中封装了CRUD(增加Create、检索Retrieve、更新Update和删除Delete)基本操作,DAO只做原子操作。无论多么复杂的查询,dao只是封装增删改查。至于增删查改如何去实现一个功能,dao是不管的。Mapper就是Mybatis操作数据库的那一层,就是DAO层
Service层: Service层叫服务层,被称为服务,粗略的理解就是对一个或多个DAO进行的再次封装,封装成一个服务,所以这里也就不会是一个原子操作了,需要事物控制。管理具体的功能的。service包含了serviceImpl(service接口的实现类) 是提供给controller 使用的,针对于某些业务将 dao 的对于某些表的crud进行组合,也就是说间接的和数据库打交道。
Controller层: Controler负责请求转发,接受页面过来的参数,传给Service处理,接到返回值,再传给页面。管理业务(Service)调度和管理跳转的。controller 通过调用service来完成业务逻辑。
pojo层 实体类这一层,与数据库中的属性值基本保持一致。有的开发写成pojo,有的写成model,也有domain,也有dto(这里做参数验证,比如password不能为空等)。
mapper层 Mapper就是Mybatis操作数据库的那一层,就是DAO层,对数据库进行数据持久化操作,他的方法语句是直接针对数据库操作的。
各个层之间的流程如下:
四、框架核心原理
AOP 面向切面编程(AOP)提供另外一种角度来思考程序结构,通过这种方式弥补了面向对象编程(OOP)的不足。除了类(classes)以外,AOP提供了切面。切面对关注点进行模块化,例如横切多个类型和对象的事务管理。Spring的一个关键的组件就是AOP框架,可以自由选择是否使用AOP。提供声明式企业服务,特别是为了替代EJB声明式服务。最重要的服务是声明性事务管理,这个服务建立在Spring的抽象事物管理之上。允许用户实现自定义切面,用AOP来完善OOP的使用可以把Spring AOP看作是对Spring的一种增强。AOP的实现乃至spring框架基本上核心代码都是基于Java语言的反射机制(所谓的反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。)。 AOP主要作用就是不通过修改源代码的方式、将非核心功能代码织入来实现对方法的增强。那么Spring AOP的底层如何实现对方法的增强?实现的关键在于使用了代理模式。代理模式的作用就是为其它对象提供一种代理,以控制对这个对象的访问,用于解决在直接访问对象时带来的各种问题,比如要访问的对象在远程的机器上。在面向对象系统中,由于其他某些原因(对象创建开销很大,或者某些操作需要安全控制,或者需要进程外的访问)等 代理主要分为两种方式:静态代理和动态代理
IOC IoC不是一种技术,只是一种思想,一个重要的面向对象编程的法则,它能指导我们如何设计出松耦合、更优良的程序。有了IoC容器后,把创建和查找依赖对象的控制权交给了容器,由容器进行注入组合对象,所以相较于传统的java servlet需要自己request.getParamiter等需要一系列取值,转换中文,转换值类型的繁琐,更重要的是使得程序的整个体系结构变得非常灵活。 自定义一个IOC容器的思路: Map做一个容器,然后用解析xml文件的工具解析出需要扫描的包。利用Java反射机制拿到锁具有的方法,属性,注入到Map容器中
DI 依赖注入,是组件之间依赖关系由容器在运行期决定,形象的说,即由容器动态地将某个依赖关系注入到组件之中。依赖注入的目的并非为软件系统带来更多功能,而是为了提升组件重用的频率,并为系统搭建一个灵活、可扩展的平台。通过依赖注入机制,我们只需要通过简单的配置,而无需任何代码就可指定目标需要的资源,完成自身的业务逻辑,而不需要关心具体的资源来自何处,由谁实现。
AOP,IoC以及DI我单独写了两篇博客,比较详细的介绍了其思想,大家可以在”笔记”标签中找到。 五、SSM框架工作流程
用户访问客户端发出请求,请求会被Spring MVC中的前端控制器拦截,前端控制器配置在web.xml中。
DispatcherServlet拦截到请求后,调用处理器映射器在dispatcher-servlet.xml文件中
处理器映射器根据URL找到具体的处理器,生成具体的处理器对象及处理器拦截器(如果有生成)返回给前端控制器。
前端控制器会选择合适的处理器适配器
HandlerAdapter会调用并执行Handler(Controller层)也被称之为后端控制器
处理器对持久化对象进行增删改查
POJO将操作映射到ORM框架
ORM框架将操作映射到数据库
关系数据库把操作的数据返回给ORM框架
ORM框架把数据返回给持久化对象
持久化对象把数据返回给Handler
Handler返回一个ModelAndView对象,包含模型和视图名
处理器适配器将这个模型返回给前端控制器
前端控制器会根据ModelAndView选择一个合适的ViewResolver
视图解析器解析后返回一个合适的视图View给前端控制器
前端控制器对view进行渲染
返回给客户端浏览器显示
SSM框架全网最详细流程图如下:
六、SSM框架整合 要让几个框架相互配合,配置文件怎么写,项目的目录结构怎么设计对我这样一个新手来说实在很头疼。 目前我也只刚刚写过一个用户登录的demo,在此记录一下。
(一)、项目目录结构 -LoginDemo -src -项目主包 -controller -mapper -entity -service -web -WEB-INF -log4j.properties -spring-mybatis.xml -springMVC-config.xml -web.xml -index.jsp -pom.xml
二、需要引入的包 (pom.xml) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 <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 > <name > LoginDemo</name > <groupId > com.cyan</groupId > <artifactId > ssm</artifactId > <packaging > war</packaging > <version > 1.0-SNAPSHOT</version > <url > http://maven.apache.org</url > <build > <finalName > ssm</finalName > <plugins > <plugin > <groupId > org.mybatis.generator</groupId > <artifactId > mybatis-generator-maven-plugin</artifactId > <version > 1.3.2</version > <configuration > <verbose > true</verbose > <overwrite > true</overwrite > </configuration > </plugin > <plugin > <groupId > org.apache.maven.plugins</groupId > <artifactId > maven-compiler-plugin</artifactId > <configuration > <source > 1.6</source > <target > 1.6</target > </configuration > </plugin > </plugins > </build > <properties > <spring.version > 4.1.1.RELEASE</spring.version > </properties > <dependencies > <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 > <dependency > <groupId > org.aspectj</groupId > <artifactId > aspectjweaver</artifactId > <version > 1.8.6</version > </dependency > <dependency > <groupId > org.aspectj</groupId > <artifactId > aspectjrt</artifactId > <version > 1.8.6</version > </dependency > <dependency > <groupId > com.mchange</groupId > <artifactId > c3p0</artifactId > <version > 0.9.5.1</version > </dependency > <dependency > <groupId > javax.servlet</groupId > <artifactId > servlet-api</artifactId > <version > 2.5</version > </dependency > <dependency > <groupId > javax.servlet.jsp</groupId > <artifactId > jsp-api</artifactId > <version > 2.1</version > <scope > provided</scope > </dependency > <dependency > <groupId > junit</groupId > <artifactId > junit</artifactId > <version > 4.11</version > <scope > test</scope > </dependency > <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 > <dependency > <groupId > mysql</groupId > <artifactId > mysql-connector-java</artifactId > <version > 5.1.6</version > </dependency > <dependency > <groupId > jstl</groupId > <artifactId > jstl</artifactId > <version > 1.2</version > </dependency > </dependencies > </project >
(三)、配置文件
web.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns ="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation ="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version ="3.1" > <listener > <listener-class > org.springframework.web.context.ContextLoaderListener</listener-class > </listener > <servlet > <servlet-name > springMVC-config</servlet-name > <servlet-class > org.springframework.web.servlet.DispatcherServlet</servlet-class > <init-param > <param-name > contextConfigLocation</param-name > <param-value > classpath:/WEB-INF/springMVC-config.xml</param-value > </init-param > </servlet > <servlet-mapping > <servlet-name > springMVC-config</servlet-name > <url-pattern > /</url-pattern > </servlet-mapping > <context-param > <param-name > contextConfigLocation</param-name > <param-value > classpath:WEB-INF/spring-mybatis.xml</param-value > </context-param > </web-app >
spring-mybatis.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 <?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:tx ="http://www.springframework.org/schema/tx" xmlns:aop ="http://www.springframework.org/schema/aop" xsi:schemaLocation ="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd" > <context:annotation-config /> <context:component-scan base-package ="com.cyan" /> <bean id ="datasource" class ="org.springframework.jdbc.datasource.DriverManagerDataSource" > <property name ="driverClassName" value ="com.mysql.jdbc.Driver" /> <property name ="url" value ="jdbc:mysql://localhost:3306/Demo" /> <property name ="username" value ="root" /> <property name ="password" value ="2233" /> </bean > <bean id ="sqlSessionFactory" class ="org.mybatis.spring.SqlSessionFactoryBean" > <property name ="dataSource" ref ="datasource" /> </bean > <bean class ="org.mybatis.spring.mapper.MapperScannerConfigurer" > <property name ="basePackage" value ="com.cyan.Mapper" /> </bean > <bean id ="txManager" class ="org.springframework.jdbc.datasource.DataSourceTransactionManager" > <property name ="dataSource" ref ="datasource" /> </bean > <tx:advice id ="txAdvice" transaction-manager ="txManager" > <tx:attributes > <tx:method name ="insert*" propagation ="REQUIRED" /> <tx:method name ="delete*" propagation ="REQUIRED" /> <tx:method name ="update*" propagation ="REQUIRED" /> <tx:method name ="select*" propagation ="SUPPORTS" /> </tx:attributes > </tx:advice > <aop:config > <aop:pointcut id ="serviceCut" expression ="execution(public * Service.*.*(..))" /> <aop:advisor pointcut-ref ="serviceCut" advice-ref ="txAdvice" /> </aop:config > </beans >
springMVC-config.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 <beans xmlns ="http://www.springframework.org/schema/beans" xmlns:context ="http://www.springframework.org/schema/context" xmlns:mvc ="http://www.springframework.org/schema/mvc" xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation =" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd" > <context:component-scan base-package ="com.cyan.Controller" > <context:include-filter type ="annotation" expression ="org.springframework.stereotype.Controller" /> <context:include-filter type ="annotation" expression ="org.springframework.web.bind.annotation.ControllerAdvice" /> </context:component-scan > <mvc:annotation-driven /> <mvc:default-servlet-handler /> <bean class ="org.springframework.web.servlet.view.InternalResourceViewResolver" > <property name ="prefix" value ="/" /> <property name ="suffix" value =".jsp" /> </bean > </beans >
(四)、详细类设计
-mapper UserMapper
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 package com.cyan.Mapper;import com.cyan.Model.User;import org.apache.ibatis.annotations.Param;import org.apache.ibatis.annotations.Select;import javax.annotation.Resource;import java.util.List;public interface UserMapper { @Select("select * from LoginDemo") public List<User> selectUser () ; @Select("select * from LoginDemo where username=#{username}") public List<User> selectUserByUsername (@Param("username") String username) ; }
-entity User
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 package com.cyan.Entity;public class User { private int id; private String username,password,slogan; public int getId () { return id; } public void setId (int id) { this .id = id; } public String getUsername () { return username; } public void setUsername (String username) { this .username = username; } public String getPassword () { return password; } public void setPassword (String password) { this .password = password; } public String getSlogan () { return slogan; } public void setSlogan (String slogan) { this .slogan = slogan; } }
-service
1 2 3 4 5 6 7 8 9 10 11 package com.cyan.Service;import com.cyan.Entity.User;public interface IUserService { public User getUserByName (String name) ; public boolean verify (String username,String pwd) ; }
UserService Spring中的几个标签@Component(声明一个类是Spring容器管理的类,可以细分为后面提到的三个标签)、@Controller(控制层)、@Service(服务层)、@Repository(持久层)。标签的作用是让Spring根据名字关联到这个类。
@Autowired标签默认以byType的形式注入,使用这个标签是不需要getter和setter方法的。(这次代码中因为用户名密码校验部分要用到get方法所以写上了) 可以配合@Qualifier标签根据bean的id来装配。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 package com.cyan.Service;import com.cyan.Mapper.UserMapper;import com.cyan.Entity.User;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;@Service("userService") public class UserService implements IUserService { @Autowired private UserMapper userMapper; public void setUserMapper (UserMapper userMapper) { this .userMapper = userMapper; } @Override public User getUserByName (String name) { return userMapper.selectUserByUsername(name).get(0 ); } @Override public boolean verify (String username, String pwd) { if (userMapper.selectUserByUsername(username).get(0 ).getPassword().equals(pwd)) return true ; else return false ; } }
-controller Login
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 package com.cyan.Controller;import com.cyan.Service.IUserService;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestMethod;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;@Controller public class Login { @Autowired private IUserService userService; @RequestMapping("/index") public String index () { return "index" ; } @RequestMapping(value ="/login",method = RequestMethod.POST) public String login (HttpServletRequest req, HttpServletResponse resp) { String username=req.getParameter("username" ); String pwd=req.getParameter("password" ); if (userService.verify(username,pwd)){ req.getSession().setAttribute("user" ,userService.getUserByName(username)); return "success" ; } else return "index" ; } }
jsp页面
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 <%-- Created by IntelliJ IDEA. User: cyan Date: 16 /3 /29 Time: 15 :55 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Login</title> </head> <body> <form action="/login" method="post" > 用户名:<input type="text" name="username" id="username" /> <br> 密码:<input type="password" name="password" id="password" /> <br> <input type="submit" value="登录" /> </form> </body> </html>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 <%@ page import ="com.cyan.Entity.User" %><%-- Created by IntelliJ IDEA. User: cyan Date: 16 /3 /31 Time: 23 :45 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>LoginSuccess</title> </head> <body> 登录成功! <% User user=(User)session.getAttribute("user" ); %> 用户名:<%=user.getUsername()%><br> 个性签名:<%=user.getSlogan()%><br> </body> </html>
运行结果,大家自行测试。 感谢阅读!