震惊!!!SSM居然是这样的!

北战南征 提交于 2019-12-01 19:30:20

SSM框架

SSMSpring+SpringMVC+MyBatis)框架集由SpringMyBatis两个开源框架整合而成(SpringMVCSpring中的部分内容)。常作为数据源较简单的web项目的框架。

 

一、Spring部分

  Spring就像是整个项目中装配bean的大工厂,在配置文件中可以指定使用特定的参数去调用实体类的构造方法来实例化对象。也可以称之为项目中的粘合剂。

  Spring的核心思想是IoC(控制反转),即不再需要程序员去显式地`new`一个对象,而是让Spring框架帮你来完成这一切。

 

1Spring的运行流程

 

 

第一步:加载配置文件ApplicationContext ac = new ClassPathXmlApplicationCont

ext("beans.xml"); ApplicationContext接口,它由BeanFactory接口派生而来,因而提供了BeanFactory所有的功能。配置文件中的bean的信息是被加载在HashMap中的,一个bean通常包括,idclassproperty等,beanid对应HashMap中的keyvalue呢就是bean

 

第二步:调用getBean方法,getBean是用来获取applicationContext.xml文件里bean的,()写的是beanid。一般情况都会强转成我们对应的业务层(接口)。例如SpringService springService =(SpringService)ac.getBean("Service");

 

第三步:这样我们就可以调用业务层(接口实现)的方法。

 

 

 

 

 

那么bean中的东西到底是怎么注入进去的?简单来讲,就是在实例化一个bean时,实际上就实例化了类,它通过反射调用类中set方法将事先保存在HashMap中的类属性注入到类中。这样就回到了我们Java最原始的地方,对象.方法,对象.属性

 

2Spring的原理

 

 

什么是spring 

spring是一个容器框架,它可以接管web层,业务层,dao层,持久层的各个组件,并且可以配置各种bean, 并可以维护beanbean的关系,当我们需要使用某个bean的时候,我们可以直接getBean(id),使用即可

 

Spring目的:就是让对象与对象(模块与模块)之间的关系没有通过代码来关联,都是通过配置类说明管理的(Spring根据这些配置 内部通过反射去动态的组装对象) ,Spring是一个容器,凡是在容器里的对象才会有Spring所提供的这些服务和功能。

 

层次框架图:

 

 

 

 

 

说明:

 

web层: struts充当web层,接管jspaction,表单,主要体现出mvc的数据输入,数据的处理,数据的显示分离

model层: model层在概念上可以理解为包含了业务层,dao层,持久层,需要注意的是,一个项目中,不一定每一个层次都有

持久层:体现oop,主要解决关系模型和对象模型之间的阻抗

 

 

 

3Spring的核心技术

 

IOC 

iocinverse of control)控制反转:所谓反转就是把创建对象(bean)和维护对象(bean)之间的关系的权利从程序转移到spring的容器(spring-config.xml

 

 

 

 

说明:<bean></bean>这对标签元素的作用:当我们加载spring框架时,spring就会自动创建一个bean对象,并放入内存相当于我们常规的new一个对象,而<property></property>中的value则是实现了“对象.set方法”,这里也体现了注入了概念

通俗讲,控制权由应用代码中转到了外部容器,控制权的转移,是所谓反转。也就是说,正常我们都是新建对象,才可以调用对象。现在不需要了,交给容器来管理,我们只需要通过一些配置来完成把实体类交给容器这么个过程。这样可以减少代码量,简化开发的复杂度和耦合度。 

 

这里,我要解释下几个概念:

1.控制反转只是一个概念,我理解为一种设计模式。

2.控制反转的主要形式有两种:依赖查找和依赖注入

依赖查找:容器提供回调接口和上下文条件给组件。EJBApache Avalon 都使用这种方式。这样一来,组件就必须使用容器提供的API来查找资源和协作对象,仅有的控制反转只体现在那些回调方法上(也就是上面所说的 类型1):容器将调用这些回调方法,从而让应用代码获得相关资源。

依赖注入:组件不做定位查询,只提供普通的Java方法让容器去决定依赖关系。容器全权负责的组件的装配,它会把符合依赖关系的对象通过JavaBean属性或者构造函数传递给需要的对象。通过JavaBean属性注射依赖关系的做法称为设值方法注入(Setter Injection);将依赖关系作为构造函数参数传入的做法称为构造器注入(Constructor Injection)。

 

 

DI

 

didependency injection)依赖注入:实际上diioc是同一个概念,spring的设计者,认为di更准确的表示spring的核心

spring提倡接口编程,在配合di技术就可以达到层与层解耦的目的,为什么呢?因为层与层之间的关联,由框架帮我们做了,这样代码之间的耦合度降低,代码的复用性提高

 

上面也解释了这个概念,其实现方式有三种:属性注入(setter注入),构造器注入和自动装配。

 

方式一、属性注入

 

package com.spring.demo02.entity;  

public class Programmer {  

  

    private String name;  

    private String sex;  

  

    // 在这里定义要依赖的computer属性,加上set方法  

    private Computer computer;  

  

    public String getName() {  

        return name;  

    }  

  

    public void setName(String name) {  

        this.name = name;  

    }  

  

    public String getSex() {  

        return sex;  

    }  

  

    public void setSex(String sex) {  

        this.sex = sex;  

    }  

  

    public Computer getComputer() {  

        return computer;  

    }  

  

    /** 

     * 加上Setter方法 

     * */  

    public void setComputer(Computer computer) {  

        this.computer = computer;  

    }  

package com.spring.demo02.entity;  

public class Computer {  

      

    private String brand;  

    private String color;  

    private String size;  

      

    public void coding() {  

        System.out.println("Computer is coding!!!");  

    }  

  

    public String getBrand() {  

        return brand;  

    }  

  

    public void setBrand(String brand) {  

        this.brand = brand;  

    }  

  

    public String getColor() {  

        return color;  

    }  

  

    public void setColor(String color) {  

        this.color = color;  

    }  

  

    public String getSize() {  

        return size;  

    }  

  

    public void setSize(String size) {  

        this.size = size;  

    }    

}

看上面的代码,可以发现,Programmer类里面,有3个属性,name,sex,computer,并且都有对应的gettersetter方法;Computer类里面也有三个属性,分别是品牌、颜色、尺寸,也都有对应的gettersetter方法。这只是第一步,在类里面声明属性并且实现set方法。

 

接下来,要写一个springxml配置文件,如下:

 

<?xml version="1.0" encoding="UTF-8"?>  

  

<beans xmlns="http://www.springframework.org/schema/beans"  

    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">  

      

  <bean id="programmer" class="com.spring.demo2.entity.Programmer">  

    <property name="name" value="小李"></property>  

    <property name="sex" value=""></property>  

    <property name="computer" ref="computer"></property>  

  </bean>  

    

  <bean id="computer" class="com.spring.demo2.entity.Computer">  

    <property name="brand" value="hp"></property>  

    <property name="color" value=""></property>  

    <property name="size" value="14"></property>  

  </bean>  

    

</beans>

解读一下这个xml文件:

1.声明一个bean,可以理解为实例化了一个对象。那这里实例化了两个对象(programmercomputer),各个属性都已经赋值上去。

 

2.idprogrammerbean,其实就是Programmer类;通过给property赋值,Spring就会通过Programmer类的各个属性的set方法,逐一给Programmer的属性赋值。

 

3.programmer里面,有一个属性是computer的,可以看到它属性值是 ref="computer",这就说明computer这个属性是个引用,这里ref后面的值其实就是指向另一个beanid值,所以这里引用的是idcomputerbean

 

以上,就是属性注入了。关键的是在类里面声明属性,写set方法,然后在xml里面配置beanproperty的值。

 

方式二、构造器注入

构造器注入,顾名思义,就是在构造器里面注入依赖对象。那是怎么实现的呢?其实跟属性注入差不多,定义一个有参构造器,然后配置xml文件就行了。看代码:

 

package com.spring.demo03.entity;  

  

import com.spring.demo02.entity.Computer;  

  

public class Programmer {  

      

    private Computer computer;  

      

    public Programmer(Computer computer){  

        this.computer = computer;  

    }  

}

package com.spring.demo03.entity;  

  

public class Computer {  

  

    private String brand;  

    private String color;  

    private String size;  

  

    public Computer(String brand, String color, String size) {  

        this.brand = brand;  

        this.color = color;  

        this.size = size;  

    }  

}

 上面两个类都有一个有参的构造器,接下来,在xml里面配置这两个bean,然后再配置构造器的参数值就可以了

 

<?xml version="1.0" encoding="UTF-8"?>  

  

<beans xmlns="http://www.springframework.org/schema/beans"  

    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">  

      

  <bean id="programmer" class="com.spring.demo3.entity.Programmer">  

    <constructor-arg ref="computer"></constructor-arg>  

  </bean>  

    

  <!-- 构造器里面没有name字段,只有value,是根据构造器的方法参数顺序来定义的 -->  

  <bean id="computer" class="com.spring.demo3.entity.Computer">  

    <constructor-arg value="联想"></constructor-arg>  

    <constructor-arg value="红色"></constructor-arg>  

    <constructor-arg value="15.6"></constructor-arg>  

  </bean>  

    

</beans> 

方式三:自动装配

 

package com.spring.demo04.entity;  

  

import org.springframework.beans.factory.annotation.Autowired;  

import org.springframework.stereotype.Component;  

  

@Component  

public class Programmer {  

      

    @Autowired  

    Computer computer;  

  

}  

package com.spring.demo04.entity;  

  

import org.springframework.stereotype.Component;  

  

@Component  

public class Computer {  

    private String brand;  

    private String color;  

    private String size;

 

    public String getBrand() {  

        return brand;  

    }  

  

    public void setBrand(String brand) {  

        this.brand = brand;  

    }  

  

    public String getColor() {  

        return color;  

    }  

  

    public void setColor(String color) {  

        this.color = color;  

    }  

  

    public String getSize() {  

        return size;  

    }  

  

    public void setSize(String size) {  

        this.size = size;  

    }  

}

<?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/context   

    http://www.springframework.org/schema/context/spring-context-3.0.xsd   

    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">  

      

    <context:component-scan base-pakage="com.spring.demo04">  

    

</beans>

关键点:在类前面加注解:@Component,在需要注入的类里面加注解:@Autowired,这样xml里面的自动扫描就会扫描到这些加了注解的类和属性,在实例化bean的时候,Spring容器会把加了@Component的类实例化;在实际运行时,会给加了@Autowired的属性注入对应的实例。@Autowired方式是通过反射来设置属性值的,具体参考:https://blog.csdn.net/wenluoxicheng/article/details/73608657

 

 

范例:

 

如: 注入xml

 

<bean id="animal" class="phz.springframework.test.Cat">   

       <property name="name" value="kitty" />    </bean>

1public class Cat implements Animal {       

 

private String name;      

public void say() {      

System.out.println("I am " + name + "cat");   

 }    

 public void setName(String name) {         

this.name = name;     }  

 

 }  

 

2

 

public class Dog implements Animal {       

 

private String name;      

public void say() {      

System.out.println("I am " + name + "dog");   

 }    

 public void setName(String name) {         

 

this.name = name;     }  

 

}  

 

public interface Animal {   

 

  public void say();   

 

}  

 

通过获取容器注册的方法

 

ApplicationContext context = new FileSystemXmlApplicationContext("applicationContext.xml");    

 

      Animal animal = (Animal) context.getBean("animal");   //只要这里xml注入的animal变化,就可以控制不同的更改变化

 

      animal.say(); 

 

如果注入bean时,把name值也注入进入了,那这里的值就动态变化了。

 

<property name = "name" value = "haha"></property>  

 

其实DI就是IOC(控制反转)后,直接注入了其具体的数值

 

 

AOP

 

aspect oriented programming(面向切面编程)

核心:在不增加代码的基础上,还增加新功能

理解:面向切面是一个概念,通常用来为许多其他的类提供相同的服务,而且是固定的服务,是独立的。提升了代码的复用性,减少了代码的耦合度,减轻程序员的工作负担,把程序的重心放在了核心的逻辑上。

它是可以通过预编译方式和运行期动态代理实现在不修改源代码的情况下给程序动态统一添加功能的一种技术。

应用场景有日志记录,性能统计,安全控制,事务处理,异常处理等。

其实面向切面是,把一些公共的“东西”拿出来,比如说,事务,安全,日志,这些方面,如果你用的到,你就引入。也就是说:当你需要在执行一个操作(方法)之前想做一些事情(比如,开启事务,记录日志等等),那你就用before,如果想在操作之后做点事情(比如,关闭一些连接等等),那你就用after。其他类似。   

 

切入点: 前置通知,后置通知, 异常通知,最终通知,环绕通知 

 

切面: 利用一种称为"横切"的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其命名为"Aspect",即切面。所谓"切面",简单说就是那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块之间的耦合度,并有利于未来的可操作性和可维护性。

 

使用"横切"技术,AOP把软件系统分为两个部分:核心关注点和横切关注点。业务处理的主要流程是核心关注点,与之关系不大的部分是横切关注点。横切关注点的一个特点是,他们经常发生在核心关注点的多处,而各处基本相似,比如权限认证、日志、事物。AOP的作用在于分离系统中的各种关注点,将核心关注点和横切关注点分离开来。

 

public interface HelloWorld{ void printHelloWorld(); void doPrint();}

 

public class HelloWorldImpl1 implements HelloWorld{ public void printHelloWorld() { System.out.println("Enter HelloWorldImpl1.printHelloWorld()"); } public void doPrint() { System.out.println("Enter HelloWorldImpl1.doPrint()"); return ; }}

 

public class HelloWorldImpl2 implements HelloWorld{ public void printHelloWorld() { System.out.println("Enter HelloWorldImpl2.printHelloWorld()"); } public void doPrint() { System.out.println("Enter HelloWorldImpl2.doPrint()"); return ; }}

 

public class TimeHandler{ public void printTime() { System.out.println("CurrentTime = " + System.currentTimeMillis()); }}

 

<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:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd

 

http://www.springframework.org/schema/aop

 

http://www.springframework.org/schema/aop/spring-aop-4.2.xsd">

 

<bean id="helloWorldImpl1" class="com.xrq.aop.HelloWorldImpl1" />

 

<bean id="helloWorldImpl2" class="com.xrq.aop.HelloWorldImpl2" />

 

<bean id="timeHandler" class="com.xrq.aop.TimeHandler" />

 

<aop:config>

 

<aop:aspect id="time" ref="timeHandler">

 

<aop:pointcut id="addAllMethod" expression="execution(* com.xrq.aop.HelloWorld.*(..))" />

 

<aop:before method="printTime" pointcut-ref="addAllMethod" />

 

<aop:after method="printTime" pointcut-ref="addAllMethod" />

 

</aop:aspect>

 

</aop:config>

 

</beans>

 

结果调用:

 

ApplicationContext ctx = new ClassPathXmlApplicationContext("aop.xml");

 

HelloWorld hw1 = (HelloWorld)ctx.getBean("helloWorldImpl1");

 

HelloWorld hw2 = (HelloWorld)ctx.getBean("helloWorldImpl2");

 

hw1.printHelloWorld();

 

hw1.doPrint();

 

System.out.println();

 

hw2.printHelloWorld();

 

hw2.doPrint();

 

最后结果:

 

CurrentTime = 1446129611993Enter

 

HelloWorldImpl1.printHelloWorld()

 

CurrentTime = 1446129611993

 

 

 

CurrentTime = 1446129611994Enter

 

HelloWorldImpl1.doPrint()

 

CurrentTime = 1446129611994

 

 

 

CurrentTime = 1446129611994

 

Enter HelloWorldImpl2.printHelloWorld()

 

CurrentTime = 1446129611994

 

 

 

CurrentTime = 1446129611994

 

Enter HelloWorldImpl2.doPrint()

 

CurrentTime = 1446129611994

 

 

二、SpringMVC

  SpringMVC在项目中拦截用户请求,它的核心ServletDispatcherServlet承担中介或是前台这样的职责,将用户请求通过HandlerMapping去匹配ControllerController就是具体对应请求所执行的操作。SpringMVC相当于SSH框架中struts

 

1Spring MVC的运行流程

 

springMVC框架 

 

 

 

框架执行流程(面试必问) 

1、用户发送请求至前端控制器DispatcherServlet

2DispatcherServlet收到请求调用HandlerMapping处理器映射器。

3、处理器映射器根据请求url找到具体的处理器,生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet

4DispatcherServlet通过HandlerAdapter处理器适配器调用处理器

5、执行处理器(Controller,也叫后端控制器)

6Controller执行完成返回ModelAndView

7HandlerAdaptercontroller执行结果ModelAndView返回给DispatcherServlet

8DispatcherServletModelAndView传给ViewReslover视图解析器

9ViewReslover解析后返回具体View

10DispatcherServletView进行渲染视图(即将模型数据填充至视图中)。

11DispatcherServlet响应用户

 

2Spring MVC的原理

 

1、什么是SpringMVC

springmvcspring框架的一个模块,springmvcspring无需通过中间整合层进行整合。

springmvc是一个基于mvcweb框架。

 

 

 

 

 

mvc

 

mvcb/s系统 下的应用:

 

 

 

 

前端控制器DispatcherServlet(不需要程序员开发) 

作用接收请求,响应结果,相当于转发器,中央处理器。有了DispatcherServlet减少了其它组件之间的耦合度。

处理器映射器HandlerMapping(不需要程序员开发

作用:根据请求的url查找Handler

处理器适配器HandlerAdapter 

作用:按照特定规则(HandlerAdapter要求的规则)去执行Handler

处理器Handler (需要程序员开发

注意:编写Handler时按照HandlerAdapter的要求去做,这样适配器才可以去正确执行Handler

视图解析器View resolver(不需要程序员开发

作用:进行视图解析,根据逻辑视图名解析成真正的视图(view

视图View (需要程序员开发

View是一个接口,实现类支持不同的View类型(jspfreemarkerpdf…)

 

 

 

struts2springMVC的区别?

 

1Struts2是类级别的拦截,一个类对应一个request 上下文, SpringMVC是方法级别的拦截,一个方法对应一个request上下文,而方法同时又跟一个url对应,,所以说从架构本身上SpringMVC就容易实现restful url,struts2的架构实现起来要费劲,因为Struts2Action的一个方法可以对应一个url ,而其类属性却被所有方法共享,这也就无法用注解或其他方式标识其所属方法了。

 

2、由上边原因, SpringMVC的方法之间基本上独立的,独享request response数据,请求数据通过参数获取,处理结果通过ModelMap交回给框架,方法之间不共享变量,Struts2搞的就比较乱,虽然方法之间也是独立的,但其所有Action变量是共享的,这不会影响程序运行,却给我们编码读程序时带来麻烦,每次来了请求就创建一个Action ,一个Action对象对应一个request 上下文。

 

3、由于Struts2需要针对每个request进行封装,request , sessionservlet生命周期的变量封装成一个一 个Map ,供给每个Action使用,并保证线程安全,所以在原则上,是比较耗费内存的。

 

4、拦截器实现机制上, Struts2有以自己的interceptor机制, SpringMVC用的是独立的AOP方式,这样导致Struts2的配置文件量还是比SpringMVC大。

 

5SpringMVC的入口是servlet ,Struts2filter (这里要指出, filterservlet是不同的。以前认为filterservlet的一种特殊),这就导致 了二者的机制不同,这里就牵涉到servletfilter的区别了。

 

6SpringMVC集成了Ajax ,使用非常方便,只需一个注解@ResponseBody就可以实现,然后直接返回响应文本即可,Struts2拦截器集成了Ajax ,Action中处理时一般必须安装插件或者自己写代码集成进去,使用起来也相对不方便。

 

7SpringMVC验证支持JSR303 ,处理起来相对更加灵活方便,Struts2验证比较繁琐,感觉太烦乱。

 

8Spring MVCSpring是无缝的。从这个项目的管理和安全上也比Struts2(当然Struts2也可以通过不同的目录结构和相关配置做到SpringMVC-样的效果,但是需要xml配置的地方不少)

 

9、设计思想上, Struts2更加符合0OP的编程思想,SpringMVC就比较谨慎,servlet上扩展。

 

10SpringMVC开发效率和性能高于Struts2

 

11SpringMVC可以认为已经100%零配置。

 

 

 

3Spring MVC的核心技术

 

 

注解开发(@Controller,@RequestMapping,@ResponseBody。。。。) 

还有Spring的诸多注解,这两者是不需要整合的~

传参,接参(request

基本配置

文件上传与下载 

Spring MVC中文件上传需要添加Apache Commons FileUpload相关的jar,

基于该jar, Spring中提供了MultipartResolver实现类: CommonsMultipartResolver.

拦截器

其实最核心的还是SpringMVC的执行流程,各个点的作用得搞清楚。

 

 三、Mybatis部分

 

1Mybatis的运行流程

 

Mybatis运行流程图:

 

 

 

 

 

第一步:配置文件mybatis.xml,大体如下,

 

 

 

 

 

第二步:加载我们的xml文件 

第三步:创建SqlSessionFactoryBuilder 

第四步:创建SqlSessionFactory 

第五步:调用openSession(),开启sqlSession 

第六步:getMapper()来获取我们的mapper(接口),mapper对应的映射文件,在加载mybatis.xml时就会加载 

第七步:使用我们自己的mapper和它对应的xml来完成我们和数据库交互。即增删改查。 

第八步:提交session,关闭session

 

代码如下:

 

 

 

 

需要注意的是,sqlSession也自带一些数据交互的操作

 

三、mybatis

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

页面发送请求给控制器,控制器调用业务层处理逻辑,逻辑层向持久层发送请求,持久层与数据库交互,后将结果返回给业务层,业务层将处理逻辑发送给控制器,控制器再调用视图展现数据。

 

Mybatis输入映射

 

通过parameterType指定输入参数的类型,类型可以是简单类型、hashmappojo的包装类型

Mybatis输出映射

 

一、resultType

 

作用:将查询结果按照sql列名pojo属性名一致性映射到pojo中。

使用resultType进行输出映射,只有查询出来的列名和pojo中的属性名一致,该列才可以映射成功。

如果查询出来的列名和pojo中的属性名全部不一致,则不会创建pojo对象。

只要查询出来的列名和pojo中的属性有一个一致,就会创建pojo对象

 

如果查询出来的列名和pojo的属性名不一致,通过定义一个resultMap对列名和pojo属性名之间作一个映射关系。

 

二、resultMap

 

使用associationcollection完成一对一和一对多高级映射(对结果有特殊的映射要求)。

association 

作用:将关联查询信息映射到一个pojo对象中。

场合:为了方便查询关联信息可以使用association将关联订单信息映射为用户对象的pojo属性中,比如:查询订单及关联用户信息。

使用resultType无法将查询结果映射到pojo对象的pojo属性中,根据对结果集查询遍历的需要选择使用resultType还是resultMap

collection 

作用:将关联查询信息映射到一个list集合中。

场合:为了方便查询遍历关联信息可以使用collection将关联信息映射到list集合中,比如:查询用户权限范围模块及模块下的菜单,可使用collection将模块映射到模块list中,将菜单列表映射到模块对象的菜单list属性中,这样的作的目的也是方便对查询结果集进行遍历查询。如果使用resultType无法将查询结果映射到list集合中。

Mybatis的动态sql

 

什么是动态sql 

mybatis核心 对sql语句进行灵活操作,通过表达式进行判断,对sql进行灵活拼接、组装。

包括, where ifforeachchoosewhenotherwisesettrim等标签的使用

数据模型分析思路

 

1、每张表记录的数据内容 

分模块对每张表记录的内容进行熟悉,相当 于你学习系统 需求(功能)的过程

2、每张表重要的字段设置 

非空字段、外键字段

3、数据库级别表与表之间的关系 

外键关系

4、表与表之间的业务关系 

在分析表与表之间的业务关系时一定要建立 [Math Processing Error]在某个业务意义基础上去分析。

 

4, SpringMVC + Mybatis

 

 

 

四、SSM整合思路

 

 

 

 

 

   ①、表现层,也就是 Controller,由 SpringMVC 来控制,而SpringMVC 是Spring 的一个模块,故不需要整合。

 

  ②、业务层,也就是 service,通常由 Spring 来管理 service 接口,我们会使用 xml 配置的方式来将 service 接口配置到 spring 配置文件中。而且事务控制一般也是在 service 层进行配置。

 

  ③、持久层,也就是 dao 层,而且包括实体类,由 MyBatis 来管理,通过 spring 来管理 mapper 接口,使用mapper的扫描器自动扫描mapper接口在spring中进行注册。

 

  很明显,spring 在三大框架的整合中占据至关重要的地位,类似于一个大管家,将 MyBatis 和 SpringMVC 揉合在一起。

 

2、准备环境

  ①、数据库环境

 

    数据库类型:MySQL 5.1

 

    数据库名称:ssm

 

    数据表:user

 

 

 

 

、开发工具 eclipse

  JDK 1.7

  mybatis 3.3

  SpringMVC 4.2.4

  Spring 4.2.4

  、数据库连接池 dbcp1.2.2

  、数据库驱动包mysql5.1.26

  、日志 log4j 1.2

 

  案例需求:输入用户名和密码进行登录验证

  具体的 jar 下载见上面的源码下载链接!

   项目的目录结构为:

 

 

 

3、整合 Dao

   也就是整合 MyBatis Spring

  、在 db.properties 文件中,保存数据库连接的基本信息

1

2

3

4

5

6

#db.properties

dataSource=org.apache.commons.dbcp.BasicDataSource

driver=com.mysql.jdbc.Driver

url=jdbc:mysql://localhost:3306/ssm

username=root

password=root

  分别是数据库连接池数据源,数据库连接驱动,数据库连接URL,数据库连接用户名,数据库连接密码

  mybatis全局配置文件 mybatis-configuration.xml

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

<?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>

    <!-- 全局 setting 配置,根据需要添加  -->

    <!--开启二级缓存  -->

    <settings>

        <setting name="cacheEnabled" value="true"/>

    </settings>

     

    <!-- 配置别名 -->

    <typeAliases>

        <!-- 批量扫描别名 -->

        <package name="com.ys.po"/>

    </typeAliases>

     

    <!-- 配置mapper,由于使用 spring 和mybatis 的整合包进行 mapper 扫描,这里不需要配置了

        必须遵循:mapper.xml 和 mapper.java 文件同名且在同一个目录下

     -->

     <!-- <mappers>

     </mappers> -->

     

</configuration>

  通过 mapper 接口来加载映射文件,具体可以看这篇博客:http://www.cnblogs.com/ysocean/p/7301548.html,必须满足下面四点:

  1xxxMapper 接口必须要和 xxxMapper.xml 文件同名且在同一个包下,也就是说 UserMapper.xml 文件中的namespaceUserMapper接口的全类名

  2xxxMapper接口中的方法名和 xxxMapper.xml 文件中定义的 id 一致

  3xxxMapper接口输入参数类型要和 xxxMapper.xml 中定义的 parameterType 一致

  4xxxMapper接口返回数据类型要和 xxxMapper.xml 中定义的 resultType 一致 

 

  、配置 Spring 文件

   我们需要配置数据源、SqlSessionFactory以及mapper扫描器,由于这是对 Dao 层的整合,后面还有对于 业务层,表现层等的整合,为了使条目更加清新,我们新建 config/spring 文件夹,这里将配置文件取名为 spring-dao.xml 放入其中。

  spring-dao.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

<?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:mvc="http://www.springframework.org/schema/mvc"

  xmlns:context="http://www.springframework.org/schema/context"

  xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"

  xsi:schemaLocation="http://www.springframework.org/schema/beans

    http://www.springframework.org/schema/beans/spring-beans-3.2.xsd

    http://www.springframework.org/schema/mvc

    http://www.springframework.org/schema/mvc/spring-mvc-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/aop

    http://www.springframework.org/schema/aop/spring-aop-3.2.xsd

    http://www.springframework.org/schema/tx

    http://www.springframework.org/schema/tx/spring-tx-3.2.xsd">

 

    <!--第一步: 配置数据源 -->

    <!-- 加载db.properties文件中的内容,db.properties文件中的key名要有一定的特殊性 -->

    <context:property-placeholder location="classpath:db.properties" />

    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">

        <property name="driverClassName" value="${jdbc.driver}"></property>

        <property name="url" value="${jdbc.url}"></property>

        <property name="username" value="${jdbc.username}"></property>

        <property name="password" value="${jdbc.password}"></property>

        <property name="maxActive" value="30"></property>

        <property name="maxIdle" value="5"></property>

    </bean>

     

    <!-- 第二步:创建sqlSessionFactory。生产sqlSession  -->

    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">

        <!-- 数据库连接池 -->

        <property name="dataSource" ref="dataSource"></property>

        <!-- 加载mybatis全局配置文件,注意这个文件的目录 -->

        <property name="configLocation" value="classpath:mybatis/mybatis-configuration.xml"></property>

    </bean>

     

    <!-- 第三步:配置 mapper 扫描器

        * 接口类名和映射文件必须同名

        * 接口类和映射文件必须在同一个目录下

        * 映射文件namespace名字必须是接口的全类路径名

        * 接口的方法名必须和映射Statement的id一致

    -->

    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">

        <!-- 扫描的包路径,如果需要扫描多个包,中间使用逗号分隔 -->

        <property name="basePackage" value="com.ys.mapper"></property>

        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>

    </bean>

     

</beans>

  、根据逆向工程生成 po 类以及 mapper 文件

  如何使用逆向工程,可以参考这篇博客:http://www.cnblogs.com/ysocean/p/7360409.html,我们逆向工程要是一个额外的工程,生成我们所需的po类以及mapper文件后,在将其复制到我们当前项目中,如下:

 

 由于我们这里是进行登录验证,所以在 UserMapper.java 中添加如下代码:

1

2

3

4

5

6

7

8

9

10

11

12

package com.ys.mapper;

 

import com.ys.po.User;

import java.util.List;

import org.apache.ibatis.annotations.Param;

 

public interface UserMapper {

 

    //通过用户名和密码查询User

    User selectUserByUsernameAndPassword(User user);

 

}

  UserMapper.xml 

1

2

3

4

<!-- 通过用户名和密码查询User -->

  <select id="selectUserByUsernameAndPassword" resultType="com.ys.po.User" parameterType="com.ys.po.User">

    select * from user where username = #{username,jdbcType=VARCHAR} and password = #{password,jdbcType=VARCHAR}

  </select>

  

 

   dao 层整合完毕之后,我们进行一个测试,要养成每做完一个小模块必须测试的习惯。步步为营,如果整个项目配置完了然后在进行测试,那么有问题进行排除会变得很困难。

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

package com.ys.test;

 

import org.junit.Before;

import org.junit.Test;

import org.springframework.context.ApplicationContext;

import org.springframework.context.support.ClassPathXmlApplicationContext;

 

import com.ys.mapper.UserMapper;

import com.ys.po.User;

 

 

public class DaoTest {

    ApplicationContext context = null;

     

    @Before

    public void init(){

        context = new ClassPathXmlApplicationContext("classpath:spring/application-dao.xml");

    }

     

    @Test

    public void testSelectByPrimaryKey(){

        UserMapper userMapper = (UserMapper) context.getBean("userMapper");

        User user = userMapper.selectByPrimaryKey(1);

        System.out.println(user.getPassword());

    }

     

}

  这里是根据 user 表的 id 进行查询。如果能打印出user对象的值,那么前面的配置是 OK的。

 

 

4、整合 service

  前面我们整理了,这层就是用 Spring 来管理 service 接口,我们会使用 xml 配置的方式来将 service 接口配置到 spring 配置文件中。而且事务控制也是在 service 层进行配置。

  这里我们以登录

  、定义 service 接口

1

2

3

4

5

6

7

8

9

10

package com.ys.service.impl;

 

import com.ys.po.User;

 

public interface IUserService {

     

    //通过用户名和密码查询User

    public User selectUserByUsernameAndPassword(User user);

 

}

  、编写 service 实现类

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

package com.ys.service;

 

import org.springframework.beans.factory.annotation.Autowired;

 

import com.ys.mapper.UserMapper;

import com.ys.po.User;

import com.ys.service.impl.IUserService;

 

public class UserServiceImpl implements IUserService{

 

    @Autowired

    private UserMapper userMapper; //通过@Autowired向spring容器注入UserMapper

     

    //通过用户名和密码查询User

    @Override

    public User selectUserByUsernameAndPassword(User user) {

        User u = userMapper.selectUserByUsernameAndPassword(user);

        return u;

    }

 

}

  通过@Autowiredspring容器注入UserMapper,它会通过spring配的扫描器扫描到,并将对象装载到spring容器中。

  

  、在spring容器中配置 Service 接口,这里我们使用 xml 的方式

   config/spring 目录下,新建 spring-service.xml

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

<?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:mvc="http://www.springframework.org/schema/mvc"

  xmlns:context="http://www.springframework.org/schema/context"

  xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"

  xsi:schemaLocation="http://www.springframework.org/schema/beans

    http://www.springframework.org/schema/beans/spring-beans-3.2.xsd

    http://www.springframework.org/schema/mvc

    http://www.springframework.org/schema/mvc/spring-mvc-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/aop

    http://www.springframework.org/schema/aop/spring-aop-3.2.xsd

    http://www.springframework.org/schema/tx

    http://www.springframework.org/schema/tx/spring-tx-3.2.xsd">

 

    <!--配置UserServiceImpl -->

    <bean id="userService" class="com.ys.service.UserServiceImpl"></bean>

     

</beans>

  

  

  、在spring容器中配置 事务处理

  在 config/spring 目录下,新建 spring-transaction.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

<?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:mvc="http://www.springframework.org/schema/mvc"

  xmlns:context="http://www.springframework.org/schema/context"

  xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"

  xsi:schemaLocation="http://www.springframework.org/schema/beans

    http://www.springframework.org/schema/beans/spring-beans-3.2.xsd

    http://www.springframework.org/schema/mvc

    http://www.springframework.org/schema/mvc/spring-mvc-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/aop

    http://www.springframework.org/schema/aop/spring-aop-3.2.xsd

    http://www.springframework.org/schema/tx

    http://www.springframework.org/schema/tx/spring-tx-3.2.xsd">

 

    <!-- 事务管理器 -->

    <!-- 对mybatis操作数据事务控制,spring使用jdbc的事务控制类 -->

    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">

         <!-- 数据源dataSource在spring-dao.xml中配置了 -->

         <property name="dataSource" ref="dataSource"/>

    </bean>

 

    <!-- 通知 -->

    <tx:advice id="txAdvice" transaction-manager="transactionManager">

         <tx:attributes>

             <tx:method name="save*" propagation="REQUIRED"/>

             <tx:method name="delete*" propagation="REQUIRED"/>

             <tx:method name="update*" propagation="REQUIRED"/>

             <tx:method name="insert*" propagation="REQUIRED"/>

             <tx:method name="find*" propagation="SUPPORTS" read-only="true"/>

             <tx:method name="get*" propagation="SUPPORTS" read-only="true"/>

             <tx:method name="select*" propagation="SUPPORTS" read-only="true"/>

         </tx:attributes>

    </tx:advice>

     

    <aop:config>

         <!-- com.ys.service.impl包里面的所有类,所有方法,任何参数 -->

         <aop:advisor advice-ref="txAdvice" pointcut="execution(* com.ys.service.impl.*.*(..))"/>

    </aop:config>    

</beans>

 

 

4、整合 SpringMVC

  、配置前端控制器

  在 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

<?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" id="WebApp_ID" version="3.0">

  <display-name>SpringMVC_01</display-name>

  <!-- 配置前端控制器DispatcherServlet -->

  <servlet>

    <servlet-name>springmvc</servlet-name>

    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

    <!--springmvc.xml 是自己创建的SpringMVC全局配置文件,用contextConfigLocation作为参数名来加载

        如果不配置 contextConfigLocation,那么默认加载的是/WEB-INF/servlet名称-servlet.xml,在这里也就是 springmvc-servlet.xml

      -->

    <init-param>

        <param-name>contextConfigLocation</param-name>

        <param-value>classpath:spirng/springmvc.xml</param-value>

    </init-param>

  </servlet>

 

  <servlet-mapping>

    <servlet-name>springmvc</servlet-name>

    <!--第一种配置:*.do,还可以写*.action等等,表示以.do结尾的或者以.action结尾的URL都由前端控制器DispatcherServlet来解析

        第二种配置:/,所有访问的 URL 都由DispatcherServlet来解析,但是这里最好配置静态文件不由DispatcherServlet来解析

        错误配置:/*,注意这里是不能这样配置的,应为如果这样写,最后转发到 jsp 页面的时候,仍然会由DispatcherServlet进行解析,

                    而这时候会找不到对应的Handler,从而报错!!!

      -->

    <url-pattern>/</url-pattern>

  </servlet-mapping>

</web-app>

  

  、配置处理器映射器、处理器适配器、视图解析器

  在 config/spring 目录下新建 springmvc.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

<?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:mvc="http://www.springframework.org/schema/mvc"

       xmlns:context="http://www.springframework.org/schema/context"

       xmlns:aop="http://www.springframework.org/schema/aop"

       xmlns:tx="http://www.springframework.org/schema/tx"

       xsi:schemaLocation="http://www.springframework.org/schema/beans

        http://www.springframework.org/schema/beans/spring-beans-4.2.xsd

        http://www.springframework.org/schema/mvc

        http://www.springframework.org/schema/mvc/spring-mvc-4.2.xsd

        http://www.springframework.org/schema/context

        http://www.springframework.org/schema/context/spring-context.xsd

        http://www.springframework.org/schema/aop

        http://www.springframework.org/schema/aop/spring-aop-4.2.xsd

        http://www.springframework.org/schema/tx

        http://www.springframework.org/schema/tx/spring-tx.xsd">

 

    <!--使用mvc:annotation-driven可以代替上面的映射器和适配器

        这里面会默认加载很多参数绑定方法,比如json转换解析器就默认加载,所以优先使用下面的配置

      -->

    <mvc:annotation-driven></mvc:annotation-driven>

 

     

    <!--批量配置Handler,指定扫描的包全称  -->

    <context:component-scan base-package="com.ys.controller"></context:component-scan>

     

 

    <!--配置视图解析器  -->

    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">

         

    </bean>

</beans>

  

  

  、编写 Handler,也就是 Controller

  在 com.ys.controller 包下新建 UserController.java 文件

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

package com.ys.controller;

 

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Controller;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.servlet.ModelAndView;

 

import com.ys.po.User;

import com.ys.service.impl.IUserService;

 

@Controller

public class UserController {

    @Autowired

    public IUserService userService;

     

    @RequestMapping("/login")

    public ModelAndView login(User user){

        ModelAndView mv = new ModelAndView();

        User u = userService.selectUserByUsernameAndPassword(user);

        //根据用户名和密码查询user,如果存在,则跳转到 success.jsp 页面

        if(u != null){

            mv.addObject("username", u.getUsername());

            mv.addObject("user", u);

            mv.setViewName("view/success.jsp");

        }else{

            //如果不存在,则跳转到 login.jsp页面重新登录

            return new ModelAndView("redirect:/login.jsp");

        }

        return mv;

    }

 

}

  

  、加载 Spring 容器

  我们在 classpath/spring 目录下新建了 spring-dao.xml,spring-service.xml,spring-transaction.xml 这些文件,里面有我们配置的 mappercontrollerservice,那么如何将这些加载到 spring 容器中呢?

  在 web.xml 文件中添加如下代码:

1

2

3

4

5

6

7

8

<!-- 加载spring容器 -->

<context-param>

   <param-name>contextConfigLocation</param-name>

   <param-value>classpath:spring/spring-*.xml</param-value>

</context-param>

<listener>

   <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>

</listener>

  由于配置文件比较多,我们使用通配符加载的方式。注意:这段代码最好要加在前端控制器的前面。

  至此 SSM 三大框架整合就完成了,接下来我们进行测试。

  

5、测试

  在 WebContent 目录下创建 login.jsp 页面,以及 success.jsp页面,如下图:

 

  login.jsp

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

<%@ 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>

    <form action="login" method="post">

        <label>账号:</label>

        <input type="text" id="txtUsername" name="username" placeholder="请输入账号" /><br/>

        <label>密码:</label>

        <input type="password" id="txtPassword" name="password" placeholder="请输入密码" /><br/>

        <input type="submit" value="提交" />

        <input type="reset" value="重置" />

    </form>

</body>

</html>

  success.jsp

1

2

3

4

5

6

7

8

9

10

11

12

<%@ 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>

    Hello ${user.username}

</body>

</html>

  1、将项目发布到 tomcat,如何发布可以参考这篇博客:http://www.cnblogs.com/ysocean/p/6893446.html

  2、在浏览器输入:http://localhost:8080/SSMDemo/login.jsp

 

点击提交:

 

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!