SSM(spring-springmvc-mybatis)学习笔记(完结)

视频链接2020版SSM框架全套在线教程-spring-springmvc-mybatis实战入门/一站搞定三大热门框架_哔哩哔哩_bilibili

Mybatis篇

第一章 框架概述

三层架构
MVC:web开发中,使用mvc架构模式。m:数据,V:视图,C:控制器
    C控制器:接收请求,调用service对象,显示请求的处理结果,当前使用servlet作为控制器
    V视图:现在使用jsp,html,css,js。显示请求处理的结果,把M中的数据显示出来
    M数据:来自数据库mysql,来自文件,来自网络
mvc作用:
    [1]实现解耦合。
    [2]让mvc各负其职。
    [3]使系统扩展更好,更容易维护。

三层架构:
1、界面层(视图层):接收用户的请求,调用service,显示请求的处理结果的。包含了jsp,html,servlet等对象。
2、业务逻辑层:处理业务逻辑,使用算法处理数据的。把数据返回给界面层。对应的是service包。
3、持久层(数据库访问层):访问数据库,或者读取文件,访问网络,获取数据。对应的包是Dao

三层架构请求处理流程
用户发起请求----->界面层------>业务层逻辑层------->持久层----->数据库(mysql)

三层架构模式和框架
每一层对应着一个框架
(1)界面层-----SpringMVC框架
(2)业务层-----Spring
(3)持久层-----MyBatis框架

框架
(1)什么是框架[framework]
框架:就是一个软件,完成了部分的功能。软件中的类和类之间的方法调用都已经规定好了
通过这些可以完成某些功能,框架看作是模板。
框架是可以升级的,改造的。框架是安全的。
框架是对某一方面有用的,不是全能的。

Mybatis框架
mybatis可以操作数据库,对数据执行增删改查,看作是高级的jdbc。解决jdbc的缺点
mybatis能做什么
[1]注册驱动
[2]创建jdbc中使用的Connection,Statement,ResultSet
[3]执行sql语句,得到ResultSet
[4]处理ResultSet,把记录集中的数据转为Java对象,同时还能把Java对象放入到List集合
[5]关闭资源
[6]实现sql语句和Java代码的解耦合
学习链接:https://mybatis.org/mybatis-3/zh/getting-started.html
下载链接:https://github.com/mybatis/mybatis-3

第二章mybatis入门

[1]创建student表(id,name,email,age)
[2]新建maven项目
[3]修改pom.xml
   1、加入依赖Mybatis依赖,MySQL驱动,junit
   2、在加入资源插件
[4]创建实体类Student。定义属性,属性名和列名保持一致
[5]创建Dao接口,定义操作数据库的方法
[6]创建xml文件(mapper文件),写sql语句
    mybatis框架推荐是把sql语句和Java代码分开
    mapper文件:定义和Dao接口在同一目录,一个表一个mapper文件
[7]创建mybatis的主配置文件(xml文件):有一个,放在resources文件下
    1、定义创建连接实例的数据源(DataSource)对象
    2、指定其他mapper文件的位置
[8]创建测试内容
    使用main方法,测试mybatis访问数据库
    也可以使用junit访问数据库


        select id,name,email,age from student where email=#{studentEmail}
    

@Param:命名参数,在方法的形参前面使用的,定义参数名。这个名称可以在mapper文件中。
    List selectByNameOrAge(@Param(value = "myname") String name, @Param(value = "myage") Integer age);
        多个简单类型的参数
        当使用了@Param命名后,例如@Param("myname")
        在mapper中,使用#{命名的参数},例如#{myname}
    

Dao接口中多个简单类型的参数,使用位置
参数位置:dao接口中方法的形参列表,从左往右,参数位置是0,1,2,3......
语法格式:#{arg0},#{arg1},#{arg2}
Dao接口方法
    List selectByPosition(String name, Integer age);
Mapper
    

Dao接口参数是一个Map
Dao接口方法
    List selectStudentByMap(Map map);
Mapper
    


#和$的区别
#占位符
语法:#{字符}
mybatis处理#{}使用jdbc对象是PrepareStatement对象
    
mybatis创建PrepareStatement对象,执行sql语句
String sql="select * from student where name=? or age=?"
PrepareStatement pst=con.prepreStatement(sql);
pst.setString(1,"春哥");
pst.setInt(2,21);
ResultSet rs=pst.executeQuery();

#{}特点:
1、使用的PrepareStament对象,执行sql语句,效率高
2、使用的PrepareStament对象,能避免sql语句,sql语句执行更安全
3、#{}常常作为列值使用,位于等号的右侧

$占位符
语法:${字符}
mybatis执行${}占位符的sql语句
    
${}表示字符串连接,把sql语句的其他内容和${}内容使用 字符串 连接的方式连在一起
String sql="select * from student where id="+"10001";
mybatis创建Statement对象,执行sql语句
Statement stmt=con.con.createStatement(sql);
ResultSet rs=stmt.executeQuery();
${}的特点
1、使用Statement对象,执行sql语句,效率低
2、${}占位符的值,使用的字符串连接方式,有sql注入的风险.有代码安全的问题
3、${}数据是原样使用的,不会区分数据类型
4、${}常用作表名或者列名,在能保证数据安全的情况下使用${}

封装输出结果
resultType:执行sql得到ResultSet转换的类型,使用类型的完全限定名或别名
注意如果返回的是集合,那应该设置为集合包含的类型,而不是集合本身。ResultType和ResultMap,不能同时使用
mybatis:执行sql语句,得到ResultSet,转化为Java对象

resultType:在执行select时使用,作为
        select * from student where id=#{studentId}
    
resultType:使用的是Java类型的全限定名称,表示的意思mybatis执行sql,把ResultSet中的数据转为
Student类型的对象.mybatis会做一下操作:
    1、调用Morries_Wu.Bean.Student的无参构造方法,创建对象
    Student student=new Student();使用反射创建调用对象
    2、同名的列赋值
    student.setId(rs.getInt("id"));
    student.setString(rs.geString("name"));
    3、得到Java对象,如果Dao接口返回的值是List集合,mybatis把student对象放入到List集合

所以执行Student mystudent=dao.selectById(1001);得到数据库中id=1001这行数据
这行数据的列值,付给了mystudent对象的属性,你能得到mystudent对象,就相当于是id=1001这行数据

自定义别名
mybatis提供给Java类型定义简短,好记名称
自定义别名的步骤
[1]、第一种方式
        1、在mybatis主配置文件,使用typeAliase标签声明别名
        
           
        
        2、在mapper文件中,resultType="别名"
        
[2]、第二种方式
name:包名,mybatis会把这个包中所有类名作为别名

resultType:表示mybatis执行sql后得到Java对象类型
           规则同名列赋值给同名属性

resultType:表示简单类型
dao方法
    int countStudent();
mapper文件
    

resultType:表示一个map结构的时候,执行sql得到一个Map结构数据,mybatis执行sql,把resultSet转化为Map
           sql执行结果,列名做map的key,列值,作为value
           sql执行得到是一行记录,转为map结构是正确的。
           dao接口返回的是一个map,sql语句最多能获取一行记录,多于一行是错误

resultMap:结果映射,自定义列名和Java对象属性的对应关系。常用在列名和属性名不同的情况
用法
1、先定义resultMap标签,指定列名和属性名称对应关系
2、在select标签使用resultMap属性,指定上面定义的resultMap的id值
    使用resultMap属性,指定映射关系的id
    resultMap和resultType,不能同时使用,二选一
定义resultMap
        id:给resultMap的映射关系起个名称,唯一值
        type:Java类型的全限定名称
        
                
                
                
                
                
                
        
        mapper
        


列名和Java对象属性名称不一样解决方式
使用resultMap:自定义和属性名称对应关系
使用resultType:使用列的别名,让别名和Java对象属性名称一样

Like
1、第一种方式:在Java程序中,把like的内容组装好,把这个内容传入到sql语句
    mapper:
    
    Test:
    String name = "%李%";
2、第二种方式:在sql语句,组织like的内容
sql语句like的格式:where name like %""空格#{name}空格"%"
    mapper:
    
    Test:
    String name="李";

第四章动态sql

什么是动态sql:同一个dao的方法,根据不同的条件可以表示不同的sql语句,主要是where部分有变化
使用mybatis提供的标签,实现动态sql的能力,主要讲if,where,foreach,sql
使用动态sql的时候,dao方法的形参使用Java对象

if标签
语法:

    sql代码

在mapper文件中
        

在mapper的动态sql中若出现比较符号最好将其转换为实体符号
否则XML会出现解析出错问题
<       <
>       >
>=      >=
<=      <=

where标签
使用if标签时,容易引起sql语句语法错误,使用where标签解决if产生的语法问题
使用时where,里面是一个或多个if标签,当有一个if标签判断为true,where标签
会转为WHERE关键字附加到sql语句的后面,如果if没有一个条件为true
忽略where和里面的if
语法:

    sql语句1
    sql语句2


where标签删除和它最近的or获取and
    


mybatis-foreach循环
使用foreach可以循环数组,list集合,一般使用在in语句中
语法:

            #{item的值}


标签属性:
collection:表示,循环的对象是数组,还是list集合
        1、如果dao接口方法的形参是数组
        collection="array"
        2、如果dao接口形参是List
        collection="list"
open:循环开始时的字符。sql.append("(");
close:循环结束时的字符。sql.close(")");
item:集合成员,自定义的变量。Integer item=idlist.get(i); item是集合成员
separator:集合成员之间的分隔符。sql.append(","); 集合之间的分隔符
#{item的值}:获取集合成员的值


1、foreach第一种方式,循环简单类型的list-->
        dao接口:
        List selectForeachOne(List IdList);
        mapper:
        

2、foreach第二种方式,循环List
            dao接口:
            List selectForeachOne(List IdList);
            mapper:
            

sql标签
sql标签标示一段sql代码,可以是表名,几个字段,where条件都可以,可以在其他地方复用sql标签的内容
使用方式:
1、在mapper文件中定义sql代码片段 部分sql语句
2、在其他的位置,使用include标签引用某个代码片段
定义代码片段
    select * from student
      

第五章Mybatis配置文件

mybatis配置文件有两大类:
1、mybatis主配置文件
    提供mybatis全局设置的,包含的内容日志,数据源,mapper文件位置
2、mybatis的mapper文件
    写sql语句的,一个表一个mapper文件

settings部分
settings是mybatis的全局设置,影响整个mybatis的运行,这个设置一般使用默认值就可以了
typeAliase别名
environment:环境标签,在他里面可以配置多个environment,可以表示一个数据库的连接信息
       属性:
       1、id自定义的环境的标识。唯一值
       2、default,必须是某个environment的id属性值
transactionManager:事务管理器
       属性:type表示事务管理器的类型
       属性值:
       1、jdbc:使用Connection对象,由mybatis自己完成事务的处理
       2、MANAGED:管理,表示把事务的处理交给容器实现(由其他软件完成事务的提交,回滚)
dataSource:数据源,创建的Connection对象,连接数据库
       属性:type数据源的类型
       属性值:
       1、POOLED,mybatis会在内存中创建PooleDatSource类,管理多个Connection连接对象使用连接池
       2、UNPOOLED,不使用连接池,mybatis创建一个UnPooleDataSource这个类
       每次执行sql语句先创建Connection对象再执行sql语句,最后关闭连接
       3、JNDI:Java的命名和目录服务

使用数据库属性配置文件
需要把数据库的配置信息收到一个单独文件中,独立管理。这个文件扩展名properties
使用自定义的key=value的格式表示数据
使用步骤:
1、在resources目录中,创建xxx.properties
2、在文件中,使用key=value的格式定义数据
例如jdbc.url=jdbc:mysql://localhost:3306/srpingdb
3、在mybatis主配置文件,使用标签引用外部的属性配置文件
4、在使用的位置,使用${key}获取key的对应value(等号右侧的值)

mapper标签使用格式有两种常用的方式:
            第一种方式,resource="mapper文件路径"
            优点:文件清晰,加载文件是明确的,文件的位置比较灵活
            缺点:文件比较多,代码量会比较大,管理难度大
        
            第二种方式,使用
            name:包名,mapper文件所在的包名
            特点:把这个包中所有mapper文件,一次加载。
            使用要求:
            1、mapper文件和dao接口在同一目录
            2、mapper文件和dao接口名称完全一致
        

 pom.xml工程maven配置文件




  4.0.0

  Morries_Wu
  Mybatis
  1.0-SNAPSHOT

  Mybatis
  
  http://www.example.com

  
    UTF-8
    1.8
    1.8
  

  
  

    
    
      org.mybatis
      mybatis
      3.5.1
    

    
    
      mysql
      mysql-connector-java
      5.1.9
    

    
    
      junit
      junit
      4.12
      test
    

    
      com.github.pagehelper
      pagehelper
      5.1.10
    

  

  
    
      
        src/main/java
        
          
          **/*.properties
          **/*.xml
        
        
        false
      
    
  


主配置文件mybatis.xml




    
    

    
    
        
    

    
    
    
        
    


    
        
    

    
        
            
            
            
                
                
                
                
                
                
            
        
    
    
    
        
        
        
        
    

Dao.xml配置文件




    

    
    select * from student

    id,name,email


    
    
    
        
        
        
        
        
        
    

    
    

    
    


    
    

    
    

    
    

    
    

    
    

    
    

    






Dao接口类文件

package Morries_Wu.Dao;


import Morries_Wu.Bean.Custom;
import Morries_Wu.Bean.Student;
import org.apache.ibatis.annotations.Param;

import java.util.List;

public interface StudentDao02 {

    Custom selectById(@Param("stuid") Integer id);

    //like第一种方式
    List selectLikeOne(@Param("name") String name);

    //like第二种方式
    List selectLikeTwo(@Param("name") String name);

    //if
    List selectIf(Student student);

    //where
    List selectWhere(Student student);

    //foreach-1
    List selectForeachOne(List IdList);

    //foreach-2
    List selectForeachTwo(List StudentList);

    List selectAllStudents();

}

第六章PageHelper

PageHelper做数据分页。在你的select语句后面加入分页的sql内容,如果你使用的MySQL数据库
它就是在select * from student后面加入limit语句
Mybaatis通用分页插件
https://github.com/pagehelper/Mybatis-PageHelper
使用步骤:
1、加入依赖pagehelper依赖
    
      com.github.pagehelper
      pagehelper
      5.1.10
    
2、在mybatis主配置文件,加入(plugins)插件声明
    
        
    
3、在select语句之前,调用PageHelper.startPage(页码,每页大小)
        PageHelper.startPage(1, 2);
        List stus = dao.selectAllStudents();

第七章其他配置文件

[1]MyBatis主配置文件




    
    

    
    
        
    

    
    
    
        
    


    
        
    

    
        
            
            
            
                
                
                
                
                
                
            
        
    
    
    
        
        
        
        

    

[2]mapper文件Dao配置文件





    

    
    

    

    


    
    

    
    
        insert into student values(#{id},#{name},#{email},#{age})
    

    


    

    
    

    
    

    
    
       update student set name=#{name},email=#{email} where id=#{id}
    

    

    
    

    


    

    

    








mybatis框架图

SSM(spring-springmvc-mybatis)学习笔记(完结)_第1张图片

Spring篇

第一章Spring概述

第一章Spring概述
什么是Spring
Spring就是一个Java框架,使用Java语言开发的,轻量级的,开源的框架。可以在JavaSE,JAVAEE项目中都可以使用
Spring核心技术:IOC,AOP
Spring又叫做:容器,spring作为容器,主要装的是Java对象,可以让spring创建Java对象,给属性赋值。
Spring作用:实现解耦合,解决Java对象之间的耦合,解决模块之间的耦合
tomcat也是容器:管理的是Servlet,listener,filter等对象。创建HelloServlet类,写web.xml
spring:创建SomeServiceImpl,写spring的配置文件

spring的地址
http://spring.io

spring优点:
spring是一个框架,是一个半成品的软件,有20个模块组成,它是一个容器管理对象
容器是装东西的,Spring容器不装文本,数字。装的是对象。Spring是存储对象的容器
1、轻量
Spring框架使用的jar都比较小,一般在1M以下或者几百KB.Spring核心功能所需的jar总共在3M左右
Spring框架运行占用的资源少,运行效率高.不依赖其他jar
2、针对接口编程,解耦合
Spring提供了IOC控制反转,由容器管理对象,对象的依赖关系。原来在程序代码中的对象创建方式,现在由容器完成,对象之间的依赖解耦合
3、AOP编程的支持
通过Spring提供的AOP功能,方便进行面向切面的编程,许多不容易用传统OOP实现的功能可以通过AOP轻松应对
在Spring中,开发人员可以从繁杂的事务管理代码中解脱出来,通过声明式方式灵活的进行事务的管理,提高开发效率和质量
4、方便集成各种优秀框架
Spring不排斥各种优秀的开源框架,而且Spring可以降低各种框架的使用难度
Spring提供了对各种优秀框架(Struts,Hibernate、Mybatis)的支持简化框架的使用
Spring像插线板一样,其他框架是插头,可以容易的组合在一起,需要使用哪个框架,就把这个插头放入插线板,不需要可以轻易的移除

第二章IOC控制反转

IOC:Inversion of Control控制反转,是一个理论,一个指导思想,指导开发人员如何使用对象,管理对象的。
把对象的创建,属性赋值,对象的声明周期都交给代码之外的容器管理


IOC分为控制和反转
    控制:对象创建,属性赋值,对象声明周期管理
        反转:把开发人员管理对象的权限转移给了代码之外的容器实现,由容器完成对象的管理
        正转:开发人员在代码中,使用new构造方法创建对象


        开发人员掌握了对象的创建,属性赋值,对象从开始到销毁的全部过程。开发人员有对对象全部控制
    通过容器,可以使用容器中的对象(容器已经创建了对象,对象属性赋值了,对象也组装好了)
    Spring就是一个容器,可以管理对象,创建对象,给属性赋值
IOC的技术实现
DI(依赖注入):Dependency Injection,缩写是DI,是IOC一种技术实现,程序只需要提供要使用的对象的名称就可以了
对象如何创建,如何从容器中查找,获取都由容器内部自己实现
依赖名词:比如说ClassA类使用了ClassB的属性或者方法,叫做ClassA依赖ClassB
Spring框架使用的DI实现IOC
通过Spring框架,只需要提供要使用的对象名词就可以了,从容器中获取名称对应的对象
Spring底层使用的反射机制,通过反射创建对象,给属性。

使用Spring:Spring作为容器管理对象,开发人员从Spring中获取要用的对象
实现步骤:
            1、新建maven项目
            2、加入依赖,修改pom.xml
                spring-context:spring依赖
                junit:单元测试
            3、开发人员定义类:接口和实现类,类也可以没有接口
            4、创建Spring的配置文件 作用:声明对象,把对象交给Spring创建和管理
               使用标签表示对象声明,一个bean表示一个Java对象
        
            5、使用容器中的对象
               创建一个表示spring容器的对象 ApplicationContext
               从容器中,根据名称获取对象,使用getBean("对象名称")
        String config = "IOC/item01/Item01.xml";
        ApplicationContext ctx = new ClassPathXmlApplicationContext(config);
        UserService userService = (UserService) ctx.getBean("userService");

Spring的配置文件
    spring标准的配置文件:
    
    

    
    1、根标签是beans
    2、beans后面的是约束文件说明
    3、beans里面是bean声明
    4、什么是bean:bean就是Java对象,spring容器管理的Java对象,叫做bean

Spring是什么时候创建对象?
    在创建spring容器对象的时候,会读取配置文件,创建文件中声明的Java对象
    优点:获取对象的速度快,因为对象已经创建好了
    缺点:占用内存

spring容器创建对象,一次创建几个?
    在创建容器对象时,会把配置文件中的所有对象都创建出来(spring的默认规则)

spring容器创建对象的特点:
    1、容器对象ApplicationContext:接口
    通过ApplicationContext对象,获取要使用的其他Java对象,执行getBean("")
    2、spring默认是调用类的无参构造方法,创建对象
    3、spring读取配置文件,一次创建好所有的Java对象,都放到map中

DI:给属性赋值
    spring调用类的无参构造方法,创建对象.对象创建后给属性赋值.
    给属性赋值
        1、xml配置文件中的标签和属性
        2、使用注解

DI分类:
        1、set注入,设值注入
        2、构造注入

基于xml的DI
在xml配置文件中使用标签和属性,完成对象创建,属性赋值。
        1、set注入,也叫设值注入[和属性无关]
        spring调用类中的set方法,在set方法中可以完成属性赋值,推荐使用
        
            
            
        

        2、引用类型注入
        
            
            
            
            
            
        


构造注入
       构造注入:spring调用类中的有参构造方法,在创建对象的同时,给属性赋值
引用类型的自动注入
概念:spring可以根据某些规则给引用类型完成赋值,只对引用类型有效。规则byName,byType
        1、byName(按名称注入):Java 类中引用类型属性名称和spring容器中bean的id名称一样的
           且数据类型也是一样的,这些bean能够赋值给引用类型
        语法:
            
                简单类型赋值
            
        2、byType(按类型注入):Java类中引用类型的数据类型和spring容器中bean的class值是同源关系
           这些bean赋值给引用类型
           同源关系:
            1、Java中引用类型的数据类型和bean的class值是一样的
            2、Java中引用类型的数据类型和bean的class值是父子类关系的
            3、Java中引用类型的数据类型和bean的class是接口和实现类关系的
            注意:在xml配置文件中,符合条件的对象
                只能有一个多于一个就会报错
            
                
                
            

项目中使用多个Spring配置文件
        分多个配置文件的方式:
            1、按功能模块分,一个模块一个配置文件
            2、按类的功能分,数据库操作相关的类在一个文件,service类在一个配置文件,配置redis,事务等等的一个配置文件
        spring管理多个配置文件:常用的是包含关系的配置文件,项目中有一个总的文件,里面有import标签包含其他的多个配置文件
            语法:
            总的文件(xml)
            
            
            关键字"classpath":表示类路径,也就是类文件(class文件)所在的目录,spring到类路径中加载文件
                              什么时候使用classpath:在一个文件中要使用其他文件,需要使用classpath

基于注解的DI:使用spring提供的注解,完成Java对象创建,属性赋值。
        注解使用的核心步驟:
        1、在源代码加入注解:@Component()
        2、在spring的配置文件,加入组件扫描器的标签
        
        注意:
           使用value指定对象的名称
           @Component(value = "myStudent")
           省略value
           @Component("myStudent")
           没有提供自定义对象名称,使用框架的默认对象名称:类名首字母小写


和@Component功能相同的创建对象的注解
         1、@Repository:放在dao接口的实现类上面,表示创建dao对象,持久层,能访问数据库
         2、@Service:放在业务层接口的实现类上面,表示创建业务层对象,业务层对象有事务的功能
         3、@Controller:放在控制器类的上面,表示创建控制器对象。属于表示层对象。
                        控制器对象能接收请求,把请求的处理结果显示给用户

          以上四个注解都能创建对象,但是@Repository,@Service,@Controller有角色说明,表示对象是分层的
          对象是属于不同层的,具有额外的功能
          扫描多个包的三种方式
                  第一种,使用多次组件扫描器
                  第二种,使用分隔符(;或者,),指定多个包
                  
                  第三种指定父包

创建对象的注解
        @Component[Bean]、@Repository[Dao层]、@Service[业务层]、@Controller[Web服务器专用]
简单类型属性赋值
        @Value
引用类型赋值
        @Autowired:spring提供的注解.支持byName,byType
        @Autowired:默认就是byType
        @Autowired @Qualifier:使用byName

        @Resource:来自jdk中的注解,给引用类型赋值的,默认是byName
        @Resource:先使用byName,再byType
        @Resource(name="bean的名称"):只使用byName注入w


IOC总结
IOC:管理对象的,把对象放在容器中,创建,赋值,管理依赖对象
IOC:通过对象,实现解耦合,IOC解决处理业务逻辑对象之间的耦合关系,也就是service和dao之间的解耦合

spring作为容器适合管理什么对象:
1、service对象,dao对象
2、工具类对象


不适合交给spring的对象
1、实体类
2、servlet,listener,filter等web中的对象,他们是tomcat创建和管理的

set注入配置文件XML




    
    
    
    
        
    

    

    

    
    
          
             
        
        
        
    

    
    
        
        
    






    

    
    

    
         
    

SSM(spring-springmvc-mybatis)学习笔记(完结)_第2张图片

注解注入

package IOC.items.item02;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

/**
 * @Component: 表示创建对象, 对象放到容器中, 作用是
 * 属性:value,表示对象名称,也就是bean的id属性值
 * 位置:在类的上面,表示创建此类的对象
 * @Component(value = "myStudent") 等同于
 * 
 * 

* 和@Component功能相同的创建对象的注解 * 1、@Repository:放在dao接口的实现类上面,表示创建dao对象,持久层,能访问数据库 * 2、@Service:放在业务层接口的实现类上面,表示创建业务层对象,业务层对象有事务的功能 * 3、@Controller:放在控制器类的上面,表示创建控制器对象。属于表示层对象。 * 控制器对象能接收请求,把请求的处理结果显示给用户 *

* 以上四个注解都能创建对象,但是@Repository,@Service,@Controller有角色说明,表示对象是分层的 * 对象是属于不同层的,具有额外的功能 */ //使用value指定对象的名称 //@Component(value = "myStudent") //省略value @Component("myStudent") //没有提供自定义对象名称,使用框架的默认对象名称:类名首字母小写 //@Component public class Student { /** * 简单类型属性赋值:@Value * * @Value:简单类型属性赋值 属性:value简单类型属性值 * 位置: * 1、在属性定义的上面,无需set方法,推荐使用 * 2、在set方法的上面 */ //使用外部属性文件中的数据,语法${"key"} @Value("${myname}") private String name; private int age; public Student() { System.out.println("Student无参数构造方法"); } public void setName(String name) { System.out.println("setName=" + name); this.name = name; } @Value("${myage}") public void setAge(int age) { System.out.println("setAge=" + age); this.age = age; } @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", age=" + age + '}'; } }

package IOC.items.item04;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component("myStudent")
public class Student {

    //${properties文件中的value}
    @Value("${myname}")
    private String name;
    @Value("${myage}")
    private int age;

    /**
     * 引用类型
     *
     * @Autowired: spring框架提供的, 给引用类型赋值, 使用自动注入原理。
     *             支持byName,byType.默认是byType
     *              位置:
     *              1、在属性定义的上面,无需set方法,推荐使用
     *              2、在set方法的上面
     *
     * byName自动注入:
     *              1、@Autowired:给引用类型赋值
     *              2、@Qualifer(value="bean的id") 从容器中找到指定名称对象,把对象赋值给引用类型
     */

    //使用byName
    @Autowired
    @Qualifier(value = "mySchool")
    private School school;

    public Student() {
        System.out.println("Student无参数构造方法");
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", school=" + school +
                '}';
    }
}
package IOC.items.item04;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component("mySchool")
public class School {

    @Value("中国云南大学")
    private String name;
    @Value("广东山西")
    private String address;

    public void setName(String name) {
        this.name = name;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    @Override
    public String toString() {
        return "School{" +
                "name='" + name + '\'' +
                ", address='" + address + '\'' +
                '}';
    }
}

注解注入的XML配置文件





    
    
    
    
    
    

Test测试类

package IOC.Item;

import IOC.items.item01.Bean.SysUser;
import IOC.items.item01.Service.UserService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Test01 {

    @Test
    public void test01() {
        String config = "IOC/item01/Item01.xml";
        ApplicationContext ctx = new ClassPathXmlApplicationContext(config);
        UserService userService = (UserService) ctx.getBean("userService");
        SysUser user = new SysUser();
        user.setName("Xixi");
        user.setAge(18);
        userService.addUser(user);
    }
}

SSM(spring-springmvc-mybatis)学习笔记(完结)_第3张图片

第三章AOP面向切面编程

增加功能,导致的问题
在源代码中,业务方法中增加的功能
1、源代码可能改动的比较多
2、重复代码比较多
3、代码难以维护

AOP概念
什么是AOP [Aspect Orient Programming]:面向切面编程
        Aspect:表示切面,给业务方法增加的功能,叫做切面,切面一般都是非业务功能,而且切面功能一般都是可以复用的
               例如 日志功能,事务功能,权限检查,参数检查,统计信息等等
        Orient:面向,对着
        Programming:编程。
        当目标方法需要一些功能时,可以在不修改,不能修改源代码的情况下,使用aop技术在程序执行期间,生成代理对象
        通过代理执行业务方法,同时增加功能


怎么理解面向切面编程?以切面为核心设计开发你的应用
        1、设计项目时,找出切面的功能
        2、安排切面的执行时间,执行的位置

AOP作用
        1、让切面功能复用
        2、让开发人员专注业务逻辑,提高开发效率
        3、实现业务的解耦和其他非业务功能解耦合
        4、给存在的业务方法,增加功能,不用修改原来的代码

AOP中术语:
        1、Aspect:切面,给业务方法增加的功能
        2、JoinPoint:连接点,连接切面的业务方法,在这个业务方法执行时,会同时执行切面的功能
        3、Pointcut:切入点,是一个或多个连接点集合。表示这些方法执行时,都能增加切面的功能
                    表示切面执行的位置
        4、target:目标对象,给那一个对象增加切面的功能,这个对象就是目标对象
        5、Adivice:通知(增强),表示切面的执行时间,在目标方法之前执行切面,还是目标方法之后执行切面
        AOP中的重要三要素:Aspect,Pointcut,Adivice.
        这个概念的理解是:在Adivice的时间,在Pointcut的位置,执行Aspect

        AOP是一个动态的思想,在程序运行期间,创建代理(ServiceProxy),使用代理执行方法时
        增加功能,这个代理对象是存在内存中的
什么时候用AOP
        要给某些方法增加相同的一些功能,源代码不能改,给业务方法增加非业务功能,也可以使用AOP


AOP技术思想的实现
        使用框架实现AOP,实现AOP的框架有很多,
        1、Spring:Spring框架实现AOP思想中的部分功能,Spring框架实现AOP的操作比较繁杂,
        2、Aspectj:独立的框架,专门是AOP


使用Aspectj框架实现AOP
        通知:
        Aspectj框架可以使用注解和xml配置文件两种方式实现AOP
        Aspectj表示切面执行的时间,用的通知(Advice).这个通知可以使用注解表示
        讲5个注解,表示切面的5个执行时间,这些注解叫做通知注解
        @Before:前置通知         在目标方法之前执行的
        @AfterRetunring:后置通知 在目标方法之后执行的
        @Around:环绕通知
        @AfterThrowing:异常通知
        @After:最终通知
        一个目标方法可以加多个通知


Pointcut位置
        Pointcut用来表示切面执行的位置,使用Aspectj中切入点表达式
        切入点表达式语法:execution(方法的定义)


使用aspectj框架的注解,实现前置通知
        实现步骤:
        1、新建maven项目
        2、修改pom.xml加入依赖
           spring-context依赖,spring-aspects依赖(能使用aspects框架的功能)
        3、创建业务接口和实现类
        4、创建一个叫做切面类,是一个普通类
           [1]在类的上面加入@Aspect
           [2]在类定义方法,方法表示切面的功能
              在方法的上面加入Aspect框架中的通知注解,例如@Before(value="切入点表达式")
        5、创建spring配置文件
           [1]声明目标对象
           [2]声明切面类对象
           [3]声明自动代理生成器
        6、创建测试类,测试目标方法执行时,增加切面的动能


AspectJ定义了专门的表达式用于指定切入点,表达式的原型是:
execution(public * *(..))   指定切入点:任意公共方法
execution(* set *(..))      指定任何一个以 "set" 开始的方法


Aspect:切面类注解
        位置:放在某个类的上面
        作用:表示当前类是切面类
        切面类:表示包含切面功能的类


@Before:前置通知 属性:value 切入点表达式,表示切面的执行位置
        在这个方式时,会同时执行切面的功能
        位置:在方法的上面
        特点:
        [1]执行时间,在目标方法之前执行的
        [2]不会影响目标方法的执行
        [3]不会修改目标方法的执行结果

切面类中的通知方法,可以有参数,也可以没有
        JoinPoint必须是他
        JoinPoint:表示正在执行的业务方法,相当于反射中的Method
        使用要求:必须是参数列表的第一个
        作用:获取方法执行时的信息,例如方法名称,方法的参数集合
        @Before(value = "execution(* *..SomeServiceImpl.do*(..))")


@Around环绕通知
       ProceedingJoinPoint extends JoinPoint
       @Around(value="切入点表达式")
       使用环绕通知:就是调用切面类中的通知方法
       位置:在方法的上面
       返回值:Object,表示调用目标方法希望得到执行结果(不一定是目标方法自己的返回值)
       参数:ProceedingJoinPoint
       作用:执行目标方法的,等于Method.invoke()
       虽然执行了doFirst目标方法,但是实际上只是执行了MyAspect类的myAround方法
       特点:
       1、在目标方法的前和后都能增强功能
       2、控制目标方法是否执行
       3、修改目标方法的执行结果


@AfterThrowing异常通知
语法@AfterThorwing(value="切入点表达式",throwing="自定义变量")


@After最终通知
语法@after(value="切入点表达式")

@Pointcut定义和管理切入点注解
@Pointcut(value="切入点表达式")
    @Pointcut(value = "execution(* *..SomeServiceImpl.doThird(..))")
    public void mypt() {
        无需代码
    }

Aspect切面功能实现

前置通知

package AOP.Items.item01.handle;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

import java.util.Date;

/**
 * Aspect:切面类注解
 * 位置:放在某个类的上面
 * 作用:表示当前类是切面类
 * 切面类:表示包含切面功能的类
 */
@Aspect
public class MyAspect {
    /**
     * 定义方法,表示切面的具体功能
     * 前置通知方法的定义
     *          [1]方法是public
     *          [2]方法是void
     *          [3]方法名臣自定义
     *          [4]方法可以有参数,如果有是JoinPoint也可以没有
     */


    /**
     * @Before:前置通知 属性:value 切入点表达式,表示切面的执行位置
     * 在这个方式时,会同时执行切面的功能
     *    位置:在方法的上面
     *    特点:
     *        [1]执行时间,在目标方法之前执行的
     *        [2]不会影响目标方法的执行
     *        [3]不会修改目标方法的执行结果
     */
    /*
    @Before(value = "execution(public void AOP.Items.item01.sevice.serviceImpl.SomeServiceImpl.doSome(String , int ))")
    public void myBefore01() {
        //切面的功能代码
        System.out.println("前置通知,切面功能,在目标方法之前先执行" + new Date());
    }


    @Before(value = "execution(void AOP.Items.item01.sevice.serviceImpl.SomeServiceImpl.doSome(String , int ))")
    public void myBefore02() {
        //切面的功能代码
        System.out.println("前置通知,切面功能,在目标方法之前先执行" + new Date());
    }
    */

    /**
     * 切面类中的通知方法,可以有参数,也可以没有
     * JoinPoint必须是他
     * JoinPoint:表示正在执行的业务方法,相当于反射中的Method
     * 使用要求:必须是参数列表的第一个
     * 作用:获取方法执行时的信息,例如方法名称,方法的参数集合
     */

    @Before(value = "execution(* *..SomeServiceImpl.do*(..))")
    public void myBefore03(JoinPoint joinPoint) {
        //获取方法的定义
        System.out.println("前置通知中,获取目标方法的定义:" + joinPoint.getSignature());
        System.out.println("前置通知中,获取方法名称:" + joinPoint.getSignature().getName());
        //获取方法执行时参数
        Object[] args = joinPoint.getArgs();//数组中存放的是,方法的所有参数
        for (Object arg : args) {
            System.out.println("前置通知,获取方法的参数:" + arg);
        }
        String methodName = joinPoint.getSignature().getName();
        if ("doSome".equals(methodName)) {
            //切面的功能代码
            System.out.println("doSome输出日志-------前置通知,切面功能,在目标方法之前先执行" + new Date());
        } else if ("doOther".equals(methodName)) {
            System.out.println("doOther前置通知,作为方法名称,参数的记录");
        }

    }


}

后置通知

package AOP.Items.item02.handle;

import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;


/**
 * Aspect:切面类注解
 * 位置:放在某个类的上面
 * 作用:表示当前类是切面类
 * 切面类:表示包含切面功能的类
 */
@Aspect
public class MyAspect {
    /**
     * 定义方法,表示切面的具体功能
     * 后置通知方法的定义
     *      [1]方法是public
     *      [2]方法是void
     *      [3]方法名称自定义
     *      [4]方法有参数,推荐使用Object类型
     */

    /**
     * @AfterReturning:后置通知 属性:value切入点表达式
     * returning:自定义的变量,表示目标方法的返回值的
     * 自定义变量名称必须和通知方法的形参名一样
     * 位置:在方法的上面
     * 特点:
     * [1]在目标方法之后,执行的
     * [2]能获取到目标方法的执行结果
     * [3]不会影响目标方法的执行
     *
     * 方法的参数:
     * Object res:表示目标方法的返回值,使用res接收doOter的调用结果
     * Object res=doOhter();
     * 后置通知的执行顺序
     * Object res=SomeServiceImpl.doOther(..);
     * myAfterReturning(res);
     *
     * 思考:
     *      1、doOther方法返回是String,Integer,long等基本类型
     *         在后置通知中,修改返回值,是不会影响目标方法的最后调用结果
     *      2、doOther返回结果是对象类型,例如Student
     *         在后置通知方法中,修改这个Student对象的属性,会不会影响最后的调用结果
     */

    @AfterReturning(value = "execution(* *..SomeServiceImpl.doOther(..))", returning = "res")
    public void myAfterReturning(Object res) {
        //修改目标方法的返回值
        if (res != null) {
            res="Hello AspectJ";
        }
        System.out.println("后置通知,在目标方法之后,执行的。能拿到执行结果" + res);
        //Obeject res有什么用
        /*
        if ("abcd".equals(res)) {
            System.out.println("根据返回值的不同,做不同的增强功能");
        } else if ("add".equals(res)) {
            System.out.println("doOthre做了添加数据库,我做了备份数据");
        }
        */
    }

}

 环绕通知

package AOP.Items.item03.handle;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;

import java.util.Date;

/**
 * Aspect:切面类注解
 * 位置:放在某个类的上面
 * 作用:表示当前类是切面类
 * 切面类:表示包含切面功能的类
 */
@Aspect
public class MyAspect {
    /**
     * 环绕方法,定义表示切面的具体功能
     * 环绕通知方法的定义
     * [1]方法是public
     * [2]方法是必须有返回值,推荐使用Object类型
     * [3]方法名称自定义
     * [4]方法必须有ProceedingJoinPoint参数.
     *
     * @Around:环绕通知 属性:value切入点表达式
     * 位置:在方法的上面
     * 返回值:Object,表示调用目标方法希望得到执行结果(不一定是目标方法自己的返回值)
     * 参数:ProceedingJoinPoint
     * 作用:执行目标方法的,等于Method.invoke()
     * 

* 虽然执行了doFirst目标方法,但是实际上只是执行了MyAspect类的myAround方法 */ @Around(value = "execution(* *..SomeServiceImpl.doFirst(..))") public Object myAround(ProceedingJoinPoint point) throws Throwable { //获取方法执行时的参数值 Object[] args = point.getArgs(); String name = ""; if (args != null && args.length > 0) { Object arg = args[0]; if (arg != null) { name = (String) arg; } } Object methodReturn = null; System.out.println("执行了环绕通知,在目标方法之前,输出日志时间" + new Date()); //执行目标方法ProceedingJoinPoint,表示doFirst if ("Morries".equals(name)) { methodReturn = point.proceed();//method.invoke(),表示执行doFirst()方法本身 } if (methodReturn != null) { methodReturn = "环绕通知中,修改目标方法原来的执行结果"; } System.out.println("执行了环绕通知,在目标方法之后,增加了事务提交功能"); //return "Hello Around,不是目标方法的执行结果"; return methodReturn; } }

主类功能即被切面类

package AOP.Items.item01.sevice.serviceImpl;

import AOP.Items.item01.sevice.SomeService;

public class SomeServiceImpl implements SomeService {

    @Override
    public void doSome(String name, int age) {
        System.out.println("业务方法doSome(),创建商品的订单");
    }

    @Override
    public void doOther() {
        System.out.println("业务方法doOther()");
    }
}

AOP配置文件




    
    

    
    

    
    

SSM(spring-springmvc-mybatis)学习笔记(完结)_第4张图片

第四章Spring集成Mybatis

spring能集成很多的框架,是spring一个优势功能,通过集成功能,让开发人员使用其他框架更方便
集成使用的是spring IOC核心技术

要使用框架,例如mybatis,怎么使用mybatis
使用mybatis,需要创建mybatis框架中的某些对象,使用这些对象,就能使用mybatis提供的功能了
分析:mybatis执行sql语句,需要使用那些对象
1、需要有Dao接口的代理对象,例如StudentDao接口,需要一个它的代理对象
   使用SqlSession.getMapper(StudentDao.class),得到dao代理对象
2、需要有SqlSessionFactory,创建SqlSessionFactory对象,才能使用openSession()得到SqlSession对象
3、数据源DataSource对象,使用一个更强大,功能更多的连接池对象代替mybatis自己的PooledDataSource


事务管理器
1、使用jdbc访问数据库,事务处理
public void updateAccount(){
    Connection con=....
    con.setAutoCommit(false);
    stat.insert();
    stat.update();
    con.commit();
    con.setAutocommit(true);
}

2、mybatis执行数据库,处理事务
public void updateAccount(){
    SqlSession session=SqlSession.openSession(false);
    try{
        session.insert("insert into student.....");
        session.update("update school.....");
        session.commit();
    }catch(Exception e){
        session.roollback();
    }

}



1、使用的mysql数据库,使用学生表student2(id int 主键列 自动增长,
                                    name varchar(20),
                                    age int         )

2、创建maven项目
3、加入依赖
   spring依赖,mybatis依赖,mysql驱动
   mybatis-spring依赖(mybatis网站上提供的,用来在spring项目中,创建mybatis对象)
   spring有关事务的依赖

   mybatis和spring整合的时候,事务是自动提交的

4、创建实体类Student
5、创建Dao接口和mapper文件写sql语句
6、写mybatis主配置文件
7、创建service接口和他的实现类
8、创建spring的配置文件
    [1]声明数据源DataSource,使用的阿里云Druid连接池
    [2]声明SqlSessionFactoryBean类,在这个类内部创建的是SqlSessionFactory对象
    [3]声明MapperScannerConfiguration类,在内部创建Dao代理对象
       创建好的对象都放在spring容器中
    [4]声明Service对象,把[3]中的dao赋值给service属性


事务定义的接口TransactionDefinition
TransactionDefinition接口,定义了三类常量,定义了有关事务控制的属性
事务的属性:
        1、隔离级别
        2、传播行为
        3、事务的超时
        给业务方法说明事务属性

隔离级别:控制事务之间影响的程度
1、DEFAULT:采用DB默认事务隔离级别,Mysql的默认为REPETABLE_READ,Oracl默认为READ_COMMITTED
2、READ_UMCOMMITTED:读未提交,未解决任何并发问题
3、READ_COMMITTED:读已提交,解决脏读,存在不可重复读与幻读
4、REPEATALE_READ:可重复读,解决脏读,不可重复读,存在幻读
5、SERIALIZABLE:串行化,不存在并发问题

超时时间
超时时间,以秒为单位,整数值,默认是-1
超时时间:表示一个业务方法最长的执行时间,没有达到时间执行完毕,spring回滚事务

传播行为
传播行为有七个
传播行为:业务方法在调用时,事务在方法之间的,传递和使用
使用传播行为,标识方法有无事务
1、PROPAGATION_REQUIRED
    spring默认传播行为,方法调用的时候,如果存在事务就是使用当前的事务
    如果没有事务则新建事务,方法在新事务中执行
2、PROPAGATION_REQUIRES_NEW
    方法需要一个新事务,如果调用方法时,存在一个事务,则原来的事务暂停,直到新事务执行完毕
    如果方法调用时,没有事务,则新建一个事务,在新事务执行代码
3、PROPAGATION_SUPPORTS
    SUPPORTS:支持,方法有事务可以正常执行,没有事务也可以正常执行

Spring框架使用事务管理器对象,管理所有的事务
事务管理器接口:PlatformTransactionManager
        作用:定义了事务的操作,主要是commit(),rollback()
事务管理器有很多实现类:一种数据库访问技术有一个实现类,由实现类具体完成事务的提交,回滚
意味着:jdbc或者mybatis访问数据库有自己的事务管理器实现类:DataSourceTransactionManager
hibernate框架,它的事务管理器实现类:HibernateTrasactionManager

事务使用的AOP的环绕通知
环绕通知:可以在目标方法的前和后都能增强功能,不需要修改代码
spring给业务方法执行,增加事务上的切面功能
@Around("execution(所有的业务方法)")
public Object myAround(ProceedingJoinPoint joinpoint){
        try{
        PlatformTransactionManager.beginTransaction();  使用spring的事务管理器,开启事务
        joinpoint.proceed();       执行目标方法
        PlatformTransactionManager.commit();    业务方法提交事务,提交事务
        }catch(Exception e){
            PlatformTransactionManager.rollback(); 业务方法正常执行,回滚事务
        }

}


Spring框架使用自己的注解@Transactional控制事务
@Transactional注解,使用注解的属性控制(隔离级别,传播行为,超时)
属性:
1、propagation:事务的传播行为,他使用的Propagation类的枚举值。Propagation.REQUIRED
2、Isolation:表示隔离级别,使用Isolation类的枚举型,表示隔离级别,默认solation.DEFAULT
3、readOnly:Boolean类型的值,表示数据库操作是否是只读的,默认是false

4、timeout:事务超时,默认是-1,整数值,单位秒,例如timeout=20
5、rollbackFor:表示回滚的异常类列表,他的值是一个数组,每个值是异常类型的class.
6、rollbackForClassName:表示回滚的异常类列表,他的值是异常类名称,是String类型的值
7、noRollbackFor:不需要回滚的异常类列表,是class类型的
8、noRollbackForClassName:不需要回滚的异常类列表,是String类型的值
    位置:
        [1]、在业务方法的上面,是在public方法的上面
        [2]、在类的上面

注解的使用步骤:
        1、在spring的配置文件,声明事务的内容
        声明事务管理器,说明使用哪个事务管理器对象
        声明使用注解管理事务,开启是注解驱动
        2、在类的源代码中,加入@Transactional
        事务的控制模式:
        1、编程式,在代码中编程控制事务
        2、声明式,不用编码

使用AspectJ框架在spring的配置文件中,声明事务控制
使用AspectJ的Aop,声明事务控制叫做声明式事务
1、pom.xml加入spring-aspects的依赖
2、在spring的配置文件声明事务的内容
    [1]声明事务管理器
    [2]声明业务方法需要的事务属性
    [3]声明切入点表达式

Spring.xml配置文件




    
    

    
    
        
        
        
    

    
    
        
        
        
        
    

    
    
        
        
        
        
    

    
    
        
    


    
    
        
        
    

    
    

mybatis.xml配置文件




    
    
        
    

    
    
        
        
        
        
    

    
        
        
        
        
        
        
    

ServiceImpl实现类

package Tran_sale.Items.Item02.Service.Impl;

import Tran_sale.Items.Item02.Bean.Goods;
import Tran_sale.Items.Item02.Bean.Sale;
import Tran_sale.Items.Item02.Dao.GoodsDao;
import Tran_sale.Items.Item02.Dao.SaleDao;
import Tran_sale.Items.Item02.Service.BuyGoodsService;
import Tran_sale.Items.Item02.excetion.NotEnougthException;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

public class BuyGoodsServiceImpl implements BuyGoodsService {
    private SaleDao saleDao;
    private GoodsDao goodsDao;

    public SaleDao getSaleDao() {
        return saleDao;
    }

    public void setSaleDao(SaleDao saleDao) {
        this.saleDao = saleDao;
    }

    public GoodsDao getGoodsDao() {
        return goodsDao;
    }

    public void setGoodsDao(GoodsDao goodsDao) {
        this.goodsDao = goodsDao;
    }

    /**
     * @Transactional 放在public方法的上面, 表示方法有事务功能
     * 第一种注释方式
     * @Transactional(propagation = Propagation.REQUIRED,
     * isolation = Isolation.DEFAULT,
     * readOnly = false,timeout = 20,
     * rollbackFor = {NullPointerException.class, NotEnougthException.class})
     * 第二种方式
     * @Transactional(propagation = Propagation.REQUIRED,
     * isolation = Isolation.DEFAULT,
     * readOnly = false, timeout = 20)
     * 

* 解释rollbackFor的使用: * 1、框架首先检查方法抛出的异常是不是在rollbackFor的数组中,如果在一定回滚 * 2、如果方法抛出的异常不在rollbackFor数组中,框架会继续检查抛出的异常是不是RumtimeException * 如果是runtimeException,一定回滚 *

* 例如 抛出SQLException,IOException * rollbackFor={SQLException.class,IOException} */ //第三种方式:使用默认值 REQUIRED,发生运行时异常回滚 @Transactional @Override public void buy(Integer goodsId, Integer num) { System.out.println("buy方法的开始"); //生成销售记录 Sale sale = new Sale(); sale.setGid(goodsId); sale.setNum(num); saleDao.insertSale(sale); //查询商品 Goods goods = goodsDao.selectById(goodsId); if (goods == null) { throw new NullPointerException(goodsId + "商品不存在"); } else if (goods.getAmount() < num) { throw new NotEnougthException(goodsId + "库存不足"); } //更新库存 Goods buygoods = new Goods(); buygoods.setId(goodsId); buygoods.setAmount(num); goodsDao.updateGoods(buygoods); System.out.println("buy方法的完成"); } }

控制器

package com.Items.Item01.controller;

import com.Items.Item01.Bean.Student;
import com.google.gson.Gson;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * @Controller 创建控制器(处理器)对象
 * 控制器:叫做后端控制器(back controller),自定义的类处理请求的
 * 位置:在类的上面,表示创建此类的对象,对象放在springmvc的容器中
 * @RequestMapping放在类的上面 属性 value:表示所有请求地址的公共前缀,相当于是模块名称
 * 位置 在类的上面
 */
@Controller
//@RequestMapping("/test")
public class MyController {
    //定义方法,处理请求 public void doGet(){}

    /**
     * springmvc框架,使用控制器类中的方法,处理请求
     * 方法的特点:
     * 1、方法的形参,表示请求中的参数
     * 2、方法的返回值,表示本次请求的处理结果
     *
     * @RequestMapping:请求映射 属性:value  请求中的uri地址,唯一值,以 "/"开头
     * method 请求方式,使用RequestMehtod.GET
     * 是一个数组
     * 位置:1、在方法的上面(必须的)   2、在类定义的上面(可选)
     * 作用:把指定的请求,交给指定的方法处理,等同于url-pattern
     * ModelAndView
     * Model:表示数据
     * View:表示视图
     */

    //指定some.do使用get请求方式
    @RequestMapping(value = "/some.do", method = RequestMethod.GET)
    public ModelAndView doSome(HttpServletResponse response, HttpServletRequest request, HttpSession session) {//doGet()
        //使用这个方法处理请求,能处理请求的方法叫做控制器方法
        //调用service对象,处理请求,返回数据
        ModelAndView mv = new ModelAndView();
        mv.addObject("msg", "处理了Some.do请求");
        mv.addObject("fun", "处理了dosome方法");

        /**
         指定视图,setViewName("视图完整路径")
         mv.setViewName("/WEB-INF/View/show.jsp");
         mv.setViewName("/WEB-INF/View/other.jsp");
         当配置了事务解析器,使用文件的名称作为视图名使用,叫做视图逻辑名称
         使用了逻辑名称,框架使用配置文件视图解析器的前缀和后缀,拼接为完整的视图路径
         /WEB-INF/View/+show+.jsp
         */
        mv.setViewName("show");
        //返回结果
        return mv;
    }

    /**
     * 当框架调用完dosome()方法之后,得到返回中ModelAndView
     * 框架会在后续的处理逻辑值,处理mv对象里面的数据和视图
     * 对数据执行request.setAttribute("msg", "处理了Some.do请求");把数据放入到request作用域
     * 对视图执行forward转发操作,等同于request.getRequestDispatcher("/show.jsp").forward.....;
     */

    //指定使用post
    @RequestMapping(value = {"/other.do", "/second.do"}, method = RequestMethod.POST)
    public ModelAndView doOther() {//doGet()
        System.out.println("执行了MyController的doOther方法");
        //使用这个方法处理请求,能处理请求的方法叫做控制器方法
        //调用service对象,处理请求,返回数据
        ModelAndView mv = new ModelAndView();
        mv.addObject("msg", "处理了other.do请求");
        mv.addObject("fun", "处理了doOther方法");
        mv.setViewName("show");
        //返回结果
        return mv;
    }


    //不指定method属性,请求方式没有限制
    @RequestMapping(value = "/doFirst")
    public ModelAndView doFirst() {//doGet()
        System.out.println("执行了MyController的doFirst 方法");
        //使用这个方法处理请求,能处理请求的方法叫做控制器方法
        //调用service对象,处理请求,返回数据
        ModelAndView mv = new ModelAndView();
        mv.addObject("msg", "处理了other.do请求");
        mv.addObject("fun", "处理了doOther方法");
        mv.setViewName("show");
        //返回结果
        return mv;
    }


    /**
     * 逐个接收请求参数
     * 要求:请求中的参数名和控制器方法的形参名一样,按名称对象接收请求参数
     * 

* 参数接收: * 1、框架使用request对象,接收参数 * String name=request.getParameter("name"); * String age=request.getParameter("age"); *

* 2、在中央调度器的内部调用 doPropertyParam方法时,按名称对象传递参数 * doPropertyParam(name,Intger.valuof(age)) * 400:http status,表示客户端异常,主要是发生在用户提交参数过程中 */ @RequestMapping(value = "/receive-property.do") public ModelAndView doPropertyParam(String name, int age) { System.out.println("执行了MyController的doPropertyParam方法name:" + name + "age:" + age); ModelAndView mv = new ModelAndView(); //添加数据 mv.addObject("myname", name); mv.addObject("myage", age); mv.setViewName("show"); //返回结果 return mv; } /** * 逐个接收请求参数:请求中参数名和形参名不一样 * * @RequestParam:解决名称不一样的问题 属性:value 请求中的参数名 * required:boolean类型,默认是一个 * true:请求中必须有此参数,没有报错 * faslse:请求中可以没有此参数 * 位置:在形参定义的前面 */ @RequestMapping(value = "/receive-param.do") public ModelAndView doReceiveParam(@RequestParam(value = "rname", required = false) String name, @RequestParam(value = "rage", required = false) int age) { System.out.println("执行了MyController的doReceiveParam方法name:" + name + "age:" + age); ModelAndView mv = new ModelAndView(); //添加数据 mv.addObject("myname", name); mv.addObject("myage", age); mv.setViewName("show"); //返回结果 return mv; } /** * 使用对象接收请求中的参数 * 要求:参数名和Java对象属性名一样 * Java类需要有一个无参构造方法,属性有set方法 *

* 框架的处理: * 1、调用Student的无参构造方法,创造对象 * 2、调用对象set方法,同名的参数,调用对应的set方法 * 参数是name,调用setName(参数值) */ @RequestMapping("/receive-object.do") public ModelAndView doReceiveObject(Student student) { System.out.println("MyController的方法doReceiveObject:" + student); ModelAndView mv = new ModelAndView(); mv.addObject("myname", student.getName()); mv.addObject("myage", student.getAge()); mv.setViewName("show"); return mv; } /** * 控制器方法返回String,表示逻辑名称,需要项目中配置视图解析器 */ @RequestMapping(value = "/return-String-view01.do") public String doReturnStringView01(HttpServletRequest request, String name, Integer age) { System.out.println("MyController的方法doReturnStringView:" + name + age); //返回结果,forward,转发到show.jsp request.setAttribute("myname", name); request.setAttribute("myage", age); return "show"; } /** * 控制器方法返回String,表示完整视图路径,项目中不能配置视图解析器 */ @RequestMapping(value = "/return-String-view02.do") public String doReturnStringView02(HttpServletRequest request, String name, Integer age) { System.out.println("MyController的方法doReturnStringView:" + name + age); request.setAttribute("myname", name); request.setAttribute("myage", age); //返回结果,forward,转发到show.jsp return "/WEB-INF/View/show.jsp"; } /** * 控制器方法是返回是void,响应Ajax请求,使用httpServletRequest输出数据 */ @RequestMapping(value = "/return-void-ajax.do") public void returnvoidAjax(HttpServletResponse response, String name, Integer age) throws IOException { System.out.println("MyController的方法doReturnStringView:" + name + age); //调用service得到结果对象 Student stu = new Student(); stu.setName(name + "同学"); stu.setAge(age); //把对象转为json Gson gson = new Gson(); String json = gson.toJson(stu); System.out.println("服务器端对象转化为json" + json); //输出json,响应Ajax response.getWriter().write(json); /** *把对象转为json * ObjectMapper om=new ObjectMapper(); * String json=om.writeValueAsString(stu); * System.out.println("服务器端对象转为的json"+json); * 输出json,响应AJAX * response.setContentType("application/json;charset=utf-8"); * PrintWriter pw=response.getWriter(); * pw.println(json); * pw.flush(); * pw.close(); * */ } /** * 控制器方法返回Student--json * application/json;charset-utf-8 *

* 框架处理模式: * 1、框架根据控制器方法的返回值类型,找到HttpMessageConverter接口的实现类 * 最后找到的是MappingJackson2HttpMessageConverter *

* 2、使用实现类MappingJackson2HttpMessageConverter执行它的write()方法 * 把Student对象转为了json格式的数据 * 3、框架使用@ResponseBody注解,把2中的json输出给浏览器 * 设置的Content-type:application/json;charset-utf-8 */ @RequestMapping("/doStudentJson.do") @ResponseBody public Student doAjaxJson(String name, Integer age) { System.out.println("控制器方法返回自定义对象Student,转为json" + name + age); Student stu = new Student(); stu.setName("同学" + name); stu.setAge(age); return stu; } /** * 控制器方法返回是List--json array * 框架的处理模式: * 1、框架根据控制器方法的返回值类型,找到HttpMessageConverter接口的实现类 * 最后找到的是MappingJackson2HttpMessageConverter * 2、使用实现类MappingJackson2HttpMessageConverter执行他的write()方法,把student对象转为json格式的数据 * 3、框架使用@ResponseBody注解,把2中的json输出给浏览器 */ @RequestMapping("/doListJsonArray.do") @ResponseBody public List doAjaxJsonArray(String name, Integer age) { System.out.println("控制器方法返回List,转为JsonArray" + name + age); Student stu01 = new Student(); stu01.setName("张三同学"); stu01.setAge(20); Student stu02 = new Student(); stu02.setName("李四同学"); stu02.setAge(26); List stulist = new ArrayList<>(); stulist.add(stu01); stulist.add(stu02); return stulist; } /** * 控制器方法返回String--数据 *区分返回值String是数据还是视图 *1、方法上面有@ReponseBody注解就是数据 *2、方法上面没有@ResponseBody注解就是视图 * * Content-Type:text/plain;charset=ISO-8859-1 *解决中文,需要使用@RequestMapping的produce属性 * produce属性:指定content-Type的值 * * 框架处理String返回值 * 1、框架使用的StringHttpMessageConverter * 2、 * */ @RequestMapping(value = "/doStringData.do",produces = "text/plain;charset=UTF-8") @ResponseBody public String doStringData(String name,Integer age){ System.out.println("控制器方法返回String,是数据"); return"Hello SpringMVC注解式开发"; } }

拦截器

package com.Items.item04.Handle;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.Date;

/**
 * 拦截器
 */
public class MyInterceptor implements HandlerInterceptor {
    /**
     * preHandle:预先处理请求的方法[总开关]
     * 参数:Object handler:被拦截的控制器对象,(MyController)
     * 返回值:boolean
     * true:请求是正确的,可以被Controller处理的
     * MyInterceptor拦截器的preHandle
     * 执行了MyController的doSome方法
     * MyInterceptor拦截器的postHandle
     * MyInterceptor拦截器的afterCompletion
     * 

* false:请求不能被处理,控制器方法不会执行,请求到此截止 * MyInterceptor拦截器的preHandle *

* 特点: * 1、预处理方法它的执行时间:在控制器方法之前先执行的 * 2、可以对请求做处理,可以做登录的检查,权限的判断,统计数据等等 * 3、决定请求是否执行 */ @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("MyInterceptor拦截器的preHandle"); //提示 //request.getRequestDispatcher("/tips.jsp").forward(request, response); return true; } /** * postHandle:后处理方法 * 参数: * Object handler:被拦截的控制器对象(MyController) * ModelAndView mv:控制器方法的返回值(请求的执行结果) * 特点: * 1、在控制器方法之后执行的 * 2、能获取到控制器方法的执行结果,可以修改原来的结果 * 可以修改数据,也可以修改视图 * 3、可以看作对请求的二次处理 */ @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("MyInterceptor拦截器的postHandle"); if (modelAndView != null) { //修改数据 modelAndView.addObject("mydate", new Date()); //修改视图 modelAndView.setViewName("other"); } } /** * afterCompletion:最后执行的方法 * 参数: * Object handler:被拦截的控制器对象(MyController) * Exception ex:异常对象 * 特点: * 1、在请求处理完成后执行的,请求处理完成的标志是视图处理完成,对视图执行forward操作后 * 2、可以做程序最后要做的工作,释放内存, 清理临时变量 * 3、方法的执行条件 * [1]当前的拦截器它的preHanlder()方法必须执行 * [2]preHandler()必须返回true */ @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("MyInterceptor拦截器的afterCompletion"); //获取数据 HttpSession session = request.getSession(); Object attr = session.getAttribute("attr"); System.out.println("attr" + attr); //删除数据 session.removeAttribute("attr"); //确定数据是否删除 attr = session.getAttribute("attr"); System.out.println("删除后,再次检查数据" + attr); } }

前端JSP

<%--
  Created by IntelliJ IDEA.
  User: Morries
  Date: 2021/11/1
  Time: 18:29
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>


    Title

    
    




    发起一个some.do的GET请求
发起了Student/add.do的请求

发起一个some.do的GET请求

姓名:
年龄:

逐个接收请求

姓名:
年龄:

逐个接收请求:请求中参数名和形参名不一样

姓名:
年龄:

对象接收参数:请求中参数名和对象属性名一样

姓名:
年龄:

控制器方法返回String,逻辑名称

姓名:
年龄:

控制器方法返回String,完整视图路径

姓名:
年龄:



发起forward.do

重定向Redirect

姓名:
年龄:

控制器处理数据页面

<%--
  Created by IntelliJ IDEA.
  User: Morries
  Date: 2021/11/1
  Time: 17:58
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>


    Title


    /WEB-INF/View/show.jsp,显示request作用域中的数据

msg数据:${msg}

msg数据:${fun}

myname数据:${myname}

myage数据:${myage}

attr数据:${attr}

Springmvc框架整理图

SSM(spring-springmvc-mybatis)学习笔记(完结)_第5张图片

Spring-Spirngmvc-mybatis(ssm)框架整合

web.xml配置文件




  
  
    contextConfigLocation
    classpath:conf/applicationContext.xml
  
  
    org.springframework.web.context.ContextLoaderListener
  

  
  
    myssm
    org.springframework.web.servlet.DispatcherServlet
    
      contextConfigLocation
      classpath:conf/dispatcherServlet.xml
    
    1
  

  
    myssm
    *.do
  


  
  
    characterEncodingFilter
    org.springframework.web.filter.CharacterEncodingFilter
    
    
      encoding
      UTF-8
    
    
    
      forceRequestEncoding
      true
    
    
    
      forceResponseEncoding
      true
    
  

  
    characterEncodingFilter
    
    /*
  

项目拟定结构

SSM(spring-springmvc-mybatis)学习笔记(完结)_第6张图片

applicationContext.xml 配置文件(spring.xml)




    
    
    


    
        
        
        
    

    
        
        
    

    
        
        
    

    






dispatcherServlet.xml配置文件(springmvc.xml)




    
    

    
    
        
        
        
        
    

    
    



mybatis.xml配置文件




    
    
        
    

    
    
        
        
    

    
    
        
        
    

Bean类对象

package Items.item01.Bean;

public class Student {
    private Integer id;
    private String name;
    private Integer age;

    public Student() {
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

控制器

package Items.item01.controller;

import Items.item01.Bean.Student;
import Items.item01.service.StudentService;
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.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import java.util.List;

@Controller
@RequestMapping("/student")
public class StudentController {
    /**
     * 声明引用类型,调用引用类型的业务方法
     * 引用类型自动注入@Autowired,@Resource
     * 添加学生
     */

    @Autowired
    private StudentService service;


    @RequestMapping("/addStudent.do")
    public ModelAndView addStudent(Student student) {
        ModelAndView mv = new ModelAndView();

        //调用service,处理业务逻辑,把处理结果返回给用户
        int rows = service.addStudent(student);
        String msg = "注册失败!";
        if (rows > 0) {
            //注册成功,给用户成功的数据和视图
            msg = "注册成功";
        }
        mv.addObject("msg", student.getName() + "," + msg);
        mv.setViewName("result");
        return mv;
    }


    @RequestMapping("/queryStudent.do")
    @ResponseBody
    public List queryStudents() {
        List stulist = service.queryStudents();
        return stulist;
    }

}


StudentServiceImpl实现类

package Items.item01.service;

import Items.item01.Bean.Student;
import Items.item01.dao.StudentDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * 
 *
 * @Service
 */
@Service
public class StudentServiceImpl implements StudentService {
    /**
     * dao是引用类型,StudentDao类型的对象是在Spring的配置文件中创建的对象
     * 引用类型自动注入@Autowired,@Resource
     */
    @Autowired
    private StudentDao dao;

    @Override
    public int addStudent(Student student) {
        int rows = dao.insertStudent(student);
        return rows;
    }

    @Override
    public List queryStudents() {
        List stulist = dao.selectStudent();
        return stulist;
    }
}

Dao.xml配置文件




    
    

    
        insert into student2(name,age) values(#{name},#{age})
    




前端入口JSP

<%--
  Created by IntelliJ IDEA.
  User: Morries
  Date: 2021/12/18
  Time: 11:09
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>


    SSM


    

SSM整合开发的例子

注册学生
查询学生

listStudent.jsp页面(查询学生信息页面)

<%--
  Created by IntelliJ IDEA.
  User: Morries
  Date: 2021/12/18
  Time: 11:17
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
    String basePath=request.getScheme()+"://"+
            request.getServerName()+":"+request.getServerPort()+request.getContextPath()+"/";
%>


    
    浏览学生
    
    






        

浏览学生

<%--代表表头的意思thread--%>
id 姓名 年龄

addStudent.jsp页面(注册学生页面)

<%--
  Created by IntelliJ IDEA.
  User: Morries
  Date: 2021/12/18
  Time: 11:06
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%String basePath=request.getScheme()+"://"+
        request.getServerName()+":"+request.getServerPort()+request.getContextPath()+"/";
%>


    
    添加


    

注册学生

姓名:
年龄:
操作

SSM框架图

SSM(spring-springmvc-mybatis)学习笔记(完结)_第7张图片

 

你可能感兴趣的:(spring,mvc,java,mysql,mybatis)