SSM(springmvc-spring-mybatis)详细教程
注:需要对mybatis, spring, springmvc, maven, http请求 ,有一定了解的前提。
第一步:使用maven的pom.xml配置jar包(准备框架所需要的各种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/xsd/maven-4.0.0.xsd"> <!--以上约束文件 --> <modelVersion>4.0.0</modelVersion><!--maven配置文件必备的四个属性 --> <groupId>maven.xiaoeyu</groupId><!--项目名,默认为包名 --> <artifactId>MavenSSM</artifactId><!--项目中的某个模块,默认项目名+模块名 --> <version>0.0.1-SNAPSHOT</version><!--版本号。快照 --> <packaging>war</packaging><!--打包方式,在创建maven项目选定 --> <name>MavenSSM</name> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><!--设置maven编码 --> <spring.version>4.3.18.RELEASE</spring.version><!--统一spring相关jar包的版本(为最多使用版本,即更稳定) --> </properties> <!-- 添加项目运行所需要的依赖地址 --> <!--GAV又maven项目的唯一地址。通过g项目名+a模块名+v版本号,指定唯一的jar包 --> <dependencies> <!-- servlet依赖 --> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> <scope>provided</scope> </dependency> <!-- jstl: --> <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency> <!-- Junit测试包 --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> <!--mybatis --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.4.1</version> </dependency> <!--mybatis-spring插件:mybatis与spring整合的jar包 --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>1.3.1</version> </dependency> <!-- spring依赖 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</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-web</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${spring.version}</version> </dependency> <!--mysql连接 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.38</version> </dependency> <!--log4j日志包 --> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency> </dependencies> </project>
第二步:先按照这个模创建package(模式不唯一,这里只是一个基础的),在config下,创建xml文件applicationContext.xml与mybatis.xml配置文件。注释在文件中

mybatis.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> <!--对jdbc的操作放到了applicationContext配置文件中 --> <!--如果没有涉及到缓存cache等必须在该配置文件下进行配置的功能。可不要。 --> </configuration>
applicationContext.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:aop="http://www.springframework.org/schema/aop" 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/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!--每一个bean都是一个对象,在这里配置的bean都是交由IOC容器进行管理的 --> <!--配置数据源:DriverManagerDataSource支持mybatis,jdbc。 --> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver"></property> <property name="url" value="jdbc:mysql://localhost:3306/bcs?useUnicode=true&characterEncoding=utf-8"></property> <property name="username" value="root"></property> <property name="password" value=""></property> </bean> <!-- 把 SqlSessionFactoryBean交给spring容器来管理 --> <bean class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource"></property> <property name="configLocation" value="classpath:config/mybatis.xml"></property><!--持久城缓存等必须在mybatis.xml中的配置信息,无法在这里替代,引用原来的文件 --> <!-- <property name="mapperLocations" value="与接口对象的.xml"></property>用于接口映射包的扫描 --> </bean> <!-- 创建一个数据映射器:给dao层接口(用注解写SQL语句的接口)创建实现类并生成映射 --> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com.xiaoeyu.dao"></property> </bean> <!--注解:用来简化xml配置文件,少些好多bean。 --> <!--组件扫描器:com.xiaoeyu.service及其后续的包都会被扫描(com.xiaoeyu.service.impl),在目录结构中,每一个点相当于文件夹的一层。把范围内的带有注解的类与属性都交给IOC管理 --> <context:component-scan base-package="com.xiaoeyu.service" /> </beans>
第三步:编写持久层代码,并验证。
1.在com.xiaoeyu.bean在创建一个pojo类,UserBean
package com.xiaoeyu.bean; public class UserBean { private int uid; private String uaccount; private String upassword; public int getUid() { return uid; } public String getUaccount() { return uaccount; } public String getUpassword() { return upassword; } public void setUid(int uid) { this.uid = uid; } public void setUaccount(String uaccount) { this.uaccount = uaccount; } public void setUpassword(String upassword) { this.upassword = upassword; } @Override public String toString() { return "UserBean [uid=" + uid + ", uaccount=" + uaccount + ", upassword=" + upassword + "]"; } }
2.com.xiaoeyu.dao创建一个接口,用于与操作数据库
package com.xiaoeyu.dao; import org.apache.ibatis.annotations.Select; import com.xiaoeyu.bean.UserBean; public interface IUserDao { // 在数据库中applicationContext配置数据源处,url的value值中,?前边的bcs是连接的mysql中的一个库,后面是修改编码集为UTF-8 // applicationContext数据映射器,根据注解创建实体类并形成映射,可以直接根据接口名(接口名在映射时有一定规则)获得调用方法, //或者用@AutoWare自动装配给指定的引用进行调用(推荐)。 // 执行查询操作。在t_user表中通过账号和密码。把查询出来的*(id,账号,密码)根据mybatis的性质,一一映射到对应的属性中 @Select("select * from t_user where uaccount=#{uaccount} and upassword=#{upassword}") public UserBean findByNameAndPwd(UserBean bean); }
3验证mybatis整合是否成功。(是否IOC容器可以创建并管理数据库连接,生成dao层下的实现类并创建映射),在src/test/java中随便创建一个类,TestMain
package com.xiaoeyu.test; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.xiaoeyu.bean.UserBean; import com.xiaoeyu.dao.IUserDao; import com.xiaoeyu.service.impl.UserServiceImpl; public class TestMain { //验证mybatis是否整合成功 //@Test测试,在pom.xml中有一个Junit就是这里用来测试的 @Test public void test1() { ApplicationContext ac = new ClassPathXmlApplicationContext("config/applicationContext.xml");//加载applicationContext.xml配置文件 IUserDao dao = ac.getBean(IUserDao.class);//获取IOC容器中根据注解创建并管理的IUserDao.class对应的操作数据库的对象。IOC帮你根据接口与注解生成了实现类 UserBean bean = new UserBean(); bean.setUaccount("123"); bean.setUpassword("123"); UserBean bean2 = dao.findByNameAndPwd(bean); System.out.println(bean2); }
}
测试成功:Junit绿条,并且控制台打印查询的数据,不成功慢慢慢慢调,不懂的看错误原因去百度。一般按照这个步骤不会出错。(对maven,mybatis,spring要有一定的基础)

第四步:编写并验证业务层
1.在com.xiaoeyu.service编写业务层接口,IUserService
package com.xiaoeyu.service; import com.xiaoeyu.bean.UserBean; public interface IUserService { public UserBean findUser(UserBean bean); }
2.在com.xiaoeyu.service.impl编写业务层实现类UserServiceImpl
package com.xiaoeyu.service.impl; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import com.xiaoeyu.bean.UserBean; import com.xiaoeyu.dao.IUserDao; import com.xiaoeyu.service.IUserService; @Service // @Service用于业务层注解,这个类交由IOC容器进行管理 public class UserServiceImpl implements IUserService { @Autowired // 自动装配:这个属性的依赖对象交由IOC容器注入:IOC根据dao的类型IUserDao,把根据接口创建的(操作数据库的)实现类,在运行时注入(赋值)给dao IUserDao dao; @Override public UserBean findUser(UserBean bean) { UserBean re = dao.findByNameAndPwd(bean); System.out.println(re); return re; } }
4.验证业务层(也包括mybatis与spring的整合)是否成功。在src/test/java中随便创建一个类,TestMain
package com.xiaoeyu.test; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.xiaoeyu.bean.UserBean; import com.xiaoeyu.dao.IUserDao; import com.xiaoeyu.service.impl.UserServiceImpl; public class TestMain { // 验证mybatis是否整合成功 // @Test测试,在pom.xml中有一个Junit就是这里用来测试的 public void test1() { ApplicationContext ac = new ClassPathXmlApplicationContext("config/applicationContext.xml");// 加载applicationContext.xml配置文件 IUserDao dao = ac.getBean(IUserDao.class);// 获取IOC容器中根据注解创建并管理的IUserDao.class对应的操作数据库的对象。IOC帮你根据接口与注解生成了实现类 UserBean bean = new UserBean(); bean.setUaccount("123"); bean.setUpassword("123"); UserBean bean2 = dao.findByNameAndPwd(bean); System.out.println(bean2); } // 参考test1,获取业务层实现类,且获取到的实现类中的dao已经被注入了依赖的对象 @Test public void test2() { ApplicationContext ac = new ClassPathXmlApplicationContext("config/applicationContext.xml"); UserServiceImpl bean = ac.getBean(UserServiceImpl.class); UserBean po = new UserBean(); po.setUaccount("123"); po.setUpassword("123"); UserBean user = bean.findUser(po); System.out.println(user); } }
测试成功。Junit显示绿条,并且控制台有打印,之所以两条数据,在test中有打印语句,在

第五步:编写并验证表示层。本层是一个分界点,在整合的时候,springmvc本就属于spring的一个模块。无论SSM还是SSH,springmvc框架在这一步是相对独立的。spring与mybatis或者hibernate的整合在前面解决,对后续的步骤不影响
1.配置springmvc.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.xsd"> <!--注解驱动:把处理器映射器,处理器适配器合二为一 --> <mvc:annotation-driven /> <!--视图解析器 --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"></bean> <!--组件扫描器 :扫描指定包下被注解修饰的类--> <context:component-scan base-package="com.xiaoeyu.controller"></context:component-scan> <!-- 设置一个默认的servlet来处理静态资源 --> <mvc:default-servlet-handler /> </beans>
2.编写处理器:在springmvc中处理器是单例的,只有一个,url请求直接到达方法。面对方法的请求,不建议定义成员变量。
分发请求给响应的业务层,需要一个业务层接口IUserService service
package com.xiaoeyu.controller; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import com.xiaoeyu.bean.UserBean; import com.xiaoeyu.service.IUserService; @Controller // 处理器注解:被修饰的类被组件扫描器扫到时,作为处理器 public class Handler { @Autowired IUserService service;//业务层接口,用于根据请求执行相关的业务 @RequestMapping("/find") // 映射器注解:被修饰的类被组件扫描器扫到时,作为处理器的url映射。当url参数请求地址为../find时,匹配到该方法。 public void find(UserBean bean) { UserBean user = service.findUser(bean); System.out.println(user); } }
3.表示层涉及到网络请求要编写web.xml配置文件,通过http请求进行测试。之前测试的时候获取类,是通过手动加载配置文件创建的。现在在web.xml中配置需要加载的配置文件,在服务器启动时,根据设置的参数,在起第一次请求或者服务器启动时便加载配置文件,以便获取相应的对象。
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1"> <!--springmvc的配置 --> <!--把指定位置(classpath:)的配置文件,传给 DispatcherServlet(或者其父类)中的contextConfigLocation引用。作为加载项 --> <!--所有被url-pattern拦截的请求都会被与相应的servlet-name对应的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:config/spring-mybatis.xml</param-value> </init-param> <load-on-startup>0</load-on-startup><!-- 加载的优先级。为整数。服务器启动时就加载,越小越优先 --> </servlet> <servlet-mapping> <servlet-name>springmvc</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <!-- 加载springioc容器 --> <context-param><!-- spring的上下文对象 --> <param-name>contextConfigLocation</param-name> <param-value>classpath:config/applicationContext.xml</param-value> </context-param> <!--监听器:当Tomcat启动时,会触发,加载applicationContext.xml配置文件,创建出IOC容器及IOC容器管理的对象,并注入到所需的类中 --> <!--否则,相关的类类中,要调用接口引用的方法,但是引用被没有被注入依赖的对象,就会报错 --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> </web-app>
4.验证:
4.1:把项目部署到Tomcat服务器,启动服务器,查看是否报错,警告信息不算,有时还会有严重的缺少日志的信息,对请求的处理没有影响,本此整合不会出现。
(步骤不出错,一般不会报错,真错了,根据错误信息去百度)。
4.2:打开游览器,在指定地址输入请求参数。虽然是500的错误.,我们看后台控制台

4.3后台控制台信息。传过去的参数打印出来,请求到了方法,我们换一下参数,upassword为123

4.4:有三条打印语句。
第一句:表示层参数bean的打印
第二句:服务层实现类中,dao的方法通过给的bean参数,从数据库中查询出来的完整的bean对象的打印。(表示层-服务层-dao持久层,三层连接没毛病)
第三局:就是第二句打印的对象,只是又返回到表示层,在表示层打印了一遍。
报错是因为:返回值为void。在springmvc作为前端控制器。返回对象,字符串,或别的交由视图解析器进行处理。整合完毕。
解决:返回一个字符串形式的本地的静态资源路径错误就没有了。

附加:
* 1 spring springMVC与web容器的关系:springmvc和spring它俩都是容器,容器就是管理对象的地方,例如Tomcat,就是管理servlet对象的,而springMVC容器和spring容器,就是管理 bean对象的地方.
再说的直白点,springmvc就是管理controller对象的容器,spring就是管理service和dao的容器,这下你明白了吧。所以我们在springmvc的配置文件里配置的扫描路径就是controller的路径,而spring的配置文件里自然配的就是service和dao的路径,在配置文件中有灰色高亮
*2 spring容器和springmvc容器的关系是父子容器的关系。spring容器是父容器,springmvc是子容器。在子容器里可以访问父容器里的对象,但是在父容器里不可以访问子容器的对象,说的通俗点就是,在controller里可以访问service对象,但是在service里不可以访问controller对象. 所以这么看的话,所有的bean,都是被spring或者springmvc容器管理的,他们可以直接注入。然后springMVC的拦截器也是springmvc容器管理的,所以在springmvc的拦截器里,可以直接注入bean对象。
可以在Controller层,对service层的属性进行注入,因为springmvc容器可以访问spring容器,但是不能在service层,写一个Controller层的类进行注入,1是不符合规范.2 是service层属于spring容器不发访问springmvc容器中的对象.
Spring 框架允许在一个应用中创建多个上下文容器。但是建议容器之间有父子关系。可以通过 ConfigurableApplicationContext 接口中定义的 setParent 方法设置父容器。
一旦设置父子关系,则可以通过子容器获取父容器中除 PropertyPlaceHolder 以外的所有资源,父容器不能获取子容器中的任意资源(类似 Java 中的类型继承)。
典型的父子容器: spring 和 springmvc 同时使用的时候。ContextLoaderListener 创建的容器是父容器,DispatcherServlet 创建的容器是子容器。
保证一个 JVM 中,只有一个树状结构的容器树。可以通过子容器访问父容器资源。
*3 web容器是管理servlet,以及监听器(Listener)和过滤器(Filter)的。这些都是在web容器的掌控范围里。但他们不在spring和springmvc的掌控范围里。因此,我们无法在这些类中直接使用Spring注解的方式来注入我们需要的对象,是无效的,
web容器是无法识别的。
但我们有时候又确实会有这样的需求,比如在容器启动的时候,做一些验证或者初始化操作,这时可能会在监听器里用到bean对象;又或者需要定义一个过滤器做一些拦截操作,也可能会用到bean对象。
那么在这些地方怎么获取spring的bean对象呢?下面我提供两个方法:
public void contextInitialized(ServletContextEvent sce) {
ApplicationContext context = (ApplicationContext) sce.getServletContext().getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
UserService userService = (UserService) context.getBean("userService");
}
public void contextInitialized(ServletContextEvent sce) {
WebApplicationContext webApplicationContext = WebApplicationContextUtils.getWebApplicationContext(sce.getServletContext());
UserService userService = (UserService) webApplicationContext.getBean("userService");
}
注意:以上代码有一个前提,那就是servlet容器在实例化ConfigListener并调用其方法之前,要确保spring容器已经初始化完毕!而spring容器的初始化也是由Listener(ContextLoaderListener)完成,因此只需在web.xml中先配置初始化spring容器的Listener,然后在配置自己的Listener。
*4 结合上面的123,可以推测出来,spring springMVC 与 web容器的关系.
2. 现在使用MVC框架,不需要在servlet的service方法下,或者在service调用的doget dopost方法下写代码. 是因为现在web容器还是把请求封装成request和response对象.传给servlet中的service方法.
但是在service是由现在的框架通过实现servlet重写的.在service中,把请求根据url匹配扔给他们管理的bean进行处理.
而他们管理的对象 Conroller和Service都是我们写的.我们写好以后,他们管理起来,web容器接收到请求时,调用service方法,在方法中匹配我们写的Controller和Service来进行处理.
浙公网安备 33010602011771号