SSM框架简介
SSM框架,是Spring + Spring MVC + MyBatis的缩写,这个是继SSH之后,目前比较主流的Java EE企业级框架,适用于搭建各种大型的企业级应用系统。 我们先大概的回顾一下吧。
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)的容器框架。
A.控制反转(IOC)是什么呢?
IOC:控制反转也叫依赖注入。利用了工厂模式将对象交给容器管理,你只需要在spring配置文件总配置相应的bean,以及设置相关的属性,让spring容器来生成类的实例对象以及管理对象。在spring容器启动的时候,spring会把你在配置文件中配置的bean都初始化好,然后在你需要调用的时候,就把它已经初始化好的那些bean分配给你需要调用这些bean的类(假设这个类名是A),分配的方法就是调用A的setter方法来注入,而不需要你在A里面new这些bean了。
[注意]:面试的时候,如果有条件,画图,这样更加显得你懂了
B.面向切面(AOP)又是什么呢?
首先,需要说明的一点,AOP只是Spring的特性,它就像OOP一样是一种编程思想,并不是某一种技术,AOP可以说是对OOP的补充和完善。OOP引入封装、继承和多态性等概念来建立一种对象层次结构,用以模拟公共行为的一个集合。当我们需要为分散的对象引入公共行为的时候,OOP则显得无能为力。也就是说,OOP允许你定义从上到下的关系,但并不适合定义从左到右的关系。例如日志功能。日志代码往往水平地散布在所有对象层次中,而与它所散布到的对象的核心功能毫无关系。在OOP设计中,它导致了大量代码的重复,而不利于各个模块的重用。将程序中的交叉业务逻辑(比如安全,日志,事务等),封装成一个切面,然后注入到目标对象(具体业务逻辑)中去。
实现AOP的技术,主要分为两大类:一是采用动态代理技术,利用截取消息的方式,对该消息进行装饰,以取代原有对象行为的执行;二是采用静态织入的方式,引入特定的语法创建“方面”,从而使得编译器可以在编译期间织入有关“方面”的代码。
[简单点解释],比方说你想在你的biz层所有类中都加上一个打印‘你好,AOP’的功能这你经可以用aop思想来做,你先写个类写个方法,方法经实现打印‘你好,AOP’让后你Ioc这个类 ref=“biz.*”让每个类都注入。
2.Spring MVC简介
Spring MVC属于Spring Framework的后续产品,已经融合在Spring Web Flow里面,它原生支持的Spring特性,让开发变得非常简单规范。Spring MVC 分离了控制器、模型对象、分派器以及处理程序对象的角色,这种分离让它们更容易进行定制。
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对象)映射成数据库中的记录。可以这么理解,MyBatis是一个用来帮你管理数据增删改查的框架。
先看一下项目的结构吧
说了这么多,现在回归正题,SSM框架里面有很多繁杂的配置,一共有三个
1.web.xml
2.spring.xml
3.mvc-servlet.xml
下面将会依次详细介绍三个配置文件的配置方法以及配置的含义
1.web.xml
web.xml是ssm项目当中最重要的一个配置文件,当服务启动时会首先加载web.xml这个文件,里面包括了对前端控制器、乱码等的配置
下面贴上代码,代码当中有详细的注释解释每个配置的意思
<!DOCTYPE web-app PUBLIC"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN""http://java.sun.com/dtd/web-app_2_3.dtd" ><web-app version="2.4"xmlns="http://java.sun.com/xml/ns/j2ee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"><!--spring的配置-->
<!--==================================================--><!-- 配置srping的位置 --><context-param><param-name>contextConfigLocation</param-name><param-value>classpath:spring.xml</param-value></context-param><!-- 配置监听器 --><listener><listener-class>org.springframework.web.context.ContextLoaderListener</listener-class></listener><!--springmvc需要配置的--><!--==================================================--><!-- 配置springmvc的核心控制器 --><servlet><servlet-name>mvc</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><init-param><param-name>contextConfigLocation</param-name><param-value>classpath:mvc-servlet.xml</param-value></init-param><load-on-startup>1</load-on-startup></servlet><servlet-mapping><servlet-name>mvc</servlet-name><url-pattern>/</url-pattern></servlet-mapping><!-- 解决乱码的配置 --><filter><filter-name>characterEncodingFilter</filter-name><filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class><init-param><param-name>encoding</param-name><param-value>UTF-8</param-value></init-param><init-param><param-name>forceEncoding</param-name><param-value>true</param-value></init-param></filter><filter-mapping><filter-name>characterEncodingFilter</filter-name><url-pattern>/*</url-pattern></filter-mapping><!-- 请求method支持 put和delete必须添加过滤器 --><filter><filter-name>myFilter</filter-name><filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class></filter><filter-mapping><filter-name>myFilter</filter-name><url-pattern>/*</url-pattern></filter-mapping><!--<!– 启用druid的监控功能 –>--><servlet><servlet-name>statViewServlet</servlet-name><servlet-class>com.alibaba.druid.support.http.StatViewServlet</servlet-class><init-param><param-name>loginUsername</param-name><param-value>admin</param-value></init-param><init-param><param-name>loginPassword</param-name><param-value>admin</param-value></init-param><load-on-startup>1</load-on-startup></servlet><servlet-mapping><servlet-name>statViewServlet</servlet-name><url-pattern>/druid/*</url-pattern></servlet-mapping>
</web-app>
2.spring.xml
spring.xml的作用是为了给spring进行配置
<?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"xmlns:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsdhttp://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.1.xsdhttp://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.1.xsd"><!-- 扫描cn --><context:component-scan base-package="cn"><!-- spring是bean的容器(spring用来操做 service+repository)controler是springmvc操作的 所以排除--><!--<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller" />--></context:component-scan><!-- 扫描jdbc文件 --><context:property-placeholder location="classpath:jdbc.properties" /><!--所有数据库操作的源头 实现自接口DataSouce DriverManagerDataSource还有很多连接池继承DataSouce DriverManagerDataSource 实现了很多子连接池 比如c3p0 dbcp druid这里我们就用阿里的druid,因为这个连接池有一个监控功能--><!-- 连接数据库 --><bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"><property name="url" value="${url}"></property><property name="driverClassName" value="${driverClass}"></property><property name="username" value="${username1}"></property><property name="password" value="${password1}"></property><!-- 默认初始化的连接个数 --><property name="initialSize" value="1"></property><!-- 最大允许的连接个数 --><property name="maxActive" value="200"></property><!-- 最大的等待人数 --><property name="maxIdle" value="100"></property><!-- 开启sql统计功能 --><property name="filters" value="stat"></property></bean><!-- 事务管理器 不再使用jdbc的commit和rollback 必须由事务管理器提供 配置事物管理器必须要注入dataSource--><bean id="tm" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource"></property></bean><!-- 定义事物里面的通知--><tx:advice id="txAdvise" transaction-manager="tm"><tx:attributes><!--tx:method的作用是拦截指定方法开头的 然后对他进行事物处理 --><tx:method name="insert*" propagation="REQUIRED" /><tx:method name="update*" propagation="REQUIRED" /><tx:method name="delete*" propagation="REQUIRED" /><!--read-only="true" 意思是除了上面拦截的以外 其他的都不拦截--><tx:method name="*" read-only="true" /></tx:attributes></tx:advice><aop:config><!-- 定义切点(搜索条件) aop:pointcut 意思相当于跟if差不多 满足条件的就会进来表示式 execution(返回值 包.类.方法(参数 ...代表任意多个参数))id 表示切点的名字--><aop:pointcut expression="execution(* cn.et.service.*.*(..))" id="myPointCut" /><!-- 关联切点和事务管理器 将事物跟切点连接起来--><aop:advisor advice-ref="txAdvise" pointcut-ref="myPointCut" /></aop:config><!-- 集成mybatis --><!-- 实例化一个SqlSessionFactory工厂--><bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"><!--指定数据源--><property name="dataSource" ref="dataSource"></property><!--指定实体文件所在的位置--><property name="typeAliasesPackage" value="cn.et.model"/><!--指定mapper.xml文件所在的位置--><property name="mapperLocations" value="classpath:mapper/*.xml" /></bean><!-- 扫描mybatis的接口映射文件 --><bean id="scannerConfigurer" class="org.mybatis.spring.mapper.MapperScannerConfigurer"><property name="basePackage" value="cn.et.mapper"></property></bean>
</beans>
3.mvc-servlet.xml
mvc-servlet.xml是为了配置springMVC
<?xml version="1.0" encoding="UTF-8"?>
<beansxmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:mvc="http://www.springframework.org/schema/mvc"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsdhttp://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.2.xsd
"><!-- 扫描cn --><context:component-scan base-package="cn"><!-- pringmvc主要操作控制层、视图层所以给不相关的层次的注解排除--><!--<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Service"/>--><!--<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Repository"/>--></context:component-scan><!--如果发现是静态资源的请求,就将该请求转由Web应用服务器默认的Servlet处理,如果不是静态资源的请求,才由DispatcherServlet继续处理。--><mvc:default-servlet-handler/><!-- 引用返回对象 响应json的消息转换器 --><mvc:annotation-driven><mvc:message-converters><bean class="org.springframework.http.converter.ByteArrayHttpMessageConverter"><property name="supportedMediaTypes"><list><value>text/html</value><value>application/x-www-form-urlencoded</value></list></property></bean><!-- 配置返回对应解析成json的消息转换器 --><bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"><property name="supportedMediaTypes"><list><value>text/html</value><value>application/x-www-form-urlencoded</value></list></property></bean></mvc:message-converters></mvc:annotation-driven>
</beans>
小提示
关于配置文件这个东西,在初学各种框架的时候非常让人头疼,一不小心配置错误,项目就运行不了。所以不如直接从网上找个小项目的源码把代码删除,直接用别人的配置来做练习,在框架能熟练运用之后再慢慢学习配置文件的问题。
据本人亲自整合,在jar包导入完全的时候,上面的这些配置文件可直接使用(数据库连接参数被删除,包名和一些路径的配置根据自己项目来进行更改)
到此我们的SSM环境也就搭建好了,现在就要去实现业务的代码了
1.model层是实体类,属性对应数据库表的每个字段,并且我们使用驼峰规则命名属性(这里很重要,字段userName和UserName在封装时差别很大,会映射不到mapper层的xml上),我们一贯的做法会让model序列化,这里虽然没有并发的情况,但是这是一种良好的做法。代码如下:
package cn.et.model;public class Student {private String id;private String name;private String age;private String sex;public String getId() {return id;}public void setId(String id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getAge() {return age;}public void setAge(String age) {this.age = age;}public String getSex() {return sex;}public void setSex(String sex) {this.sex = sex;}
}
2.mapper层,这里实现和数据库直接交互的接口,@Repository的注解目的是持久化数据层。在这里为了同时将mybatis注解写sql跟xml写sql表现出来,我有的接口用的是注解实现的有的接口用的是xml实现的代码如下:
package cn.et.mapper;import cn.et.model.Student;
import org.apache.ibatis.annotations.*;import java.util.List;public interface StudentMapper {/*** 添加* @param student*/void insertStudent(@Param("student") Student student);/*** 删除* @param id*/@Delete("delete from student where sid=#{id}")void deleteStudent(@Param("id") String id);/*** 修改* @param student*/void updateStudent(@Param("student") Student student);/*** 查询所有* @return*/@Results({@Result(column = "sid",property = "id"),@Result(column = "sname",property = "name"),@Result(column = "sage",property = "age"),@Result(column = "ssex",property = "sex")})@Select("select * from student")List<Student> studentList();/*** 根据id查询单个* @param id* @return*/@Results({@Result(column = "sid",property = "id"),@Result(column = "sname",property = "name"),@Result(column = "sage",property = "age"),@Result(column = "ssex",property = "sex")})@Select("select * from student where sid=#{id}")Student studentById(@Param("id") String id);/*** 根据条件查询* @param student* @return*/List<Student> studentQuery(@Param("student") Student student);}
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="cn.et.mapper.StudentMapper" ><resultMap id="studentMap" type="cn.et.model.Student"><result property="id" column="sid"/><result property="name" column="sname"/><result property="age" column="sage"/><result property="sex" column="ssex"/></resultMap><insert id="insertStudent">INSERT INTO student (sid,sname,sage,ssex) VALUES (#{student.id},#{student.name},#{student.age},#{student.sex})</insert><update id="updateStudent">UPDATE student<set><if test="student.name !=null and student.name !=''">sname=#{student.name},</if><if test="student.age !=null and student.age !=''">sage=#{student.age},</if><if test="student.sex !=null and student.sex !=''">ssex=#{student.sex},</if></set>WHERE sid =#{student.id}</update><select id="studentQuery" resultMap="studentMap">select * from student<where><if test="student.name !=null and student.name !=''">and sname like '%${student.name}%'</if><if test="student.age !=null and student.age !=''">and sage=#{student.age}</if><if test="student.sex !=null and student.sex !=''">and ssex=#{student.sex}</if></where></select></mapper>
3.service层,这是用来处理业务的,代码如下:
package cn.et.service;import cn.et.model.Student;import java.util.List;public interface StudentService {/*** 添加* @param student*/void insertStudent(Student student);/*** 删除* @param id*/void deleteStudent(String id);/*** 修改* @param student*/void updateStudent(Student student);/*** 查询所有* @return*/List<Student> studentList();/*** 根据id查询单个* @param id* @return*/Student studentById(String id);/*** 根据条件查询* @param student* @return*/List<Student> studentQuery(Student student);}
4.serviceImpl层是service的实现类,@Service注解告诉Spring这是个业务层,Service中声明了几个接口,我们并没有去真正去实现,但是有人想为什么不直接写个实现类,反而要加一个Service层呢?这个问题,这要归结到代码复用性和维护性问题,如果你直接写一个实现,当你增加新的功能时就要在一大堆代码中是添加修改,这是非常耗时的操作,所以接口和实现分离有利于维护,代码如下:
package cn.et.service.impl;import cn.et.mapper.StudentMapper;
import cn.et.model.Student;
import cn.et.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.util.List;@Service
public class StudentServiceImpl implements StudentService {@AutowiredStudentMapper studentMapper;public void insertStudent(Student student) {studentMapper.insertStudent(student);}public void deleteStudent(String id) {studentMapper.deleteStudent(id);}public void updateStudent(Student student) {studentMapper.updateStudent(student);}public List<Student> studentList() {List<Student> students = studentMapper.studentList();return students;}public Student studentById(String id) {return studentMapper.studentById(id);}public List<Student> studentQuery(Student student) {return studentMapper.studentQuery(student);}
}
5.控制层Controller
使用@Controller注解,然后使用@AutoWired导入service层,因为service中的方法是我们使用到的,controller通过接收前端传过来的参数进行业务操作,在返回一个指定的路径或者数据表。RequestMapping是一个用来处理请求地址映射的注解,可用于类或方法上。用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径。@responseBody注解的作用是将controller的方法返回的对象通过适当的转换器转换为指定的格式之后,写入到response对象的body区,通常用来返回JSON数据或者是XML数据,需要注意的呢,在使用此注解之后不会再走试图处理器,而是直接将数据写入到输入流中,他的效果等同于通过response对象输出指定格式的数据。上面讲的这些都是Spring MVC知识,如果你看不懂请百度Spring MVC流程控制,基础知识我就不多废话。具体代码如下:
package cn.et.controller;import cn.et.model.Student;
import cn.et.service.StudentService;
import cn.et.tool.CommonResponse;
import cn.et.tool.Response;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.util.List;@RestController
public class StudentController {@AutowiredStudentService studentService;@RequestMapping("insertStudent")public Response insertStudent(Student student){studentService.insertStudent(student);return Response.success();}@RequestMapping("deleteStudent")public Response deleteStudent(String id){studentService.deleteStudent(id);return Response.success();}@RequestMapping("updateStudent")public Response updateStudent(Student student){studentService.updateStudent(student);return Response.success();}@RequestMapping("studentList")public Response studentList(){List<Student> students = studentService.studentList();return new CommonResponse<List<Student>>(students);}@RequestMapping("studentById")public Response studnetById(String id){Student student = studentService.studentById(id);return new CommonResponse<Student>(student);}@RequestMapping("studentQuery")public Response studentQuery(Student student){List<Student> students = studentService.studentQuery(student);return new CommonResponse<List<Student>>(students);}}
至此我们的后台代码就告一段落了,如有疑问的小伙伴给我留言。。。。。。。。