SpringMvc快速学习笔记

前言

本篇是快速学习而非深度学习,知识点可能讲的不充分,在保证前置知识掌握扎实的情况下可以学习本篇

第一章 什么是springMvc?

SpringMvc是一个表述层框架是对Servlet的封装。基于Spring框架完成的,继承了高性能的优点,从一开始就包含在Spring Framework中。他的优点如下:

  • Spring 家族原生产品,与IOC容器等基础设施无缝对接
  • 表述层各细分领域需要解决的问题全方位覆盖 ,提供全面解决方案
  • 代码清新简洁,大幅度提升开发效率
  • 内部组件化程度高,可插拔式组件即插即用,想要什么功能配置相应组件即可
  • 性能卓著,尤其适合现代大型、超大型互联网项目要求

为什么SpringMvc?

我们看一段代码,直观的感受一下相比于原生的Servlet开发,SpringMvc给我们带来的便利。

java 复制代码
protected void doGet(HttpServletRequest request, HttpServletResponse response) 
                                                        throws ServletException, IOException {  
    String userName = request.getParameter("userName");
    
    System.out.println("userName="+userName);
}
less 复制代码
@RequestMapping("/user/login")
public String login(@RequestParam("userName") String userName,Sting password){
    
    log.debug("userName="+userName);
    //调用业务即可
    
    return "result";
}
  1. 我们通过@RequestMapping注解直接指定是对哪些请求的映射

  2. 通过@RequestParam直接将请求中的用户名或其他属性赋值给我们的参数 。根本不需要像上面那样繁琐的步骤重写doGet方法一步步去取出来,我们可以将更多的精力放在对业务逻辑的编写上


见一叶落,而知岁之将暮;睹一壶之冰,而知天下之寒:以近论远。

这样看来,SpringMvc的代码简洁程度与强大不言而喻!

上面我们看到SpringMvc简化了对前端参数的接收,同时也简化了对前端数据的响应,后面我们会详细讲。


第二章 SpringMVc如何工作?


我们把整个后端想象成一个向外提供服务的公司,而Controller-》Service-》dao三层组成了生产部(真正产出服务的人) 。而公司的组成绝对不止生产部这么简单,因为再好的东西也需要跟外部建立联系并将他们销售出去 ,这样才能实现它真正的价值。而SpringMvc则承接了其余全部的工作


公司的CEO ---- DispatcherServlet

DispatcherServlet承接了外部所有的订单 (请求),他主要负责与外部建立联系,并将请求交给不同的部门来处理,并将最终结果返还给客户

公司的秘书 ---- HandlerMapping

HandlerMapping会承接来自CEO的任务,根据提供的请求路径 去寻找有没有指定的员工(Handler)可以生产出客户想要的商品。并将相关的结果返回给CEO

公司的经理 ---- HandlerAdapter

我们发现,到目前为止,员工还没有开始工作,因为还没有收到详细的订单信息(前端请求的参数) ,而HandlerAdapter就是负责将CEO提供的客户详细需求(request对象)简化成员工工作所需要知道的部分(方法的请求参数),当员工工作完成后,将返回的结果封装进客户所需要的礼盒(response对象)里,然后返回给CEO。

公司的财务 ---- viewResolver

从上面看,似乎我们已经完成了所有的工作。但别忘了,用户可能会请求一些静态的资源(如html,图片)。而视图解析器内部则是一大堆的路径前缀和后缀。他会把CEO送来的路径片段(其实是HandlerAdapter手下的Controller提供的)封装成真实的路径,然后去寻找对应的静态资源,并将他们返回给CEO。当然这一步并非是必须的,也有可能根本不会走这一步。

图解关系组成

我们需要做什么?

  1. 使用web.xml配置DispatcherServlet让他生效,它是核心,所有的请求都经由他手处理和转发
  2. HandlerMapping,我们需要配置它并放入IOC容器中,使他生效
  3. HandlerAdapter,我们需要配置它并放入IOC容器中,使他生效
  4. Handler,写我们的业务逻辑。
  5. ViewResolve,同样需要配置它并放入IOC容器中,使他生效。(前后端分离的项目不需要后端返回页面,无需配置)

快速上手SpringMvc

创建一个父项目并将它设置为聚合项目pom,并引入以下依赖。(记得改一下maven设置)

xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.atguigu</groupId>
    <artifactId>SpringMvc6</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>pom</packaging>
    <modules>
        <module>pro-01</module>
    </modules>
    <properties>
        <spring.version>6.0.8</spring.version>
        <servlet.api.version>9.1.0</servlet.api.version>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <!-- web相关依赖  -->
        <!-- 在 pom.xml 中引入 Jakarta EE Web API 的依赖 -->
        <!--
            在 Spring Web MVC 6 中,Servlet API 迁移到了 Jakarta EE API,因此在配置 DispatcherServlet 时需要使用
             Jakarta EE 提供的相应类库和命名空间。错误信息 "'org.springframework.web.servlet.DispatcherServlet'
             is not assignable to 'javax.servlet.Servlet,jakarta.servlet.Servlet'" 表明你使用了旧版本的
             Servlet API,没有更新到 Jakarta EE 规范。
        -->
        <dependency>
            <groupId>jakarta.platform</groupId>
            <artifactId>jakarta.jakartaee-web-api</artifactId>
            <version>${servlet.api.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${spring.version}</version>
        </dependency>
    </dependencies>

</project>

创建子项目并将其改成web项目

本步骤演示如何将普通项目转换为web项目

  1. 点击项目右击F4或右击选择Open Module Setting,打开模块设置
  2. 点击加号添加web模块

3. 修改上下两个路径,把要添加的web文件夹以及相关内容全部改到模块下的src\main\文件夹下。

4. 保存后生效。

创建测试用Controller

less 复制代码
@Controller
public class helloController {

    //该方法返回一个JSON字符串,内容为 hello SpringMvc
    @RequestMapping("spring/helloController")
    @ResponseBody
    public String helloController(){
        System.out.println("helloController.helloController");


        return "hello SpringMvc";
    }
}

将秘书与经理放入IOC并配置CEO

  1. 我们先声明一个配置类

  2. 指定包扫描地址

  3. 我们将HandlerMapping放入IOC,保证SpringMVC中寻找handler路径的模块正常工作

  4. 我们将Adapter放入IOC,保证SpringMVC中简化handler所需参数和封装Response的模块正常工作

typescript 复制代码
//TODO 无需添加Component,因为这些注解内部包含的有
//TODO 在Mvc中,我们无需去自己创建ClassPathXMLApplicationContext自己创建Spring容器
@ComponentScan("com.atguigu")
@Configuration
public class SpringMvcConfig {

    //TODO 把我们的秘书-》handlerMapping放入Spring

    @Bean
    public RequestMappingHandlerMapping requestMappingHandlerMapping(){
        return new RequestMappingHandlerMapping();
    }

    //TODO 把我们的经理-》Adapter放入Spring

    @Bean
    public RequestMappingHandlerAdapter requestMappingHandlerAdapter(){
        return new RequestMappingHandlerAdapter();
    }

}

配置我们的CEO,保证所有请求均由DispatcherServlet来处理

我们需要继承一个初始化抽象类 ,并实现方法找到刚配置的类将所有请求交给它来处理 。我们就不再需要在web.xml中配置DispatcherServlet了。

scala 复制代码
package com.atguigu.Config;

import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;

//TODO 我们这个类存在的意义是为了替代web.xml中手动去配置Servlet
public class SpringMvcInit extends AbstractAnnotationConfigDispatcherServletInitializer {
    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class[0];
    }

    //TODO 指定了这个才能让Spring找到他
    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class[]{SpringMvcConfig.class};
    }

    //TODO 表示我们所有的请求全去找它来处理
    @Override
    protected String[] getServletMappings() {
        return new String[]{"/"};
    }
}

下载安装配置tomcat10

打个war包并导入

手动打包教学

最终测试

tomcat跑起来后路径上加入我们Controller的地址/spring/helloController

解决tomcat控制台乱码

  1. 找到专门管日志的配置文件并打开

  2. 把里面所有的UTF-8换成GBK,这样一来,把转码交给IDEA处理即可

SpringMvc注解详解

1. requestMapping注解以及子注解

① requestMappring用来干嘛的?

requestMapping相当于秘书,用来标记路径指示DispatcherServlet找到指定的方法

② requestMappring的属性

我们主要讲2个属性


value属性

用来填写路径,我们主要有以下几个知识点

  1. 我们对于路径的填写格式相对宽松 ,可以填/user/login,也可以是user/login,又或者是user/login/

  1. 如果我们希望单个方法处理多个请求 ,可以使用{"user/login","user/getName"}的格式来填写
ini 复制代码
@RequestMapping(value = {"user/login","user/getName"})

  1. 使用模糊匹配可以解决某路径下任意子路径的映射
less 复制代码
@RequestMapping(value = "spring/*") 表示spring/任意字符全部配
@RequestMapping(value = "spring/**") 表示spring/任意层级,任意字符全部匹配

  1. 如果requestMapping注解里面没有其他要填写的属性,可以直接省略value关键字
kotlin 复制代码
@RequestMapping("spring/helloController")

method属性

用来定义前端发来的请求类型,spring使用枚举类来存放几个参数

  1. 格式为 method = "RequestMethod.GET"
  2. 如果跟前面的value参数一起写可以试用一下格式
ini 复制代码
@RequestMapping(value = "spring/helloController",method = RequestMethod.GET)

③ RequestMapping注解放在哪?

可以放在类上面简化方法上的路径,假如一个Controller类全部为关于user的映射 ,而且路径全部为/user/????,那我们就可以在类上定义一个@RequestMapping("user"),内部的方法直接拼接即可

④ RequestMapping的子注解

less 复制代码
@GetMapping()
@POSTMapping()
@DeleteMapping()
@PutMapping()

2. RequestParam注解

① RequestParam注解的作用是什么?

RequestParam注解放在请求参数上,把前端请求的参数取出来,赋值给处理方法的参数上,并且提供多种灵活的处理方式

我们来看一组代码

less 复制代码
@GetMapping("user/login")
@ResponseBody()
public String userLogin(String userName, String password){
    System.out.println("userName = " + userName + ", password = " + password);

    return "ok";
}

请求页
http://localhost:8080/user/login?userName=jack&password=10010

在上面的代码中,我们没有使用@RequestParam注解,依然可以正常使用,说明这个@RequestParam注解不是必须的

但是如果没有使用该注解,则必须满足前端请求的参数名与后端处理方法的参数名一致,但是参数是可传可不传的 如果不传,int类型的默认值为0


② RequestParam注解解决一名多值

先看一组代码

less 复制代码
@GetMapping("user/login2")
@ResponseBody()
public String userLogin2(@RequestParam List<String> userName, String password){
    System.out.println("userName = " + userName + ", password = " + password);

    return "ok";
}


请求页
http://localhost:8080/user/login2?userName=jack&userName=lisa&password=10010

如果我们想用List接收参数(userName由多个值组成),则必须使用@RequestParam注解


③ RequestParam注解参数详解

看一下该注解的源码

less 复制代码
@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RequestParam {
    @AliasFor("name")
    String value() default "";

    @AliasFor("value")
    String name() default "";

    boolean required() default true;

    String defaultValue() default "\n\t\t\n\t\t\n\ue000\ue001\ue002\n\t\t\t\t\n";
}

明显可以看到有3个参数

  1. value参数

value参数用来填写前端的请求参数如果前后端的请求参数名不一致,可以使用该参数正确的将前端参数映射给方法参数

  1. require参数

该参数默认是false,表示该参数可传可不传

  1. defaultValue参数

当require参数为true时,可以设置默认参数,当前端没有给出必要的参数时,我们保证代码有兜底


④ 使用对象接收参数

写好pojo,直接指定为参数即可,无需做任何设置,无需使用注解 。但是要求参数名必须与属性名一致

如果要求有默认值,则可以直接写到pojo里面


动态路径传参与@PathVariable注解

① 什么是动态路径传参?

动态路径传参就是不使用传统的param格式传参,而是用/username的值/xxx参数的值,就像下面这个链接,直接传值。这样做接收效率更高

bash 复制代码
http://localhost:8080/user/jack/1234

服务端写法:

less 复制代码
@GetMapping("user/{userName}/{password}")
@ResponseBody()
public String userLogin3(@PathVariable String userName, @PathVariable String password){
    System.out.println("userName = " + userName + ", password = " + password);

    return "ok";
}
  1. 直接用/{???}接收,
  2. 必须使用PathVariable接收

② 相关的参数

直接看源码

less 复制代码
@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface PathVariable {
    @AliasFor("name")
    String value() default "";

    @AliasFor("value")
    String name() default "";

    boolean required() default true;
}
  1. value参数

value参数用来填写前端的请求参数如果前后端的请求参数名不一致,可以使用该参数正确的将前端参数映射给方法参数

  1. require参数

该参数默认是false,表示该参数可传可不传


3. JSON传参与@RequestBody注解

我们尝试让前端传一个JSON串过来,内容为:{"userName":"jack","age":12}

我们使用一个对应的javaBean来接收它:

kotlin 复制代码
package com.atguigu.POJO;


import lombok.Data;

@Data
public class User {
    private String userName;
    private Integer age;
}

@RequestBody注解

RequestBody注解放在参数上面,表示将前端的JSON赋值给该值

用对象接收

less 复制代码
@PostMapping("user/jsonTest")
@ResponseBody()
public String userLogin4(@RequestBody User user){
    System.out.println("user = " + user);

    return "ok";
}

用Map接收

发送方式与对象格式一致

less 复制代码
@PostMapping("user/jsonTest")
@ResponseBody()
public String userLogin4(@RequestBody Map user){
    

    return "ok";
}

用List接收

less 复制代码
@PostMapping("user/jsonTest")
@ResponseBody()
public String userLogin4(@RequestBody List<User> users){
    

    return "ok";
}

JSON传参的问题

下面使用的postMan不会用请移步:PostMan简单使用教学 - 掘金 (juejin.cn)

上面的代码测试后报错如下

报错原因是什么?

这是因为java本身是不支持使用JSON作为参数格式 的,(Spring底层是用java写的

解决方法

  1. 引入JSON相关的依赖。
xml 复制代码
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.15.0</version>
</dependency>
  1. 给我们的经理HandlerAdapter赋能(配置类加上@EableWebMvc),让他能够完成JSON相关的解析工作
kotlin 复制代码
package com.atguigu.Config;

import jakarta.servlet.RequestDispatcher;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;


//TODO 无需添加Component,因为这些注解内部包含的有
//TODO 在Mvc中,我们无需去自己创建ClassPathXMLApplicationContext自己创建Spring容器
//TODO 加上EnableWebMvc 开启Adapter支持JSON
@ComponentScan("com.atguigu")
@Configuration
@EnableWebMvc
public class SpringMvcConfig {

    //TODO 把我们的秘书-》handlerMapping放入Spring

    @Bean
    public RequestMappingHandlerMapping requestMappingHandlerMapping(){
        return new RequestMappingHandlerMapping();
    }

    //TODO 把我们的经理-》Adapter放入Spring

    @Bean
    public RequestMappingHandlerAdapter requestMappingHandlerAdapter(){
        return new RequestMappingHandlerAdapter();
    }

}

好了,正常到这里应该是测试成功了。如果依旧显示上面的报错请移步:手动给java项目打war包 - 掘金 (juejin.cn)


附加知识->关于@EnableWebMvc注解

该注解其实内部不仅给HandlerAdapter增加了JSON处理器,还自动帮我们把经理与秘书放入了IOC容器中 ,所以我们已经不需要手动放入他们了。

我们注释掉它仍然可以运行

less 复制代码
@EnableWebMvc()
@Configuration
@ComponentScan("com.atguigu")
public class SpringMvcConfig{

    //TODO 把我们的秘书-》handlerMapping放入Spring

//    @Bean
//    public RequestMappingHandlerMapping handlerMapping(){
//        return new RequestMappingHandlerMapping();
//    }

    //TODO 把我们的经理-》Adapter放入Spring

//    @Bean
//    public RequestMappingHandlerAdapter handlerAdapter(){
//        return new RequestMappingHandlerAdapter();
//    }

}

获取Cookie与SpringMvc的默认数据接收模式

获取Cookie我们需要使用到新的注解:@CookieValue

他的用法如下:

less 复制代码
@RequestMapping("t1/sendCookie")
public String getCookie(@CookieValue("userId") String userId){
    System.out.println("userId = " + userId);
    return "ok!";
}

我们把它加在Handler的参数上,指定要获取的Cookie的kev,就能取到想要的value

当然,如果我们想要获取cookie,需要提前给客户端设置相应的cookie,所以我们需要先让用户请求,并为它设置cookie

typescript 复制代码
@GetMapping("t1/getCookie")
public String setCookie(HttpServletResponse response){
    Cookie userId = new Cookie("userId", "10010");
    response.addCookie(userId);
    return "ok!";
}

SpringMvc的默认数据接收模式

这里我想讨论一个东西,就是我们会发现,在上面的代码中,我们并没有设置任何注解,但是我们仍然可以拿到请求中的HttpServletResponse对象 ,包括像我们最初给大家提供的第一套代码,我们并没有设置任何注解,只需要保证Handler参数与前端发送的请求参数一致,就能取到数据

这是因为HandlerAdapter给我们取到了数据 ,它默认使用Param方式接收参数。一般来讲会有三种接收模式

  1. Param传参
  2. JS传承传参
  3. 动态路径传参

我们会发现,除了第一种默认的Param传参,其他两种都要求必须使用相关注解才能取到参数


获取请求头信息

SpringMvc为我们提供了新的注解@RequestHeader注解,用来取出请求头内的数据 ,他的用法略有不同,我们需要指定要取的是请求头内部的哪一条信息,而非整个请求头

less 复制代码
@RequestMapping("t1/getHeader")
public String getHeader(@RequestHeader(value = "host")String host){
    System.out.println("host = " + host);
    return "host="+host;
}

获取原生对象与3种共享域

还记得我们上面的设置Cookie的代码么?我们直接获取了Response对象,同样,我们获取Request对象的方法也就是直接写上HttpServletRequest即可

简单复习3种共享域

什么是共享域?

共享域是指在Servlet存储数据,方便数据在web应用中共享和访问。常见的作用域有4种。分别是ServletContextHttpServletRequestHttpSessionPageContext

他们的应用范围各不相同,他们其实算是服务端对客户端管理时产生的必要产物,客户端是无法拿到这些会话内部数据的,只是方便服务端操作使用

ServletContext作用域

  1. 它是最大的作用域,可以在整个web应用中使用,也称为Application级作用域

  2. 他里面存放的数据在被各个Handler访问时是线程安全的。

  3. SpringMvc在初始化时就已经把它初始化并放入IOC容器中 了,我们只需要定义它并使用@AutoWired即可

less 复制代码
@Controller
@ResponseBody
public class Controller2 {
    @Autowired
    ServletContext servletContext;

    @GetMapping("t1/getCookie")
    public String setCookie(HttpServletResponse response){
        Cookie userId = new Cookie("userId", "10010");
        response.addCookie(userId);
        return "ok!";
    }

HttpSession作用域

它是范围第二大的作用域,他的实现方法是为每一台客户端建立一个Session会话,并将生成的会话id放到给客户端的Cookie中 ,这样就保证了只要客户端不关闭浏览器,就一直会带上这个cookie ,服务器端依据这个确定客户端是谁,并能找到与其对应的会话

kotlin 复制代码
@RequestMapping("t1/testSession")
public String testSession(HttpSession session){
    //放置参数。。。获取。。删除。。。
    session.setAttribute("jack","jack is happy");
    //获取会话创建时间
    System.out.println(session.getCreationTime());
    //主动让会话失效
    session.invalidate();
    return "ok";
}

HttpServletRequest作用域

相对较小的作用域,其实就是请求对象本身在这次请求中生效,返回后就不复存在了

我们通过它也可以拿到我们的Application作用域哦!

typescript 复制代码
@RequestMapping("t1/testRequest")
public String testRequest(HttpServletRequest request){
    //放置参数。。。获取。。删除。。。
    request.setAttribute("jack","jack is happy");
    request.getServletContext();
    return "ok";
}

@RestController注解

该注解是@Controller与@ResponseBody的组合体,表示该类为Controller,而且内部所有Handler方法的内容全部以JSON格式打包返回。 注意注意,该注解与@RequestMapping注解没有关系!!!!!

RestFul风格

restFul风格是依据Http协议的设计理念延伸出来的一种代码风格。对我们接口的设计做了同一的规范,使接口的设计更简单明确。

简单来讲就是将URI定义为名词,而诉求则使用不同的请求方法来区别。

而请求参数的传递则依据情况来定,非敏感的单个数据尽量使用路径传参,范围数据则使用Param传参,对于请求体或敏感数据则使用JSON传参

RestFul风格不能解决所有问题,一个固定的URI也不可能无限次使用,数量不够时可以使用不同的URI

restFul风格实际演示

less 复制代码
package com.atguigu.Controller;

import com.atguigu.pojo.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@RestController()
@RequestMapping(value = "user",produces = "application/json;charset=utf-8")
public class UserController {

    //TODO 单个数据尽量使用路径传参,并且使用名词定义URI~~
    //TODO get请求用GetMapping
    @GetMapping("/{userid}")
    public User getUserById(@PathVariable() int userid){
        User user = new User();
        user.setId(userid);
        user.setName("jack");
        user.setAge(12);
        return user;
    }

    //TODO 单个数据尽量使用路径传参,并且使用名词定义URI~~
    //TODO delete请求用DeleteMapping
    @DeleteMapping("/{userid}")
    public String deleteUserById(@PathVariable int userid){
        System.out.println("此处省略删除步骤");
        System.out.println("aaaa");
        return "删除成功";
    }

    //TODO 单个数据尽量使用路径传参,并且使用名词定义URI~~
    //TODO delete请求用PutMapping
    @PutMapping("/{userid}")
    public String putUserById(@PathVariable int userid){
        System.out.println("此处省略保存步骤");
        System.out.println("aaaa");
        return "删除成功";
    }

    //TODO 多个数据或范围数据用Param传参
    @GetMapping()
    public List<User> getPage(@RequestParam int page,@RequestParam int size){
        System.out.println("page = " + page + ", size = " + size);
        User user = new User();
        user.setId(1001);
        user.setName("jack");
        user.setAge(12);
        ArrayList<User> users = new ArrayList<>();
        users.add(user);
        return users;
    }

    //TODO 敏感数据用请求体
    @PostMapping
    public String saveUserByIdAndPassword(@RequestBody Map<String,Object> userInfo){
        
        System.out.println(userInfo.get("userName"));
        System.out.println(userInfo.get("password"));
        System.out.println("我省略了更改用户信息~~~~");
        return "ok~";
    }

}

自定义异常处理

Spring使用AOP向我们生成了两个新的注解,它存在的目的是将异常处理从代码中抽取出来,进行更规范统一的处理

  1. 注解@RestControllerAdvice
  2. 注解@ExceptionHandler

@RestControllerAdvice

一般放在类上面。表示该类内部的方法为异常处理方法,当发生异常时,不会优先使用Java的报错,而是进入该类寻找对应的Handler方法来处理异常


@ExceptionHandler

放在对应的处理方法上面,注解内部需要指定对应的异常,表示该异常由该方法进行处理 ,异常处理遵循细化方法作针对处理 ,没有细化的异常处理则会被更大范围的异常处理兜底

代码实战

kotlin 复制代码
package com.atguigu.MyExceptionHandler;

import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(NullPointerException.class)
    public Object nullPointerExceptionHandler(Exception exception){
        System.out.println("空指针异常!!!->报错为"+exception.getMessage());
        return exception.getMessage();
    }


    @ExceptionHandler(Exception.class)
    public Object ExceptionHandler(Exception exception){
        System.out.println("报错啦~~~~~~(大异常)"+exception.getMessage());
        return exception.getMessage();
    }
}

另起一篇(下篇地址)

这东西写多了页面会非常卡,根本写不了。另起一篇来写剩余内容 地址为:

相关推荐
弥琉撒到我3 小时前
微服务swagger解析部署使用全流程
java·微服务·架构·swagger
2401_857622667 小时前
SpringBoot框架下校园资料库的构建与优化
spring boot·后端·php
2402_857589367 小时前
“衣依”服装销售平台:Spring Boot框架的设计与实现
java·spring boot·后端
哎呦没9 小时前
大学生就业招聘:Spring Boot系统的架构分析
java·spring boot·后端
_.Switch9 小时前
Python Web 应用中的 API 网关集成与优化
开发语言·前端·后端·python·架构·log4j
韩楚风10 小时前
【linux 多进程并发】linux进程状态与生命周期各阶段转换,进程状态查看分析,助力高性能优化
linux·服务器·性能优化·架构·gnu
杨哥带你写代码10 小时前
足球青训俱乐部管理:Spring Boot技术驱动
java·spring boot·后端
AskHarries11 小时前
读《show your work》的一点感悟
后端
A尘埃11 小时前
SpringBoot的数据访问
java·spring boot·后端
yang-230711 小时前
端口冲突的解决方案以及SpringBoot自动检测可用端口demo
java·spring boot·后端