栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

SSM学习笔记(Spring5+SpringMVC)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

SSM学习笔记(Spring5+SpringMVC)

文章目录
  • Spring
    • 1. Spring简介
      • 1.1 Spring主要知识点
      • 1.2 Spring的作用
    • 2. Spring IOC
      • 2.1 思维导图
      • 2.2 Spring IOC核心技术
      • 2.3 Spring框架环境搭建
        • 2.3.1 环境要求
        • 2.3.2 新建Maven项目
        • 2.3.3 调整项目环境
        • 2.3.4 添加Spring框架的依赖坐标
        • 2.3.5 编写Bean对象
        • 2.3.6 添加Spring配置文件
        • 2.3.7 加载配置文件,获取实例化对象
      • 2.4 Spring IOC容器Bean对象实例化模拟
      • 2.5 Spring IOC容器Bean对象实例化
        • 2.5.1 构造器实例化
        • 2.5.2 静态工厂实例化
        • 2.5.3 实例化工厂实例化
        • 2.5.4 三种实例化方法比较
      • 2.6 Spring IOC注入
        • 2.6.1 Spring IOC手动装配(注入)
          • 2.6.1.1 set方法注入
          • 2.6.1.2 构造器注入
          • 2.6.1.3 静态工厂注入
          • 2.6.1.4 实例化工厂注入
          • 2.6.1.5 注入方式选择
        • 2.6.2 Spring IOC自动装配(注入)
          • 2.6.2.1 准备环境
          • 2.6.2.2 @Resource注解
          • 2.6.2.3 @Autowired注解
      • 2.7 Spring IOC扫描器
        • 2.7.1 Spring IOC扫描器的配置
      • 2.8 Bean的作用域与生命周期
        • 2.8.1 Bean的作用域
        • 2.8.2 Prototype作用域
        • 2.8.3 Web应用中的作用域
        • 2.8.4 Bean的生命周期
      • 2.9 Spring IOC总结
    • 3. Spring AOP
      • 3.1 思维导图
      • 3.2 代理模式
      • 3.2 静态代理
        • 3.2.1 代理三要素(以结婚为例)
        • 3.2.2 静态代理的特点
      • 3.3 动态代理
        • 3.3.1 动态代理的特点
        • 3.3.2 JDK动态代理实现
        • 3.3.3CGLIB动态代理
          • 3.3.3.1 添加依赖
          • 3.3.3.1 定义类
          • 3.3.3.2 调用方法
        • 3.3.4 JDK动态代理和CGLIB代理的区别
      • 3.4 Spring AOP
        • 3.4.1 问题引入
        • 3.4.2 第二个栗子(装饰器模式解决)
        • 3.4.3 AOP的特点
          • 3.4.3.1 什么是AOP
          • 3.4.3.2 AOP能做什么?
          • 3.4.3.3 AOP的特点
          • 3.4.3.4 AOP底层代码实现
        • 3.4.4 AOP基本概念
          • 3.4.4.1 Joinpoint (连接点)
          • 3.4.4.2 Pointcut (切入点)
          • 3.4.4.4 Aspect (切面)
          • 3.4.4.5 Target ( 目标对象)
          • 3.4.4.7 Introduction (引入)
        • 3.4.5 Spring AOP的实现
          • 3.4.5.1 Spring环境搭建
          • 3.4.5.2 注解实现AOP
          • 3.4.5.3 xml实现AOP
          • 3.4.5.4 Spring AOP总结
    • 4. Spring MVC
      • 4.1 知识点概览
      • 4.2 MVC思想&SpringMVC框架概念与特点
        • 4.2.1 什么是MVC?
        • 4.2.2 常见MVC框架开发效率比较
        • 4.2.3 SpringMVC是什么?
        • 4.2.4 SpringMVC能帮我们做什么?
      • 4.3 SpringMVC请求流程&环境搭建
        • 4.3.1 SpringMVC请求处理流程分析
      • 4.4 Spring MVC环境搭建
          • 4.4.1 开发环境
          • 4.4.2 pom.xml坐标添加
          • 4.4.3 配置web.xml
          • 4.4.4 servlet-context.xml配置
          • 4.4.5 配置jsp文件
          • 4.4.6 页面控制器
      • 4.5 URL地址映射配置&参数绑定
        • 4.5.1 URL地址映射配置之@RequestMapping
          • 4.5.1.1 映射单个URL
          • 4.5.1.2 映射多个URL
          • 4.5.1.3 映射URL在控制器上
          • 4.5.1.4 设置URL映射的请求方式
          • 4.5.1.5 通过参数名称映射URL
        • 4.5.2 参数绑定
          • 4.5.2.1 基本数据类型
          • 4.5.2.2 包装数据类型
          • 4.5.2.3 字符串类型
          • 4.5.2.4 数组类型
          • 4.5.2.5 JavaBean类型
          • 4.5.2.6 List集合
          • 4.5.2.7 Set集合
          • 4.5.2.8 Map类型
        • 4.5.3 请求域对象
      • 4.6 请求转发与重定向的问题
        • 4.6.1 重定向
        • 4.6.2 请求转发
      • 4.7 SpringMVC之JSON数据开发
        • 4.7.1 基本概念
          • 4.7.1.1 @ResponseBody简介
          • **4.7.1.2 @RequestBody**简介
        • 4.7.2 使用配置
          • 4.7.2.1 在pom.xml中添加json坐标
        • 4.7.3 注解使用
          • 4.7.3.1 @ResponseBody
          • 4.7.3.2 @RequestBody
      • 4.8 课程总结&SpringMVC常用注解
      • 4.8 课程总结&SpringMVC常用注解

Spring

Spring框架是一个开源的JavaEE的应用程序

主要核心是IOC(控制反转/依赖注入)和AOP(面向切面编程)两大技术

1. Spring简介 1.1 Spring主要知识点 1.2 Spring的作用

传统项目分层架构:

  • Dao层:用来与数据库进行一系列JDBC操作,常用框架Mybatis
  • Service层:用来处理业务逻辑,由于业务逻辑的差异性,所以没有主流框架
  • Controller层:用来接收请求、响应数据、地址配置、页面转发,常用框架Spring MVC,常用技术Servlet

Spring定义:Spring是一个基于分布式的框架,是一个轻量级的框架

Spring框架的作用:

  • 配置管理
  • IOC技术:Bean对象的实例化
  • 集成第三方框架,例如Mybatis、Hibernate(SSH中的H,已不流行)Spring MVC、Spring Security权限框架、QUartz时钟框架
  • 自带一系列服务,例如:Mail邮件处理、定时任务处理、异步消息处理

Spring模块划分:

  • Spring IOC模块:Bean对象的实例化
  • Spring AOP模块:动态代理,面向切面编程
  • Spring JDBC模块:事务处理
  • Spring web模块:web处理

2. Spring IOC 2.1 思维导图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JfjCXikx-1634731431674)(https://i.loli.net/2021/10/02/pLg3do8URm9zVIi.png)]

2.2 Spring IOC核心技术
  • 工厂设计模式:简单工厂、工厂方法、抽象工厂
  • XML解析:DOM4J
  • 反射技术:实例化对象、反射获取方法、反射获取属性、反射获取构造器、反射调用方法
  • 策略模式:加载资源
  • 单例:IOC创建实例化对象

2.3 Spring框架环境搭建 2.3.1 环境要求
  • JDK版本1.7以上
  • Spring版本5.x
2.3.2 新建Maven项目

1.创建Maven的普通Java项目

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jSNEoRWr-1634731431675)(https://i.loli.net/2021/10/02/4asKzCYyfkciFRI.png)]

2.设置工作空间

3.设置项目的Maven环境

2.3.3 调整项目环境

1.修改JDK版本

  
    UTF-8
    1.8
    1.8
  

2.修改单元测试版本

  
    
      junit
      junit
      4.12
      test
    
  

3.删除多余的插件

  

  
2.3.4 添加Spring框架的依赖坐标

Maven仓库:https://mvnrepository.com/

	
    
    
      org.springframework
      spring-context
      5.3.9
    
2.3.5 编写Bean对象 2.3.6 添加Spring配置文件

1.再项目的src下创建文件夹resource(Alt+insert)

2.将resource标记为资源目录

3.在srcmainresources目录下新建spring.xml文件,并拷贝官网文档提供的模板内容到xml中

配置bean到xml中,把对应的bean纳入Spring容器中来管理

spring.xml




      
        
    

    
        
    

    


4.spring.xml中配置Bean对象



2.3.7 加载配置文件,获取实例化对象

加载单个配置文件

加载多个配置文件

//Java
//多配置文件加载,通过总的配置文件import其他配置文件,只需要加载总配置文件即可
ApplicationContext ac=new ClassPathXmlApplicationContext("All.xml");


    
    
    

2.4 Spring IOC容器Bean对象实例化模拟

思路

  1. 定义Bean工厂接口,提供获取Bean方法
  2. 定义Bean工厂接口实现类,解析配置文件,实例化Bean对象
  3. 实现获取Bean方法

定义bean



    
     
     

第一步:定义Bean工厂接口,提供获取Bean方法

public interface MyFactory {
    //通过Id属性值获取对象
    public Object getBean(String id);
}

第二步:定义Bean工厂接口实现类,解析配置文件,实例化Bean对象

Maven配置:

    
    
      dom4j
      dom4j
      1.6.1
    
    
    
      jaxen
      jaxen
      1.1.6
    

栗子:

package com.fx.Spring;

import org.dom4j.document;
import org.dom4j.Element;
import org.dom4j.XPath;
import org.dom4j.io.SAXReader;

import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


public class MyClassPathXmlApplicationContext implements MyFactory {

    private List beanList;//存放从配置文件中获取到的bean标签的信息(MyBean代表的就是每一个bean标签)
    private Map beanMap = new HashMap<>();//存放实例化好的对象,通过id获取对应的对象

    
    public MyClassPathXmlApplicationContext(String fileName) {
        //第二步:通过dom4j解析我们的xml配置文件,得到一个list集合
        this.parseXml(fileName);
        //通过反射得到对应的实例化对象,放置在map对象中
        this.instanceBean();
    }

    
    private void parseXml(String fileName) {
        // 1. 获取解析器
        SAXReader saxReader = new SAXReader();
        // 2. 获取配置文件的URL
        URL url = this.getClass().getClassLoader().getResource(fileName);
        try {
            // 3. 通过解析器解析配置文件(xml文件)
            document document = saxReader.read(url);
            // 4. 通过xpath语法解析,获取beans标签下的所有bean标签
            XPath xPath = document.createXPath("beans/bean");
            // 5. 通过指定的解析语法解析文档对象,返回元素集合
            List elementList = xPath.selectNodes(xPath);
            // 6. 判断元素集合是否为空
            if (null != elementList && elementList.size() > 0) {
                //实例化beanList
                beanList = new ArrayList<>();
                // 7. 如果元素集合不为空,遍历集合
                for(Element el : elementList){
                    // 8. 获取bean标签元素的属性(id和class属性值)
                    String id=el.attributevalue("id");//id属性值
                    String clazz=el.attributevalue("class");//class属性值
                    // 9. 获取MyBean对象,将id和class属性值设计到对象中,再将对象设置到MyBean的集合中
                    MyBean myBean = new MyBean(id, clazz);
                    beanList.add(myBean);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    
    private void instanceBean() {
        // 1. 判断对象集合是否为空,如果不为空,则遍历集合,获取对象的id和class属性
        if(null!=beanList&&beanList.size()>0){
            for(MyBean myBean : beanList){
                String id=myBean.getId();
                String clazz=myBean.getClazz();
                try {
                	// 2. 通过类的全路径名,发射得到实例化对象  Class.forName(class).newInstance()
                    Object object = Class.forName(clazz).newInstance();
                    // 3. 将对应的id和实例化好的bean对象设置到map对象中
                    beanMap.put(id,object);
                } catch (Exception e) {
                	e.printStackTrace();
                }
            }
        }
    }

    
    @Override
    public Object getBean(String id) {
        Object obj = beanMap.get(id);
        return obj;
    }
}

2.5 Spring IOC容器Bean对象实例化 2.5.1 构造器实例化

注意:通过默认构造器创建,空构造方法必须存在,否则创建失败

1.设置配置文件spring.xml




        
        

2.代码实现

        BeanFactory factory=new ClassPathXmlApplicationContext("spring02.xml");
        //空构造器实例化
        TypeDao typeDao= (TypeDao) factory.getBean("typeDao");
        typeDao.test();
2.5.2 静态工厂实例化

1.设置配置文件Spring.xml



        
        

2.代码实现

        BeanFactory factory=new ClassPathXmlApplicationContext("spring02.xml");        
		//静态工厂实例化
        TypeService typeService= (TypeService) factory.getBean("typeService");
        typeService.test();
2.5.3 实例化工厂实例化

1.配置xml文件



            
        
        
        
        

2.代码实现

        //实例化工厂实例化
        TypeController typeController= (TypeController) factory.getBean("typeController");
        typeController.test();
2.5.4 三种实例化方法比较

● 方式一:通过bean的缺省构造函数创建, 当各个bean的业务逻辑相互比较独立的时候或者和外界关联较少的
时候可以使用。
● 方式二:利用静态factory方法创建,可以统一管理各 个bean的创建,如各个bean在创建之前需要相同的初始
化处理,则可用这个factory方法险进行统- -的处理等等。
● 方式三:利用实例化factory方法创建,即将factory方法也作为了业务bean来控制,1可用于集成其他框架的
bean创建管理方法, 2能够使bean和factory的角色互换。

​ 开发中项目一般使用一种方式实例化bean,项目开发基本采用第一种方式, 交给Spring托管,使用时直接拿
来使用即可。另外两种了解

2.6 Spring IOC注入

手动实例化与外部引入

图一:

图二:

对比发现:图二中对于UserDao对象的创建并没有像图-那样主动的去实例化,而是通过带参方法形式将 UserDao传入过来,从而实现UserService对UserDao类的依赖。 而实际创建对象的幕后对象即是交给了外部来创建

2.6.1 Spring IOC手动装配(注入)

Spring支持的注入方式有四种:set注入、构造器注入、静态工厂注入、实例化工厂注入

注:

  • 属性字段需要提供set方法
  • 四种手动注入方法,推荐使用set注入

2.6.1.1 set方法注入

类型有:

  1. 业务对象JavaBean
  2. 常用对象和基本类型
  3. 集合类型和属性对象

第一种Set注入:业务对象JavaBean注入

1.属性字段提供set方法

    //业务逻辑对象 JavaBean对象,set方法注入
    private UserDao userDao;

    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }

    public void test(){
        System.out.println("UserService Test...");
        userDao.test();
    }

2.配置文件bean标签中中配置property标签




        
        
                
        

        


第二种,常用对象和基本类型

1.属性字段提供set方法

    //常用类型String(日期类型)
    private String host;

    public void setHost(String host) {
        this.host = host;
    }

    //基本类型Integer
    private Integer port;

    public void setPort(Integer port) {
        this.port = port;
    }

2.配置文件bean标签中中配置property标签

                
                
                
                

第三种,集合类型和属性对象

1.属性字段提供set方法

    //List集合
    private List list;

    public void setList(List list) {
        this.list = list;
    }
    //Set集合
    private Set set;

    public void setSet(Set set) {
        this.set = set;
    }
    //Map集合
    private Map map;

    public void setMap(Map map) {
        this.map = map;
    }
    //properties属性对象
    private Properties properties;

    public void setProperties(Properties properties) {
        this.properties = properties;
    }

2.配置文件bean标签中中配置property标签

                
                        
                                北京
                                上海
                                广州
                                深圳
                        
                
                
                
                        
                                北京
                                上海
                                广州
                                深圳
                        
                
                
                
                        
                                
                                        周杰伦
                                        晴天
                                
                                
                                        林俊杰
                                        江南
                                
                                
                                        陈奕迅
                                        浮夸
                                
                        
                
                
                
                        
                                北京
                                上海
                                深圳
                        
                
2.6.1.2 构造器注入

类型有:

  1. 单个Bean对象作为参数
  2. 多个Bean对象作为参数
  3. Bean对象和常用对象作为参数

构造器注入会产生的问题:循环依赖问题

第一种:单个Bean对象作为参数

java代码:

    private UserDao03 userDao03;
    //构造器构造
    public UserService03(UserDao03 userDao03) {
        this.userDao03 = userDao03;
    }

xml配置:




        
        
                

        
        

第二种:多个Bean对象作为参数

java代码:

    private UserDao02 userDao02;
    public UserService03(UserDao03 userDao03, UserDao02 userDao02) {
        this.userDao03 = userDao03;
        this.userDao02 = userDao02;
    }

xml配置:




        
        
                
        
        

Bean对象和常用对象作为参数

java代码:

    //常用对象、数据类型构造器注入
    private String uName;

    public UserService03(UserDao03 userDao03, UserDao02 userDao02, String uName) {
        this.userDao03 = userDao03;
        this.userDao02 = userDao02;
        this.uName = uName;
    }

xml配置文件:




        
        
                
                
                
        
        

2.6.1.3 静态工厂注入

先欠着,后面再看叭静态工厂注入

2.6.1.4 实例化工厂注入

同上

2.6.1.5 注入方式选择

​ 开发项目中set方式注入首选

​ 使用构造注入可以在构建对象的同时一并完成依赖关系的建立,对象-建立则所有的一 切也就准备好了,但.
如果要建立的对象关系很多,使用构造器注入会在构建函数上留下一长串的参数,且不易记忆,这时使用Set注入会是
个不错的选择。
​ 使用Set注入可以有明确的名称,可以了解注入的对象会是什么,像setXXX(这样的名称会比记忆Constructor
上某个参数的位置代表某个对象更好。

p名称空间的使用

​ spring2.5以后,为了简化setter方法属性注入,引用p名称空间的概念,可以将子元素,简化
为元素属性配置。

第一步:在xml文件中引入p命名空间

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

xml完整配置:



        
        
        
        

第二步:Java配置

//业务逻辑对象 JavaBean对象,set方法注入
    private UserDao userDao;

    public UserService04() {
    }

    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }


    //常用类型String(日期类型)
    private String host;

    public void setHost(String host) {
        this.host = host;
    }


    public void test() {
        System.out.println("UserService Test...");
        userDao.test();

        //常用对象
        System.out.println(host);

    }
2.6.2 Spring IOC自动装配(注入)

注解方式注入Bean

​ 对于bean的注入,除了使用xml配置以外,可以使用注解配置。注解的配置,可以简化配置文件,提高开
发的速度,使程序看上去更简洁。对于注解的解释,Spring对于注解有专 的解释器,对定义的注解进行解析,实
现对应bean对象的注入。通过反射技术实现。

2.6.2.1 准备环境

1.修改配置环境





2.开启自动化装配环境

    
    
2.6.2.2 @Resource注解

@Resource注解实现自动注入(反射)

● 默认根据属性字段名称查找对应的bean对象(属性字段的名称 与bean标签的id属性值相等)
● 如果属性字段名称未找到,则会通过类型(Class类型) 查找
● 属性可以提供set方法,也可以不提供set方法
● 注解可以声明在属性级别或set方法级别
● 可以设置name属性, name属性值必须与bean标签的id属性值一致;如果设置了name属性值,就只会按照
name属性值查找bean对象
● 当注入接口时,如果接口只有一-个实现则正常实例化;如果接口存在多个实现,则需要使用name属性指定需
要被实例化的bean对象

1.xml配置

    
    
    
    
    
    
    
    

2.Java代码

public class UserService {

    //注入JavaBean对象
    @Resource
    private UserDao userDao;
    //set方法注入
    public UserService(UserDao userDao) {
        this.userDao = userDao;
    }
    //接口注入
    @Resource(name = "userDaoImpl02")
    private com.fx.Interface.UserDao iUserDao;


    public void test(){
        System.out.println("UserService Test...");
        userDao.test();
        iUserDao.test();
    }
}
2.6.2.3 @Autowired注解

@Autowired注解实现自动化注入:

● 默认通过类型(Class类型) 查找bean对象 与属性字段的名称无关
● 属性可以提供set方法,也可以不提供set方法
● 注解可以声明在属性级别或set方法级别
● 可以添加@Qualifier结合使用,通过value属性值查找bean对象(value属性值必须要设置,且值要与bean标签的id属性值对应)


1.默认通过类型(Class类型)查找bean对象,与属性字段的名称无关

public class AccountService {

    @Autowired
    @Qualifier(value = "accountDao")
    private AccountDao accountDao;

    public void test(){
        System.out.println("AccountService Test...");
        accountDao.test();
    }
}

2.xml配置



2.7 Spring IOC扫描器

​ 实际的开发中,bean的数量非常多,采用手动配置bean的方式已无法满足生产需要, Spring这时候同样提供
了扫描的方式,对扫描到的bean对象统一进行管理, 简化开发配置,提高开发效率。

2.7.1 Spring IOC扫描器的配置
Spring IOC 扫描器
    作用: bean对象统-进行管理,简化开发配置,提高开发效率
        
    1、设置自动化扫描的范围
    	如果bean对象未在指定包范围,即使声明了注解,也无法实例化
    2、使用指定的注解(声明在类级别)
        bean对象的i d属性默认是类的首字母小写
        Dao层:
        	@Repository
        Service层:
        	@Service
        Controller层:
        	@Controller
    	任意类:
    		@Component
    注:开发过程中建议按照指定规则声明注解

1.设置自动扫描的范围


2.在java中配置相应的加载关系

    @Resource
    private TypeService typeService;
    public void test(){
        System.out.println("TypeController Test...");
        typeService.test();
    }
2.8 Bean的作用域与生命周期 2.8.1 Bean的作用域

​ 默认情况下,我们从Spring容器中拿到的对象均是单例的,对于Bean的作用域如下

Singleton的作用域

​ 注意: lazy-init是懒加载,如果等于true时作用是指Spring容器启动的时候不会去实例化这个bean,而是在程
序调用时才去实例化.默认是false即Spring容器启动时实例化

​ 默认情况下,被管理的bean只会IOC容器中存在一个实例, 对于所有获取该Bean的操作Spring容器将只返回
同一个Bean。

​ 容器在启动的情况下就实例化所有singleton的bean对象,并缓存与容器中

lazy-init属性(懒加载)
如果为false,则在IOC容器启动时会实例化bean对象,默认false
如果为true,则I0C容器启动时不会实例化Bean对象,在使用bean对象时才会实例化
lazy-init设置为false有什么好处?
1.可以提前发现潜在的配置问题

​ 2.Bean 对象存在于缓存中,使用时不用再去实例化bean,加快程序运行效率
什么对象适合作为单例对象?

​ 一般来说对于无状态或状态不可改变的对象适合使用单例模式。(不存在会改变对象状态的成员变量)
比如: controller层、 service层、 dao层

什么是无状态或状态不可改变的对象?
实际上对象状态的变化往往均是由于属性值的变化而引起的,比如user类姓名属性会有变化,属性姓名的变
化一般会引起user对象状态的变化。对于我们的程序来说,无状态对象没有实例变量的存在,保证了线程的安全
性,service层业务对象即是无状态对象。线程安全的。

2.8.2 Prototype作用域

​ 通过scope="prototype"设置bean的类型,每次向Spring容器请求获取Bean都返回一个全新的Bean,相对于"singleton"来说就是不缓存Bean,每次都是一个根据Bean定义 创建的全新Bean。


作用域演示xml代码:



        
        
        

2.8.3 Web应用中的作用域
  1. request作用域

表示每个请求需要容器创建一个全新Bean。 比如提交表单的数据必须是对每次请求新建一个Bean来保持这些表单数据,请求结束释放这些数据。

  1. session作用域

表示每个会话需要容器创建一个全新Bean。 比如对于每个用户-般会有一个会话,该用户的用户信息需要存储到会话中,此时可以将该Bean作用域配置为session级别。

  1. globalSession作用域

类似于session作用域,其用于portlet(Portlet是基 于Java的Web组件,由Portlet容器管理,并由容器处理请求,生产动态内容)环境的web应用。如果在非portlet环境将视为session作用域。

配置方式和基本的作用域相同,只是必须要有web环境支持,并配置相应的容器监听器或拦截器从而能应用

2.8.4 Bean的生命周期

​ 对比已经学过的servlet生命周期(容器启动装载并实例化servlet类,初始化servlet, 调用service方法,销毁servlet)

​ 同样对于Spring容器管理的bean也存在生命周期的概念

​ 在Spring中,Bean的生命周期包括Bean的定义、初始化、使用和销毁4个阶段

Bean的定义

  • 在Spring中,通常是通过配置文档的方式来定义Bean的。
  • 在一个配置文档中,可以定义多个Bean。

初始化

默然在IOC容器加载时,实例化对象

Spring Bean初始化有两种方式:

方式一:在配置文件中通过init-method属性来完成

使用

先欠着,后面在看Bean生命周期

销毁

同上

2.9 Spring IOC总结

IOC/DI -控制反转和依赖注入
将对象实例化的创建过程转交给外部容器(IOC容器充当工厂角色)去负责;属性赋值的操作

3. Spring AOP 3.1 思维导图

3.2 代理模式

代理模式

​ **代理模式在Java开发中是一种比较常 见的设计模式。**设计目的旨在为服务类与客户类之间插入其他功能,插入的功能对于调用者是透明的,起到伪装控制的作用。如租房的例子:房客、中介、房东。对应于代理模式中即:客户类、代理类、委托类(被代理类)。

​ 为某一个对象(委托类)提供一个代理(代理类),用来控制对这个对象的访问。委托类和代理类有一个共同的父类或父接口。代理类会对请求做预处理、过滤,将请求分配给指定对象。

​ 生活中常见的代理情况:
​ 租房中介、婚庆公司等

常用的代理模式:

​ 1.静态代理

​ 2.动态代理


3.2 静态代理 3.2.1 代理三要素(以结婚为例)

1.有共同的行为(结婚) 定义接口

2.目标角色(新人) 实现接口

3.代理角色(婚庆公司) 实现接口,增强用户行为

3.2.2 静态代理的特点

1.目标角色固定

2.在程序应用前就得知目标角色

3.代理对象会增强目标对象的行为

4.可能产生大量代理的情况,导致“类爆炸”


3.3 动态代理

动态代理,可以根据需要,通过反射机制在程序运行期,动态的为目标对象创建代理对象

动态代理的两种实现方式:

  1. JDK动态代理
  2. CGLIB动态代理
3.3.1 动态代理的特点
  1. 目标对象不固定
  2. 在程序运行时,动态创建目标对象
  3. 代理对象会增强目标对象的行为
3.3.2 JDK动态代理实现

JDK动态代理

注意:JDK动态代理的目标对象必须有接口实现

  1. newProxyInstance类

Proxy类:Proxy类是专门完成代理的操作类,可以通过此类为一个或多个接口动态地生成实现类,此类提供了如下操作方法

        
public static object new ProxyInstace(ClassLoader loader,
                                     Class[] interfaces,
                                     InvocationHandler h)

2.动态代理实现栗子:

public class JdkHandler implements InvocationHandler {
    //设置动态代理的目标对象,目标对象的类型不固定,创建时动态生成
    private Object target;
    //通过带参构造器传递目标对象
    public JdkHandler(Object target) {
        this.target = target;
    }

    
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //调用用户方法前的增强行为
        System.out.println("调用用户方法前的增强行为");
        //调用目标对象中的方法(返回Object)
        Object object=method.invoke(target,args);
        //调用用户方法后的增强行为
        System.out.println("调用用户方法后的增强行为");
        return null;
    }
    
    public Object getProxy(){
        Object object= Proxy.newProxyInstance(this.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
        return object;
    }

}

3.测试

//目标对象
Jack jack=new Jack();
//得到代理类
JdkHandler jdkHandler=new JdkHandler(jack);
Marry marry= (Marry) jdkHandler.getProxy();
        

欠着JDK动态代理的源码解析: JDK动态代理源码解析

3.3.3CGLIB动态代理

​ JDK的动态代理机制只能代理实现了接口的类,而不能实现接口的类就不能使用DK的动态代理,cglib是针对
类来实现代理的,它的原理是对指定的目标类生成一个子类, 并覆盖其中方法实现增强,但因为采用的是继承,所
以不能对final修饰的类进行代理。

3.3.3.1 添加依赖

在pom.xml文件中引入cglib的相关依赖


    cglib
    cglib
    2.2.2


3.3.3.1 定义类

实现MethodInterceptor接口

public class CglibInterceptor implements MethodInterceptor {

    //目标对象
    private Object target;
    //通过构造器传入目标对象
    public CglibInterceptor(Object target) {
        this.target = target;
    }

    
    public Object getProxy(){
        //1. 通过Enhancer对象中的create()方法生成一个类,用于生成代理对象
        Enhancer enhancer=new Enhancer();
        //2. 设置父类(将目标类作为代理类的父类)
        enhancer.setSuperclass(target.getClass());
        //3. 设置拦截器,回调对象为本身对象
        enhancer.setCallback(this);
        //4. 生成代理类对象,并返回给调用者
        return enhancer.create();
    }

    
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {

        //增强行为
        System.out.println("intercept方法执行前的增强行为");
        //调用目标类中的方法
        Object object = methodProxy.invoke(target, objects);
        //增强行为
        System.out.println("intercept方法执行后的增强行为");
        return object;
    }
}
3.3.3.2 调用方法
public class TestCglibInterceptor {
    public static void main(String[] args) {
        //1. 得到目标对象
        Jack jack=new Jack();
        //2. 得到拦截器
        CglibInterceptor cglibInterceptor=new CglibInterceptor(jack);
        //3. 得到代理对象
        Marry marry= (Marry) cglibInterceptor.getProxy();
        //4. 通过代理对象调用目标对象中的方法
        marry.toMarry();

        //没有继承接口也能实现cglib动态代理
        User user=new User();
        CglibInterceptor cglibInterceptor02=new CglibInterceptor(user);
        User user1= (User) cglibInterceptor02.getProxy();
        user1.test();
    }
}
3.3.4 JDK动态代理和CGLIB代理的区别
  • JDK动态代理实现接口,Cglib动态代理继承思想
  • JDK动态代理( 目标对象存在接口时)执行效率高于Ciglib
  • 如果目标对象有接口实现,选择JDK代理, 如果没有接口实现选择Cglib代理

最优选择:如果目标对象存在接口实现,优先选择JDK动态代理,反之这选择cglib动态代理

3.4 Spring AOP 3.4.1 问题引入

引入一个问题,如果没有代理模式如何处理下面的业务需求

​ 但这样两个方法就是强耦合的,假如此时我们不需要这个功能了,或者想换成其他功能,那么就必须一个个修改。

通过代理模式,可以在指定位置执行对应流程。这样就可以将一些横向的功能抽离出来形成一个独立的模块,然后 在指定位置插入这些功能。这样的思想,被称为面向切面编程,即AOP。

3.4.2 第二个栗子(装饰器模式解决)

第二个栗子:日志处理带来的问题

1.日志处理带来的问题

​ 我们有一个Pay(接口)然后两个实现类DollarPay和RmbPay,都需要重写pay()方法, 这时我们需要对pay方法进行性能监控,日志的添加等等怎么做?

2.最容易想到的方法

对每个字符方法均做日志代码的编写处理,如下面方式

缺点:代码重复太多,添加的日志代码耦合度太高(如果需要更改日志记录代码功能需求,类中方法需要全部改动,工程量浩大)

可以使用装饰器模式/代理模式改进解决方案

  • 装饰器模式:动态地给一个对象添加一些额外的职能
  • 代理模式:在不影响用户行为的前提下,做用户行为的增强,可以看3.3.1节。可以得出以下结构

​ 仔细考虑过后发现虽然对原有内部代码没有进行改动,对于每个类做日志处理,并引用目标类,但是如果待添加日志的业务类的数量很多,此时手动为每个业务类实现-个装饰器或创建对应的代理类,同时代码的耦合度也加大,需求一旦改变,改动的工程量也是可想而知的。

有没有更好的解决方案,只要写一次代码,对想要添加日志记录的地方能够实现代码的复用,达到松耦合的同时,又能够完美完成功能?

​ 答案是肯定的,存在这样的技术,aop已经对其提供了完美的实现!

AOP要做的事情就是将重复的实现功能代码提取出来,并在所有需要用的地方都可以去使用它


3.4.3 AOP的特点 3.4.3.1 什么是AOP

​ Aspect Oriented Programing 面向切面编程,相比较oop面向对象编程来说,Aop关注的不再是程序代码中某个类,某些方法,而aop考虑的更多的是一种面到面的切入,即层与层之间的一种切入,所以称之为切面。联想大家吃的汉堡(中间夹肉)。那么aop是怎么做到拦截整个面的功能呢?考虑前面学到的servlet filter @Component//表示将任意对象交给IOC容器处理 @Aspect public class LogCut { @Pointcut("execution(* com.fx.service..*.*(..))") public void cut(){ } }

声明前置通知、返回通知、异常抛出通知、最终通知、环绕通知、

  • @Before:前置通知
  • @AfterReturning:返回通知
  • @AfterThrowing:异常抛出通知
  • @After:最终通知
  • @Around:环绕通知
	
    @Before(value = "cut()")
    public void before(){
        System.out.println("前置通知...");
    }

    
    @AfterReturning(value = "cut()")
    public void afterReturn(){
        System.out.println("返回通知...");
    }

    
    @After(value = "cut()")
    public void after(){
        System.out.println("最终通知...");
    }

    
    @AfterThrowing(value = "cut()")
    public void afterThrow(){
        System.out.println("发生异常后执行的通知...");
    }

    
    @Around(value = "cut()")
    public Object around(ProceedingJoinPoint pjp){
        System.out.println("环绕里的前置通知...");
        Object obj=null;

        try {
        	//显示的去调用对应的方法
            obj=pjp.proceed();
            System.out.println(pjp.getTarget());
            System.out.println("环绕通知里的返回通知...");
        } catch (Throwable throwable) {
            throwable.printStackTrace();
            System.out.println("环绕通知里的异常通知...");
        }
        System.out.println("环绕通知中的最终通知...");
        return obj;
    }

在xml文件中配置AOP代理

    
    
3.4.5.3 xml实现AOP

欠着欠着 xml实现AOP

3.4.5.4 Spring AOP总结
  1. 代理模式实现三要素
    1.1 接口定义

    1.2 目标对象与代理对象必须实现统一接口

    1.3 代理对象持有目标对象的引用增强目标对象行为

  2. 代理模式实现分类以及对应区别
    2.1 静态代理:手动为目标对象制作代理对象,即在程序编译阶段完成代理对象的创建

    2.2 动态代理:在程序运行期动态创建目标对象对应代理对象。

    2.3 jdk动态代理:被代理目标对象必须实现某一-或某一 组接口实现方式通过回调创建代理对象。

    2.4 cglib动态代理:被代理目标对象可以不必实现接口,继承的方式实现。

    动态代理相比较静态代理,提高开发效率,可以批量化创建代理,提高代码复用率。

  3. Aop理解

    3.1 面向切面,相比oop关注的是代码中的层或面

    3.2 解耦,提高系统扩展性 3.提高代码复用.

    3.3 提高代码的复用率

  4. AOP关键字

    1.连接点:每一个方法

    2.切入点:匹配的方法集合

    3.切面:连接点与切入点的集合决定了切面,横切关注点的抽象

    4.通知:五种通知(前置、返回、异常、最终、环绕)

    5.目标对象:被代理对象

    6.织入:程序运行期将切面应用到目标对象并生成代理对象的过程

    7.引入:在不修改原始代码情况下,在程序运行期为程序动态引入方法或字段的过程

4. Spring MVC 4.1 知识点概览

思维导图:


4.2 MVC思想&SpringMVC框架概念与特点 4.2.1 什么是MVC?

​ 模型-视图-控制器(MVC) 是一个众所周知的以设计界面应用程序为基础的设计思想。它主要通过分离模型、视图及控制器在应用程序中

的角色将业务逻辑从界面中解耦。通常,模型负责封装应用程序数据在视图层展示。视图仅仅只是展示这些数据,不包含任何业务逻辑。

控制器负责接收来自用户的请求,并调用后台服务(service或者dao)来处理业务逻辑。处理后,后台业务层可能会返回了- -些数据在视图

层展示。控制器收集这些数据及准备模型在视图层展示。MVC模式的核心思想是将业务逻辑从界面中分离出来,允许它们单独改变而不会相互影响。

4.2.2 常见MVC框架开发效率比较

Jsp+servlet > struts1 > spring mvc > struts2+freemarker > struts2,ognl,值栈。

​ 开发效率上,基本正好相反。值得强调的是,spring mvc开发效率和struts2不相上下,但从目前来看,springmvc的流行度已远远超过

struts2。

4.2.3 SpringMVC是什么?

​ Spring MVC是Spring家族中的一个web成员,它是一种基于Java的实现了Web MVC设计思想的请求驱动类型的轻量级Web框架,即

使用了MVC架构模式的思想,将web层进行职责解耦,基于请求驱动指的就是使用请求-响应模型,框架的目的就是帮助我们简化开

发,Spring MVC也是要简化我们日常Web开发的。Spring MVC是服务到工作者思想的实现。前端控制器是DispatcherServlet;

应用控制器拆为处理器映射器(Handler Mapping)进行处理器管理和视图解析器(View Resolver)进行视图管理;支持本地化/国际化(Locale)

解析及文件上传等;提供了非常灵活的数据验证、格式化和数据绑定机制;提供了强大的约定大于配置(惯例优先原则)的契约式编程支持。

4.2.4 SpringMVC能帮我们做什么?
  1. 让我们能非常简单的设计出干净的Web层;
  2. 进行更简洁的Web层的开发;
  3. 天生与Spring框架集成(如IoC容器、 AOP等) ;
  4. 提供强大的约定大于配置的契约式编程支持;
  5. 能简单的进行Web层的单元测试;
  6. 支持灵活的URL到页面控制器的映射;
  7. 非常容易与其他视图技术集成,如jsp、 Velocity、 FreeMarker等等 ,因为模型数据不放在特定的API里,而是放在一个Model里(Map数据结构实现,因此很容易被其他框架使用) ;
  8. 非常灵活的数据验证、格式化和数据绑定机制,能使用任何对象进行数据绑定,不必实现特定框架的API;
  9. 支持灵活的本地化等解析;
  10. 更加简单的异常处理;
  11. 对静态资源的支持
  12. 支持Restful风格。

4.3 SpringMVC请求流程&环境搭建 4.3.1 SpringMVC请求处理流程分析

​ Spring MVC框架也是一个基于请求驱动的Web框架,并且使用了前端控制器模式(是用来提供一个集中的请求处理机制,所有的请求都

将由一一个单一的处理程序处理来进行设计,再根据请求映射规则分发给相应的页面控制器(动作/处理器)进行处理。首先让我们整体看一下

Spring MVC处理请求的流程:

  1. 首先用户发送请求,请求被SpringMvc前端控制器(DispatherServlet) 捕获;

  2. 前端控制器(DispatherServlet)对请求URL解析获取请求URI,根据URI,调用HandlerMapping;

  3. 前端控制器(DispatherServlet)获得返回的HandlerExecutionChain (包括Handler对象以及 Handler对象对应
    的拦截器) ;

  4. DispatcherServlet根据获得的HandlerExecutionChain,选择-个合适的HandlerAdapter。(附注: 如果成
    功获得HandlerAdapter后,此时将开始执行拦截器的preHandrlr…)方法) ;

  5. HandlerAdapter根据请求的Handler适配并执行对应的Handler; HandlerAdapter(提取Request中的模型数
    据,填充Handler入参,开始执行Handler (Controller)。 在填充Handler的入参过程中, 根据配置,Spring
    将做一些额外的工作:

HttpMessageConveter:将请求消息(如Json. xml等数据)转换成一个对象, 将对象转换为指定的响应信息。

数据转换:对请求消息进行数据转换。如String转换成Integer. Double等数据格式化:

数据格式化。如将字符串转换成格式数字或格式化日期等

数据验证:验证数据的有效性(长度、格式等) , 验证结果存储到BindingResult或Error中)

  1. Handler执行完毕,返回一-个ModelAndView(即模型和视图)给HandlerAdaptor

  2. HandlerAdaptor适配器将执行结果ModelAndView返回给前端控制器。

  3. 前端控制器接收到ModelAndView后,请求对应的视图解析器。

  4. 视图解析器解析ModelAndView后返回对应View;

  5. 渲染视图并返回渲染后的视图给前端控制器。

  6. 最终前端控制器将渲染后的页面响应给用户或客户端


4.4 Spring MVC环境搭建 4.4.1 开发环境

idea+Maven+Jdk1.8+Jetty

4.4.2 pom.xml坐标添加
	
    
    
      org.springframework
      spring-web
      5.3.9
    

    
    
    
      org.springframework
      spring-webmvc
      5.3.9
    

    
    
    
      javax.servlet
      javax.servlet-api
      3.1.0
      provided
    

插件:

	
      
      
        org.apache.maven.plugins
        maven-compiler-plugin
        2.3.2
        
          1.8
          1.8
          UTF-8
        
      

      
      
        org.eclipse.jetty
        jetty-maven-plugin
        9.4.27.v20200227
        
          10
          
          
            8080
          
          
          
            /springMVC1001
          
        
      

    
4.4.3 配置web.xml


  
  
    char encoding filter
    encodingFilter
    org.springframework.web.filter.CharacterEncodingFilter
    
      encoding
      UTF-8
    
  
  
    encodingFilter
    
@Controller
public class HelloController {
    
    @RequestMapping("/hello")
    public ModelAndView hello(){
        ModelAndView modelAndView = new ModelAndView();
        //设置数据
        modelAndView.addObject("hello","hello SpringMVC");
        //设置视图名称
        modelAndView.setViewName("hello");
        //返回
        return modelAndView;
    }
}
4.5 URL地址映射配置&参数绑定 4.5.1 URL地址映射配置之@RequestMapping

​ 通过注解@RequestMapping将请求地址与方法进行绑定,可以在类级别和方法级别声明。类级别的注解负
责将一个特定的请求路径映射到一个控制器上,将url和类绑定;通过方法级别的注解可以细化映射,能够将一个
特定的请求路径映射到某个具体的方法上,将url和类的方法绑定。

4.5.1.1 映射单个URL

@RequestMapping("/请求路径")

@Controller
public class URLController {
    
    @RequestMapping("/test01")
    public ModelAndView test01(){
        ModelAndView modelAndView = new ModelAndView();
        //可以在resources目录下配置key
        modelAndView.addObject("hello","test01");
        //设置视图
        modelAndView.setViewName("hello");
        return modelAndView;
    }

    
    @RequestMapping("test02")
    public ModelAndView test02(){
        ModelAndView modelAndView = new ModelAndView();
        //可以在resources目录下配置key
        modelAndView.addObject("hello","test02");
        //设置视图
        modelAndView.setViewName("hello");
        return modelAndView;
    }
}
4.5.1.2 映射多个URL

实质上是访问一个数组:@RequestMapping({"/访问路径一","/访问路径二"})

	
    @RequestMapping({"/test03_01","/test03_02"})
    public ModelAndView test03(){
        ModelAndView modelAndView = new ModelAndView();
        //可以在resources目录下配置key
        modelAndView.addObject("hello","test03");
        //设置视图
        modelAndView.setViewName("hello");
        return modelAndView;
    }
4.5.1.3 映射URL在控制器上

用于类上,表示类中的所有响应请求的方法都是以改地址作为父路径

栗子中的访问地址变为:http://localhost:8080/springMVC1001/url/test01

@Controller
@RequestMapping("/url")
public class URLController {
    
    @RequestMapping("/test01")
    public ModelAndView test01(){
        ModelAndView modelAndView = new ModelAndView();
        //可以在resources目录下配置key
        modelAndView.addObject("hello","test01");
        //设置视图
        modelAndView.setViewName("hello");
        return modelAndView;
    }
}
4.5.1.4 设置URL映射的请求方式

​ 默认没有设置请求方式,在HTTP请求中最常用的请求方法是GET、POST,还有其他的一些方法,如:DELET、PUT、HEAD等

可以通过method属性设置支持的请求方式,如method=RequestMethod.POST;如设置多种请求方式,以大括号包围,逗号隔开即可

	
    @RequestMapping(value = "/test05",method = RequestMethod.POST)
    public ModelAndView test05(){
        ModelAndView modelAndView = new ModelAndView();
        //可以在resources目录下配置key
        modelAndView.addObject("hello","test05");
        //设置视图
        modelAndView.setViewName("hello");
        return modelAndView;
    }
4.5.1.5 通过参数名称映射URL

访问路径:http://localhost:8080/springMVC1001/url?test06

	
    @RequestMapping(params = "test06")
    public ModelAndView test06(){
        ModelAndView modelAndView = new ModelAndView();
        //可以在resources目录下配置key
        modelAndView.addObject("hello","test06");
        //设置视图
        modelAndView.setViewName("hello");
        return modelAndView;
    }
4.5.2 参数绑定 4.5.2.1 基本数据类型

基本数据类型

@RequestParam注解注解的使用

	
    @RequestMapping("/data01")//给一个映射的地址
    public void data01(int age,double money){
        System.out.println("age="+age+"money="+money);
    }

    
    @RequestMapping("/data02")
    public void data02(@RequestParam(defaultValue = "18") int age,
                       @RequestParam(defaultValue = "25.5") double money){
        System.out.println("age="+age+",money="+money);
    }

    
    @RequestMapping("/data03")
    public void data03(@RequestParam(defaultValue = "18",name = "userAge") int age,
                       @RequestParam(defaultValue = "25.5",name="userMoney") double money){
        System.out.println("age="+age+",money="+money);
    }
4.5.2.2 包装数据类型

包装类的默认值为null,可以避免请求参数为空时报500异常的情况

	
    @RequestMapping("/data04")
    public void data04(Integer age,Double money){
        System.out.println("age="+age+",money="+money);
    }
4.5.2.3 字符串类型
	
    @RequestMapping("/data05")
    public void data05(String UserName,String UserPwd){
        System.out.println("UserName="+UserName+",UserPwd="+UserPwd);
    }
4.5.2.4 数组类型
	
    @RequestMapping("/data06")
    public void data06(String[] hobbys){
        System.out.println(Arrays.toString(hobbys));
    }
4.5.2.5 JavaBean类型
	
    @RequestMapping("/data07")
    public void data07(User user){
        System.out.println(user.toString());
    }
4.5.2.6 List集合

此时User实体需要定义对应list属性(对于集合的参数绑定,一般需要使用JavaBean对象进行包装)

Java控制器代码:

	
    @RequestMapping("/data08")
    public void data08(User user){
        System.out.println(user.toString());
    }

JSP代码:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>


    List集合数据绑定


    

Javabean代码:

public class User {
    //优先使用包装类型,防止接收为null参数时报异常
    private Integer id;
    private String UserName;
    private String UserPwd;
    private List ids;
    private List phoneList;
  	...提供构造器、setter&getter方法、toString方法
}

public class Phone {
    private String num;
	...提供构造器、setter&getter方法、toString方法
}
4.5.2.7 Set集合

和上面的List类似,只是Set集合不允许有重复元素出现

4.5.2.8 Map类型

Map最为灵活,它也需要绑定在对象上,而不能直接写在Controller方法的参数上

			<%--Map集合--%>
            
            
            
4.5.3 请求域对象

请求域对象一共有五种

  1. ModelAndView
  2. Model
  3. ModelMap
  4. Map
  5. HttpServletRequest
@Controller
public class ModelController {

    @RequestMapping("/model01")
    public ModelAndView model01(){
        ModelAndView modelAndView = new ModelAndView();
        //设置数据模型(请求域对象的数据)
        modelAndView.addObject("hell0","hello model01");
        //设置视图
        modelAndView.setViewName("hello");
        //返回modelAndView
        return modelAndView;
    }

    
    @RequestMapping("/model02")
    public String model02(ModelMap modelMap){
        //设置请求域对象
        modelMap.addAttribute("hello","hello model02");
        //返回视图
        return "hello";
    }

    
    @RequestMapping("/model03")
    public String model03(Model model){
        //设置请求域对象
        model.addAttribute("hello","hello model03");
        //返回视图
        return "hello";
    }

    
    @RequestMapping("/model04")
    public String model04(Map map){
        //设置请求域对象
        map.put("hello","hello Model04");
        //返回视图
        return "hello";
    }


    
    @RequestMapping("/model05")
    public String model05(HttpServletRequest request){
        //设置请求域对象
        request.setAttribute("hello","hello Model05");
        //返回视图
        return "hello";
    }
}

4.6 请求转发与重定向的问题

SpringMVC默认采用服务器内部转发的形式展示页面信息。同样也支持重定向页面

4.6.1 重定向

重定向是发一个302的状态码给浏览器,浏览器自己去请求跳转的网页。地址栏会发生改变。

重定向以redirect:开头

@Controller
public class ViewController {
    
    @RequestMapping("/view01")
     public String view01(){
         return "redirect:view.jsp";
     }

    
    @RequestMapping("/view02")
     public String view02(){
         return "redirect:view.jsp?uname=zhangsan&upwd=123456";
     }

    
    @RequestMapping("/view04")
     public String view04(RedirectAttributes attributes){
        //设置参数
        attributes.addAttribute("uname","张三");
        attributes.addAttribute("upwd","123456");
        attributes.addAttribute("hobby","篮球");
        return "redirect:view.jsp";
     }

    
     @RequestMapping("/view05")
     public ModelAndView view05(ModelAndView modelAndView){
        //设置参数
         modelAndView.addObject("uname","张三");
         modelAndView.addObject("upwd","123456");
         modelAndView.addObject("hobby","篮球");
         //设置视图
         modelAndView.setViewName("redirect:view.jsp");
         return modelAndView;
     }

    
     @RequestMapping("/view06")
     public ModelAndView view06(ModelAndView modelAndView){
        //设置参数
         modelAndView.addObject("uname","张三");
         modelAndView.addObject("upwd","123456");
         modelAndView.addObject("hobby","篮球");
         //设置视图
         modelAndView.setViewName("redirect:test");
         return modelAndView;
     }


}

请求转发用forward:开头

 @RequestMapping("/view07")
 public String view07(){
    return "forward:view.jsp";
 }


 @RequestMapping("/view08")
 public String view8(){
    return "forward:view.jsp?uname=张三&upwd=123";
 }


 @RequestMapping("/view09")
 public String view9(Model model){
     model.addAttribute("name","管理员");
    return "forward:view.jsp?uname=张三&upwd=123";
 }



 @RequestMapping("/view10")
 public String view10(Model model){
     model.addAttribute("name","管理员");
     return "../../view";
 }


 @RequestMapping("/view11")
 public ModelAndView view11(ModelAndView modelAndView){
     modelAndView.setViewName("forward:test");
     return modelAndView;
 }


 @RequestMapping("/view12")
 public ModelAndView view12(ModelAndView modelAndView){
     modelAndView.setViewName("forward:test?uname=张三&upwd=123456");
     return modelAndView;
 }
4.6.2 请求转发

请求转发在浏览器中是一个默认的方式(浏览器中地址不发生改变)

请求转发,直接调用跳转的页面,让它返回。对于浏览器来说,它无法感觉服务器有没有forward。地址栏不发生改变。可以获取请求域中的数据。

请求转发以forward:开头

4.7 SpringMVC之JSON数据开发 4.7.1 基本概念

​ Json在企业开发中已经作为通用的接口参数类型,在页面(客户端)解析很方便。SpringMVC对于jsor提供
了良好的支持,这里需要修改相关配置,添加json 数据支持功能

4.7.1.1 @ResponseBody简介

该注解用于将Controller的方法返回的对象,通过适当的 HttpMessageConverter转换为指定格式后,写入到 Response对象的body 数据区。
返回的数据不是 html标签的页面,而是其他某种格式的数据时(如json、xml等)使用(通常用于ajax请求)

4.7.1.2 @RequestBody简介

该注解用于读取Request请求的body部分数据,使用系统默认配置的HttpMessageConverter进行解析,然后把相应的数据绑定到要返回的对象上,再把 HttpMessageConverter返回的对象数据绑定到controller中方法的参数上。

4.7.2 使用配置 4.7.2.1 在pom.xml中添加json坐标

pom.xml添加json坐标


    com.fasterxml.jackson.core
    jackson-core
    2.12.3



    com.fasterxml.jackson.core
    jackson-databind
    2.12.4



    com.fasterxml.jackson.core
    jackson-annotations
    2.12.3


4.7.4.2 修改resources目录下的xml配置文件

    
	
        
            
            
        
    
4.7.3 注解使用 4.7.3.1 @ResponseBody
	
    @RequestMapping("/query01")
    @ResponseBody
    public User queryUser01(){
        User user=new User();
        user.setId(1);
        user.setUserName("张三");
        user.setUserPwd("123456");
        //返回User对象
        return user;
    }

    // @ResponseBody也可以设置在方法返回值的前面
    @RequestMapping("/query02")
    public @ResponseBody User queryUser02(){
        User user=new User();
        user.setId(2);
        user.setUserName("李四");
        user.setUserPwd("123456");
        //返回User对象
        return user;
    }

    @RequestMapping("/query03")
    public @ResponseBody List queryUser03(){
        List list=new ArrayList<>();
        User user=new User();
        user.setId(2);
        user.setUserName("李四");
        user.setUserPwd("123456");

        User user02=new User();
        user02.setId(1);
        user02.setUserName("张三");
        user02.setUserPwd("123456");

        list.add(user);
        list.add(user02);
        //返回User对象
        return list;
    }

    
    @RequestMapping("/query04")
    @ResponseBody
    public User queryUser04(){
        User user=new User();
        user.setId(3);
        user.setUserName("张三");
        user.setUserPwd("123456");
        //返回User对象
        return user;
    }
4.7.3.2 @RequestBody

​ @RequestBody注解常用来处理content-type 不是默认的application/x-www-form-urlcoded类型的内容.

比如说: application/json或者是application/xml等。一般情况下来说常用其来处理application/json类型。@RequestBody接受的是一个

json格式的字符串,一定是一个字符串。通过@RequestBody可以将请求体中的JSON字符串绑定到相应的bean上,当然,也可以将其分

别绑定到对应的字符串上。

java代码:

	
    @RequestMapping("/query05")
    @ResponseBody
    public User queryUser05(@RequestBody User user){
        System.out.println(user);
        return user;
    }

jsp文件配置:



4.8 课程总结&SpringMVC常用注解

@Controller
负责注册一个bean 到spring 上下文中。
@Service
声明Service组件,例如@Service(“myMovieLister”)
@Repository
声明Dao组件。
@Component
泛指组件, 当不好归类时使用此注解。
@Resource
用于注入,( j2ee提供的 ) 默认按名称装配,@Resource(name=“beanName”) 。
@Autowired
用于注入,(srping提供的) 默认按类型装配 。
@Transactional( rollbackFor={Exception.class})
事务管理。
@Scope(“prototype”)
设定bean的作用域。
@RequestMapping
注解为控制器指定可以处理哪些 URL 请求。
@RequestBody
该注解用于读取Request请求的body部分数据,使用系统默认配置的HttpMessageConverter进行解析,然后把相应的数据绑定到要返回的对象上 ,再把HttpMessageConverter返回的对象数据绑定到 controller中方法的参数上。
@ResponseBody
该注解用于将Controller的方法返回的对象,通过适当的HttpMessageConverter转换为指定格式后,写入到Response对象的body数据区。
@ModelAttribute    
在方法定义上使用 @ModelAttribute 注解:Spring MVC 在调用目标处理方法前,会先逐个调用在方法级上标注了@ModelAttribute 的方法。
在方法的入参前使用 @ModelAttribute 注解:可以从隐含对象中获取隐含的模型数据中获取对象,再将请求参数 –绑定到对象中,再传入入参将方法入参对象添加到模型中 。
@RequestParam 
在处理方法入参处使用 @RequestParam 可以把请求参 数传递给请求方法。
@PathVariable
绑定 URL 占位符到入参。
@ExceptionHandler
注解到方法上,出现异常时会执行该方法。
@ControllerAdvice
使一个Contoller成为全局的异常处理类,类中用@ExceptionHandler方法注解的方法可以处理所有Controller发生的异常。

(){
List list=new ArrayList<>();
User user=new User();
user.setId(2);
user.setUserName(“李四”);
user.setUserPwd(“123456”);

    User user02=new User();
    user02.setId(1);
    user02.setUserName("张三");
    user02.setUserPwd("123456");

    list.add(user);
    list.add(user02);
    //返回User对象
    return list;
}


@RequestMapping("/query04")
@ResponseBody
public User queryUser04(){
    User user=new User();
    user.setId(3);
    user.setUserName("张三");
    user.setUserPwd("123456");
    //返回User对象
    return user;
}


##### 4.7.3.2 @RequestBody

​	@RequestBody注解常用来处理content-type **不是默认的application/x-www-form-urlcoded**类型的内容.

比如说: application/json或者是application/xml等。一般情况下来说常用其来处理application/json类型。@RequestBody接受的是一个

json格式的字符串,一定是一个字符串。通过@RequestBody可以将请求体中的JSON字符串绑定到相应的bean上,当然,也可以将其分

别绑定到对应的字符串上。

java代码:

```java
	
    @RequestMapping("/query05")
    @ResponseBody
    public User queryUser05(@RequestBody User user){
        System.out.println(user);
        return user;
    }

jsp文件配置:



4.8 课程总结&SpringMVC常用注解

@Controller
负责注册一个bean 到spring 上下文中。
@Service
声明Service组件,例如@Service(“myMovieLister”)
@Repository
声明Dao组件。
@Component
泛指组件, 当不好归类时使用此注解。
@Resource
用于注入,( j2ee提供的 ) 默认按名称装配,@Resource(name=“beanName”) 。
@Autowired
用于注入,(srping提供的) 默认按类型装配 。
@Transactional( rollbackFor={Exception.class})
事务管理。
@Scope(“prototype”)
设定bean的作用域。
@RequestMapping
注解为控制器指定可以处理哪些 URL 请求。
@RequestBody
该注解用于读取Request请求的body部分数据,使用系统默认配置的HttpMessageConverter进行解析,然后把相应的数据绑定到要返回的对象上 ,再把HttpMessageConverter返回的对象数据绑定到 controller中方法的参数上。
@ResponseBody
该注解用于将Controller的方法返回的对象,通过适当的HttpMessageConverter转换为指定格式后,写入到Response对象的body数据区。
@ModelAttribute    
在方法定义上使用 @ModelAttribute 注解:Spring MVC 在调用目标处理方法前,会先逐个调用在方法级上标注了@ModelAttribute 的方法。
在方法的入参前使用 @ModelAttribute 注解:可以从隐含对象中获取隐含的模型数据中获取对象,再将请求参数 –绑定到对象中,再传入入参将方法入参对象添加到模型中 。
@RequestParam 
在处理方法入参处使用 @RequestParam 可以把请求参 数传递给请求方法。
@PathVariable
绑定 URL 占位符到入参。
@ExceptionHandler
注解到方法上,出现异常时会执行该方法。
@ControllerAdvice
使一个Contoller成为全局的异常处理类,类中用@ExceptionHandler方法注解的方法可以处理所有Controller发生的异常。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/340575.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号