Spring核心与MVC笔记

前言

现在已经很少有新项目不使用SpringBoot而使用基础的、原始的Spring框架以及SpringMVC,但SpringBoot又会需要这些“老东西”的概念,故重新整理SpringBoot的“前辈”相关笔记并合并,主要还是对概念的记录。

Spring IOC

IOC意为控制反转,简单理解为将对象的创建(new)行为由程序员转为由容器执行,程序员只需要在任意要用的地方“注入”。

基于注解定义Bean

因为只是记录原理,故不记录如何在配置文件中启用Bean扫描。

因为现在新项目或者有头脑的Leader迁移到SpringBoot之后基本不会去单独使用这原始的Spring。

  • 定义Bean

    • 在类前加上注解@Component, @Service, @Controller, @Repository
      四者功能相同,日后可能不同,并且用于约定区分不同类型的Bean并且用于过滤器过滤。
    • 使用@Scope设定作用域:

      • singleton

        默认的scope,表示单例模式。

      • prototype

        一般的new模式,适合有状态要独立的Bean。

      • request

        类似prototype但只在每个http请求(线程或控制器)中独立的。

      • session

        类似prototype但只在每个会话(线程或控制器)中独立的。

  • 注入

    • 构造函数注入

      类前添加了Bean声明注解的,构造函数会自动注入类所需成员。

    • Setter注入

      在成员的Setter方法前添加@Autowired,将会注入。

    • 直接注入

      在类的成员变量上添加@Autowired或@Resource,将会注入。

  • 参数注入

    • 固定参数注入

      在类成员变量上添加@Value注解

    • 配置文件参数注入

      别问为什么没用也别学

XML配置方式繁杂且基本不会去使用,故不记录

Spring AOP

面向切面编程,简单理解为在某个类的某个方法执行的前、后等时刻基于额外操作,也能够拦截传入的参数。

使用得并不多,但很有用。

基本概念

后面所说的通知类,指通常所说的代理Proxy类

  • 连接点:类中可以被增强(代理)的方法

  • 切入点:实际上被增强的连接点

  • 通知:增强部分的代码

    • 前置通知、后置通知:方法执行前或后的增强
    • 环绕通知:前和后都增强
    • 异常通知:出现异常时处理
    • 最终通知:无论如何都会最后执行的(try后的finally
  • 切面:把通知应用到切入点的过程(织入、执行

基于注解使用AOP

不使用SpringBoot的话,实际上需要在配置文件中开启扫描,忽略同上。

但在SpringBoot中使用AOP要另外引入Starter!

  • 通知类前添加@Aspect注解

    同时,通知类与要增强的类(AOP受体)均要为Bean。

  • 通知方法前加上注解

    注解 用途
    @Before 前置通知,在连接点前执行
    @AfterReturning 连接点正常执行后通知,没有抛出错误时执行
    @AfterThrowing 连接点抛出错误时执行
    @After 无论有没有抛出错误都在连接点结束后执行(finally)
    @Around 在@Before前和没有抛出错误结束后都执行
  • 通知方法的顺序

    @Around前 –>

    @Before –>

    切入点(本体)–>

    @AfterReturning/@AfterThrowing –>

    @Around后

    不同版本可能会有不同

  • 通知的参数语法(切入点选择)

    • execution(* 包.类.方法(参数类型表))
      指定为这个方法
    • execution(* 包.类.*(..两个点表示任意))
      指定为这个类的所有方法
    • execution(* 包..(..))
      指定为这个包下所有类的所有方法(当然也可指定所有类的某个方法
    • execution(* 包...(..))
      在上一个的基础上,一同搜索子包里的
    • execution(* *A(..))
      所有以“A”结尾的方法
    • within(包.*)
      包内的所有接入点,也可双点搜索子包
      Spring AOP Only
    • this/target(接口全路径)
      实现了这个接口的类的接入点
      this: 匹配不到被重写了的接口中的方法
      target: 全部
    • 相关功能注解
      • @Target(注解类)
        同target execution用法
      • @Annotation(注解类)
        所有含有这个注解的方法(接入点)
      • @Within(注解类)
        同this execution用法
      • @Order(优先级,小的优先)
        多个通知同时作用于一个切入点时控制通知链的内部的顺序
    • 抽取公共(复用)切入点
      在通知类中对某个方法使用@Pointcut选择切入点,其他通知的参数写上该方法名

Spring MVC

简化了万恶的Servlet。

原理

工作流程如图:

  1. 当接收到用户的请求时,请求进入到DispatcherServlet进行处理
  2. DispatcherServlet根据请求的URL从HandlerMapping获取映射的处理请求的Bean,也就是Controller
  3. 通过HandlerAdapter调用Controller(应该是适配处理了数据转换),Controller内部处理业务
  4. Controller返回ModelAndView(Model相当于请求响应参数,View是指定要跳转的视图)
  5. ViewResolver根据返回的指定的View(可能没有)进行跳转

配置

同上述IOC、AOP中的情况,SpringMVC配置一样很繁琐,甚至还要依赖web.xml,现在已经没有多少项目使用(就是使用你也不怎么用动配置文件或者百度一下就能轻松知道。

用配置文件配置控制器已经要被扫进垃圾桶辣!

通过注解实现控制器

  • 类加上注解@RestController

    • 相当于@Controller + @ResponseBody
    • @ResponseBody表示这个方法返回的字符串直接写到响应内容
  • 控制器类的每个http接口需要@RequestMapping, @GetMapping, @PostMapping等

返回数据与重定向

  • RestController的return直接返回对应数据给前端
  • 数据与重定向(ModelAndView)

    • 返回值的ModelAndView将Model(给View的数据)和View(指定跳转的视图)返回给DispatcherServlet(经Adapter)
    • ModelAndView通过.addObject()等方法添加参数(类似基本Servlet向请求或响应中setAttribute),通过.setViewName()指定跳转的视图
    • 如果需要Model则在方法参数列表声明(org.springframework.ui.)Model变量
      返回字符串的方法会将Model转发
    • 参数列表的ModelMap
      与Model或ModelAndView相比就是个HashMap和简化出常用方法的区别
  • 直接重定向 (非RestController)
    若没有在XML或配置类中配置ViewResolver,实际上能够在return视图的名称时直接指定,也可以使用前缀指定是转发还是重定向:

    1
    2
    3
    4
    5
    //转发
    return "/your-path/page.jsp";
    return "forward:/sbv/sss.jsp";
    //重定向
    return "redirect:/aaaa.jsp";
    • 转发是指带着请求的参数到下一个地方去
    • 重定向是客户端浏览器自己进行跳转的行为(相当于用户自己重新访问新页面
      重定向无法访问WEB-INF

传入的HTTP参数

  • 一般参数传入,非Restful(…/method?param=value&…)

    • 获取参数

      1
      2
      @RequestMapping("/echo")
      public ModelAndView handleRequest(String msg) throws Exception {}

      中,当使用”…/echo?msg=xxx”访问时能正确获得msg参数。

    • 当url中参数名和方法参数表变量名不一致时,可在方法参数前加@RequesParam(“url中的实际名称”)来指定,如:

      1
      2
      @RequestMapping("/echo")
      public ModelAndView handleRequest(@RequestParam("message") String msg) throws Exception {}

      此时使用”…/echo?message=xxx”访问能正确填充msg。

    • 组成成对象

      当传入的参数可以组成一个类(并且名字与类属性一一对应)时,可以直接把类写到参数,如:

      1
      2
      3
      4
      5
      @RequestMapping("/echo")
      public ModelAndView handleRequest(User user) throws Exception {}
      /*
      User: int id; string name;
      */

      此时使用”…/echo?id=xxx&name=xxx”访问能正确填充user。

  • Restful参数传入

    • HTTP接口方法可在参数列表使用@PathVariable获取url参数。

      @RequestMapping中需要注明参数名像:

      @RequstMapping("/map/{varA}/{varB}")
      然后对参数表中的参数注解如:

      @PathVariable("varA") String bbb

    • 如果RequestMapping中的参数名称和方法参数表得到相同可省略@PathVariable的参数。

    • @RequestMapping中可以指定method为GET/PUT/POST/DELETE,或直接使用@GetMapping/@PostMapping等。


Spring核心与MVC笔记
https://sodacooky.netlify.app/2022/Spring核心与MVC笔记/
作者
Sodacooky
发布于
2022年9月30日
许可协议