喜欢与改变

导航

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&amp;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 + "]";
    }

}
UserBean

 

  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);
}
IUSerService

  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容器的关系.

1.web容器接受到浏览器发送的请求,把请求封装成request和response,调用servlet中的方法传递过来.所以之前我们就在servlet的service方法中,通过对两个参数的处理来完成与客户端的相应.
2. 现在使用MVC框架,不需要在servlet的service方法下,或者在service调用的doget dopost方法下写代码. 是因为现在web容器还是把请求封装成request和response对象.传给servlet中的service方法.
  但是在service是由现在的框架通过实现servlet重写的.在service中,把请求根据url匹配扔给他们管理的bean进行处理.
  而他们管理的对象 Conroller和Service都是我们写的.我们写好以后,他们管理起来,web容器接收到请求时,调用service方法,在方法中匹配我们写的Controller和Service来进行处理.

 

posted on 2019-01-16 19:32  喜欢与改变  阅读(387)  评论(0)    收藏  举报