Web登录认证-课堂笔记
1. 接收表单参数的时候,如果是日期字符串,服务端接收时需要加注解:@DateTimeFormat(pattern="日期格式")
2. 接收路径变量参数的时候,Controller的方法形参上要加:@PathVariable("")
3. 文件上传:
客户端三要素:
表单提交方式要使用POST
表单form标签上![在这里插入图片描述](https://img-blog.csdnimg.cn/9100f08b5ded409095287e11104f87ff.png#pic_center)
enctype属性值必须是multipart/form-data
表单form标签里边应该有文件选择框,并且必须有name <input type="file" name="表单参数名"/>
服务端要接收文件参数:
要使用MultipartFile类型接收文件数据
文件的存储:
可以存储到服务器本地磁盘上
1. 先重命名文件:
获取原始文件名:multipartFile.getOriginalFilename()
截取得到后缀名
拼接一个随机字符串:UUID.randomUUID().toString() + 文件后缀名
2. 再把文件保存到磁盘上
multipartFile.transferTo(new File("文件路径"));
可以存储到云服务器上,比如阿里云的OSS
去云平台上注册帐号、开通OSS服务
在OSS控制台上:创建Bucket
要把文件上传到OSS:从官方文档里找到上传文件的代码,拷贝改一下就能使用了
4. SpringBoot工程的配置文件
支持:
properties文件:语法更简单,但是不方便表示配置参数的层级
yml或yaml文件:可以表示参数的层级,但是容易出错
yaml文件语法:
每个配置参数也是键值对格式,键值对之间使用 :空格 分隔
参数的层级,是通过键值对前边的空格数量。相同数量的空格,表示这些参数属于同一层级
参数值:
纯量:简单值。
数组: - 元素值
Map: 子级的键值对
获取配置文件里某些参数值:
@Value("${配置参数名}"),把参数值注入给一个成员变量
@ConfigurationProperties(prefix="前缀"),把一批参数封装成一个JavaBean对象
1. 创建一个类,类上加@ConfigurationProperties(prefix="前缀"),和@Component
2. 类里要有成员变量,并提供get和set方法。要求 前缀+成员变量名 要和 配置参数名 相同
一、登录功能-基本功能实现
需求
用户需要在登录页面上,输入自己的帐号密码后点击“登录”按钮。
如果服务端校验帐号和密码都正确,才允许进入tlias系统页面
如果服务端校验帐号或密码不正确,需要给出错误提示,并不允许跳转到tlias系统功能页面
分析
实现
LoginController
package com.itheima.controller;
import com.itheima.pojo.Emp;
import com.itheima.pojo.Result;
import com.itheima.service.EmpService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
/**
* @author liuyp
* @since 2023/08/23
*/
@RestController
public class LoginController {
@Autowired
private EmpService empService;
@PostMapping("/login")
public Result login(@RequestBody Emp emp) {
Emp e = empService.login(emp);
return e == null ? Result.error("帐号或密码错误") : Result.success();
}
}
EmpService
Emp login(Emp emp);
EmpServiceImpl
@Override
public Emp login(Emp emp) {
return empMapper.login(emp);
}
EmpMapper
@Select("select * from emp where username = #{username} and password = #{password}")
Emp login(Emp emp);
二、登录校验-用户身份令牌
1. 功能介绍
虽然我们已经完成了登录功能,但是当用户在登录后对其它功能的访问中,服务端并不知道当是哪个用户帐号在做本次操作,这是不利于系统的权限控制的。
如果想要服务端能够识别每次请求的用户身份,就需要在登录成功后的每次请求中,共享当前用户的身份数据
能够在多次请求中识别用户身份的常用技术有:
- 传统的会话技术:Cookie和Session。在会话中共同数据的技术,当然可以共享登录的用户帐号
- 目前流行的技术:JWT令牌。目前比较流行的技术,广泛用于系统中作为身份识别的令牌
2. 会话技术【了解】
会话技术介绍
什么是会话:会话的双方指的是客户端和服务端
- 当客户端和服务端建立TCP连接开始,一次会话就开始了
- 在会话过程中,客户端和服务端之间可以有多次请求和响应
- 当客户端和服务端之间的连接断开,会话就结束了
什么是会话技术:
- 是在一次会话过程(包含多次请求请求)中,共享数据的一种技术
有哪些会话技术:
- Cookie技术:客户端的会话技术,数据数据存储到客户端的技术,在一次会话中可以进行共享
- session技术:服务端的会话技术,数据存储到服务端session对象里,在一次会话中可以进行共享。session依赖于Cookie
会话技术的问题:
-
Cookie的问题:
- 某些客户端技术默认不支持Cookie,比如APP
- 客户端,用户可能会禁用Cookie
- 不能跨域
-
session的问题:
- 服务端集群环境下不能直接使用session技术。如果真要用,还需要解决服务器集群之间的 session同步问题
Cookie技术
开启会话:
- 客户端发请求------------------------------------>服务端:创建Cookie对象,把数据放到Cookie里
- 客户端得到Cookie<------------------------------服务端:把Cookie对象响应给客户端
- 客户端后续每次请求,都会携带Cookie---------->服务端:接收Cookie里的数据
- 客户端后续每次请求,都会携带Cookie---------->服务端:接收Cookie里的数据
- 客户端浏览器关闭:所有Cookie清空
会话结束
缺点:
- 客户端每次请求都要携带一些数据,造成一些网络宽带的压力
- Cookie只有共享字符串类型的数据,不能其它其它数据(比如JavaBean对象)
Session技术
开启会话:
- 客户端第一次请求----------------------------------->服务端:创建session对象,把数据存储到session里
- 客户端得到Cookie(session的id)<--------------------服务端:把session的id放到Cookie里,响应给客户端
- 客户端后续每次请求携带cookie(session的id)------->服务端:根据session的id找到对应session对象,从中取出数据
- 客户端后续每次请求携带cookie(session的id)------->服务端:根据session的id找到对应session对象,从中取出数据
- …
- 关闭浏览器
会话结束:Cookie被清空了
session技术:
- 可以存储、共享任意类型的数据:字符串、JavaBean对象,任意Java对象都可以
- 网络负荷减小了:客户端服务端之间只需要传输session的id,不需要传输那么多Cookie对象了
- 会话之间共享的数据也可以更多:服务端session对象里可以存储任意多个数据,只要JVM内存空间足够
3. JWT技术【重点】
JWT介绍
JWT:
-
JSON Web Token,json格式的web令牌技术,属于令牌技术的一种。用于解决web开发中的身份识别问题
-
定义了一种简洁的、自包含的格式,用于在通信双方以json数据格式传输信息。由于数字签名的存在,这些信息是可靠的。
JWT的特性:
- 可以防篡改。一旦被篡改,服务端可以校验出来的
- 不能防泄露。任何人得到jwt令牌,都可以从中得到 令牌承载的用户信息
JWT的注意:
- 生成token时,一定不要往token里放敏感信息。比如用户的密码、手机号等等
JWT结构
由三部分组成 :
- Header头:里边放的是令牌的类型、签名算法等等元数据信息。使用Base64Url编码得到的
- Body载荷:里边放的是用户的身份信息。使用Base64Url编码得到的
- Signature签名:Header + Body + 密钥字符串,通过签名算法生成签名,用于做防篡改校验
JWT示例
添加依赖
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.1</version>
</dependency>
JWT的生成与解析
package com.itheima;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
/**
* @author liuyp
* @since 2023/08/23
*/
public class DemoJwt {
public static void main(String[] args) throws InterruptedException {
//1. 生成JWT令牌
//1.1 准备载荷信息,即用户的身份信息
Map<String, Object> claims = new HashMap<>();
claims.put("id", 1);
claims.put("username", "tom");
//1.2 生成JWT令牌
String token = Jwts.builder()
//把载荷内容设置到JWT令牌里
.setClaims(claims)
//设置令牌的过期时间。这里设置有效期为:截止到当前时间+1000毫秒,即有效期只有1秒(可以根据实际情况自定义有效期)
.setExpiration(new Date(System.currentTimeMillis() + 1000))
//设置令牌的密钥。在将来解析令牌时,根据密钥校验令牌的签名,防止令牌被篡改
.signWith(SignatureAlgorithm.HS256, "itheima")
//生成令牌
.compact();
//token = eyJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjkyODc4MDE1LCJ1c2VybmFtZSI6InRvbSJ9.VhKA_ghuwKnIcxevdeb6AS0ZMw78WT3zqVQpQOFSvUk
System.out.println("token = " + token);
// Thread.sleep(1000);
//2. 校验与解析令牌:如果令牌过期,会抛出异常;如果令牌被篡改,会抛出异常;如果一切正常,会得到令牌里的载荷内容
Claims claimsRes = Jwts.parser()
//设置密钥。用于稍后的令牌签名校验,判断令牌是否被篡改了。如果令牌被篡改,会抛出异常
.setSigningKey("itheima")
//校验并解析令牌。如果令牌被篡改或已过期,会抛出异常
.parseClaimsJws(token)
//获取令牌载荷内容
.getBody();
System.out.println(claimsRes);
}
}
4. 完善登录功能-生成JWT令牌
只要修改LoginController
里的登录方法login
即可
package com.itheima.controller;
import com.itheima.pojo.Emp;
import com.itheima.pojo.Result;
import com.itheima.service.EmpService;
import com.itheima.util.JwtUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.Map;
/**
* @author liuyp
* @since 2023/08/23
*/
@RestController
public class LoginController {
@Autowired
private EmpService empService;
@PostMapping("/login")
public Result login(@RequestBody Emp emp) {
Emp e = empService.login(emp);
if (e != null) {
Map<String, Object> claims = new HashMap<>();
claims.put("id", e.getId());
claims.put("username", e.getUsername());
String token = JwtUtils.generateJwt(claims);
return Result.success(token);
}
return Result.error("帐号或密码错误");
}
}
三、登录校验-登录状态校验
1. 功能介绍
到目前为止,我们已经解决了帐号密码校验、用户身份识别的问题,但是登录功能还缺一部分没有完成:如果没有登录,则不允许对服务端的功能访问,即不允许使用员工管理、部门管理等等功能
这就需要我们能够对客户端的请求进行拦截,然后根据是否登录的状态,再决定是否放行
这样的技术常见的有:
- JavaEE基础技术提供的-Filter过滤器。一些传统的项目可能使用Filter
- SpringMVC框架提供的-Interceptor拦截器。如果相对较新的项目,项目里使用了Spring框架,通常都会用Interceptor
常见的使用场景:
- 过滤敏感词
- 黑名单过滤
- 权限控制:没有登录不允许访问
2. 过滤器Filter
2.1 使用入门
使用步骤
- 创建Java类,实现
javax.servlet.Filter
接口- 重写接口的
doFilter
方法:在方法里编写过滤逻辑,并决定是否要放行 - 在类上添加注解
@WebFilter
:标记一下,这个类是过滤器类。如果不加这个注解,过滤器就不生效
- 重写接口的
- 在引导类上添加注解
@ServletComponentScan
,用于扫描Servlet相关的注解,包括@WebFilter
使用示例
过滤器类Demo01Filter
package com.itheima.filter;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
/**
* @author liuyp
* @since 2023/08/23
*/
@WebFilter
public class Demo01Filter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
//目标方法执行之前的预处理,根据需求自定义。。。
System.out.println("拦截器Demo01Filter.doFilter执行了,目标方法执行前...");
//放行不拦截。如果没有这行代码,就不放行。只有放行了,客户端的请求才能够访问到目标资源
filterChain.doFilter(servletRequest, servletResponse);
//目标方法执行之后的后处理,根据需求自定义。。。
System.out.println("拦截器Demo01Filter.doFilter执行了,目标方法执行后...");
}
}
引导类
引导类上添加@ServletComponentScan
注解
package com.itheima;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;
@ServletComponentScan
@SpringBootApplication
public class TliasWebManagementApplication {
public static void main(String[] args) {
SpringApplication.run(TliasWebManagementApplication.class, args);
}
}
测试效果
打开Postman,访问tlias系统里的任意一个功能,发请求时,查看idea控制台,发现拦截器都执行了
2.2 过滤器详解
执行原理(执行过程)
如果一次请求有多个过滤器可以进行过滤,任意一个过滤器不放行,整个请求就不可能到达目标资源
拦截范围
在过滤器上使用注解@WebFilter
时,可以使用注解的urlPatterns
或value
属性,配置过滤器的拦截范围。
@WebFilter(urlPatterns = "拦截范围")
@WebFilter(value = "拦截范围")
@WebFilter("拦截范围")
拦截范围的写法,常用的有:
拦截范围 | 语法示例 | 作用 |
---|---|---|
精确拦截 | /emps | 只拦截客户端对/emps 的请求 |
范围拦截 | /emps/* (必须以/ 开头以* 结尾) | 拦截客户端对/emps 下的资源请求,比如/emps ,/emps/1 , /emps/xx/yy 等等 |
示例:
package com.itheima.filter;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
/**
* @author liuyp
* @since 2023/08/24
*/
@WebFilter(urlPatterns = "/emps/*")
public class Demo01Filter implements Filter {
/**
* 这个方法就是过滤器的过滤方法。客户端的每次请求,只要在此过滤器的过滤范围内,这个方法就必定执行
* @param request 请求对象。它封装了本次http请求的所有数据
* @param response 响应对象。我们向这个对象里设置数据,这些数据最终会被转换成HTTP响应,返回给客户端
* @param chain 过滤器链对象。用于放行请求的
*
*/
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
//在目标方法执行之前的预处理
System.out.println("A");
//可以放行。只有过滤器放行了,本次请求才可能到达目标资源(Controller里的方法)
chain.doFilter(request, response);
//在目标方法执行之后的后处理
System.out.println("B");
}
}
多过滤器的过滤顺序(过滤器链)
按照过滤器的全限定类名进行排序。
哪个过滤器排序靠前,哪个过滤器就先执行
2.3 完善登录功能-使用Filter校验登录状态
分析
需要使用过滤器Filter进行拦截。在过滤器里:
- 获取本次请求的uri路径。如果是登录:直接放行
- 获取本次请求的携带的token。如果获取不到:不放行,给客户端直接返回响应
- 校验本次请求的token。如果token非法或过期:不放行,给客户端直接返回响应
- 否则:token一切正常,直接放行
添加fastjson依赖
因为稍后我们需要使用到json转换工具:FastJson,所以先把FastJson的依赖坐标添加到pom.xml里
<!--fastJSON-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.76</version>
</dependency>
登录校验校验Filter
package com.itheima.filter;
import com.alibaba.fastjson.JSON;
import com.itheima.pojo.Result;
import com.itheima.util.JwtUtils;
import io.jsonwebtoken.Claims;
import lombok.extern.slf4j.Slf4j;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @author liuyp
* @since 2023/08/23
*/
@Slf4j
@WebFilter("/*")
public class LoginFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
response.setContentType("application/json;charset=utf-8");
//1. 获取本次请求的目标资源路径。如果是登录,就直接放行不拦截
String uri = request.getRequestURI();
if ("/login".equals(uri)) {
log.info("本次请求是登录,直接放行");
filterChain.doFilter(request, response);
return;
}
//2. 获取本次请求携带的token,并校验
String token = request.getHeader("token");
// 2.1 如果token为空:直接返回响应“未登录”
if (token == null || "".equals(token)) {
log.warn("本次请求{},没有携带token,不允许访问", uri);
response.setStatus(401);
response.getWriter().println(JSON.toJSONString(Result.error("未登录")));
return;
}
// 2.2 如果token非法或过期:直接返回响应“未登录”
try {
JwtUtils.parseJWT(token);
} catch (Exception e) {
log.warn("本次请求{},携带的token过期或非法,不允许访问", uri);
response.setStatus(401);
response.getWriter().println(JSON.toJSONString(Result.error("请重新登录")));
return;
}
//3. 放行
filterChain.doFilter(request, response);
}
}
功能测试
- 请求时不携带token,请求被拦截
- 请求时携带了token,没有被拦截,功能正常
3. 拦截器Interceptor【重点】
是由SpringMVC框架提供的技术
3.1 使用入门
使用步骤
-
创建拦截器类:创建Java类,实现
HandlerInterceptor
接口,重写接口的方法(需要用哪个,就重写哪个):preHandle
方法:在目标方法执行前的预处理方法postHandle
方法:在目标方法执行成功后的后处理方法afterCompletion
方法:在服务端给客户端返回响应之前执行的最终方法
-
配置拦截器:
-
创建Java类,作为Spring的配置类
添加注解
@Configuration
,把类标记为Spring的配置类实现接口
WebMvcConfigurer
,作为Web层框架SpringMVC的配置类,必须实现此接口 -
重写接口的
addInterceptors
方法在方法里配置拦截器
-
使用示例
拦截器类Demo01Interceptor
package com.itheima.interceptor;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* @author liuyp
* @since 2023/08/23
*/
public class Demo01Interceptor implements HandlerInterceptor {
/**
* 预处理方法:在目标方法执行之前先执行
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("Demo01Interceptor.preHandle.....");
//如果方法返回true,表示放行;如果返回false,表示不放行
return true;
}
/**
* 后处理方法:在目标方法执行之后再执行(目标方法执行成功以后,才会执行)
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("Demo01Interceptor.postHandle.....");
}
/**
* 最终处理方法:在给客户端返回响应之前,最终执行(无论目标方法有没有异常,都必定会执行)
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("Demo01Interceptor.afterCompletion.....");
}
}
配置类WebConfig
package com.itheima.config;
import com.itheima.interceptor.Demo01Interceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* @author liuyp
* @since 2023/08/23
*/
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
//注册拦截器,并设置拦截范围为/**,表示拦截所有请求
registry.addInterceptor(new Demo01Interceptor()).addPathPatterns("/**");
}
}
3.2 拦截器详解
拦截范围
写法 | 示例 | 作用 |
---|---|---|
拦截一级匹配路径 | /emp/* | 只拦截一级目录。拦截/emp/1 , /emp/2 ;不拦截/emp/xx/yy |
拦截任意级匹配路径 | /emp/** | 拦截任意级目录。拦截/emp ,/emp/1 , /emp/2 ,/emp/xx/yy , /emp/xx/yy/zz |
多过滤器的拦截顺序
-
先执行所有拦截器的
preHandle
方法。如果任何一个拦截器的preHandle方法返回false,就拦截不放行了
-
再执行目标方法
-
再执行所有拦截器的
postHandle
方法。只有在目标方法执行后,没有异常时才会执行的
执行的顺序,和
preHandle
的顺序是倒着的 -
再执行所有拦截器的
afterCompletion
方法无论目标方法有没有异常,都必定会执行的
执行的顺序,和
preHandle
的顺序是倒着的
3.3 完善登录功能-使用Interceptor校验登录状态
拦截器LoginInterceptor
package com.itheima.interceptor;
import com.alibaba.fastjson.JSON;
import com.itheima.pojo.Result;
import com.itheima.util.JwtUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* @author liuyp
* @since 2023/08/23
*/
@Slf4j
public class LoginInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//1. 如果本次请求是登录,就直接放行
String uri = request.getRequestURI();
if ("/login".equals(uri)) {
log.info("本次请求是登录,直接放行");
return true;
}
//2. 获取本次请求携带的token
String token = request.getHeader("token");
// 如果没有token:直接返回响应结果
if (!StringUtils.hasText(token)) {
response.setContentType("application/json;charset=utf-8");
response.setStatus(401);
response.getWriter().println(JSON.toJSONString(Result.error("未登录")));
return false;
}
// 如果token过期或非法:直接返回响应结果
try {
JwtUtils.parseJWT(token);
} catch (Exception e) {
response.setContentType("application/json;charset=utf-8");
response.setStatus(401);
response.getWriter().println(JSON.toJSONString(Result.error("请重新登录")));
return false;
}
//3. 放行
return true;
}
}
WebConfig里配置拦截器
package com.itheima.config;
import com.itheima.interceptor.LoginInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* @author liuyp
* @since 2023/08/23
*/
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoginInterceptor()).addPathPatterns("/**");
}
}
功能测试
四、异常处理
1. 项目中的异常处理方案
项目里遇到异常,通常做一件事:抛
所有异常抛,最终统一由异常处理器进行处理
2. SpringMVC异常处理器
使用步骤
- 创建一个Java类,类上添加注解
@RestControllerAdvice
。表示这个类是对Controller进行功能增强的 - 类里创建一个方法用于处理异常
- 方法上加注解
@ExceptionHandler(异常类名.class)
- 方法里要加形参:注解里要抓取什么类型的异常,方法就要有什么类型的形参。
- 方法里要处理异常:
- 打印异常信息
- 给客户端返回友好提示
- 方法上加注解
使用示例
package com.itheima.exception;
import com.itheima.pojo.Result;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
/**
* 类上加的注解@RestControllerAdvice:表示当前类是用于对 Controller类进行功能增强的
* @author liuyp
* @since 2023/08/24
*/
@RestControllerAdvice
public class TliasExceptionHandler {
/**
* 方法上加@ExceptionHandler(异常类型):表示告诉SpringMVC,这个方法用于抓取什么样的异常进行处理
* 注解里写的什么类型的异常,方法里就要加什么类型的形参:是抓取到的异常对象
* @param e
* @return
*/
@ExceptionHandler(Exception.class)
public Result handleException(Exception e){
//在实际开发中,一旦抓到异常,一定要打印出来。不能把异常吃掉
e.printStackTrace();
//给客户端返回一个更友好的结果
return Result.error("系统正在维护……");
}
}