目录
一、登录功能
1.1 思路
1.2 LoginController
1.3 EmpService
1.4 EmpServiceImpl
1.5 EmpMapper
1.6 启动服务-测试
1.7 前后端联调
二、登录校验(重点)
2.1 问题
2.2 问题分析
2.3 登录校验编辑
2.4 会话技术
2.4.1 会话技术
2.4.2 会话跟踪方案对比
2.5 JWT令牌
2.5.1 简介
2.5.2 应用场景
2.5.3 jwt-生成
5.5.3.1 引入包
5.5.3.2 生成JWT
5.5.3.3 解析JWT
2.6 案例实现JWT
2.6.1 新建JwtUtils工具类
2.6.2 LoginController
2.6.3 启动服务-测试
2.6.4 前后端联调
2.7 过滤器Filter
2.7.1 概述
2.7.2 快速入门
2.7.2.1 新增DemoFilter
2.7.2.2 SpringBootProjectTestApplication
2.7.2.3 启动服务-测试
2.7.2.4 总结
2.7.3 详解(执行流程、拦截路径、过滤器链)
2.7.3.1 执行流程
2.7.3.2 Filter-拦截路径 编辑
2.7.3.3 过滤器链(优先级按过滤器名自然排序)
2.7.3.4 总结
2.7.4 案例-登录校验-Filter
2.7.4.1 思路
2.7.4.2 pom.xml引入依赖fastjson
2.7.4.3 新建工具类拦截器LoginCheckFilter
2.7.4.4 启动服务-测试
2.8 拦截器Interceptor
2.8.1 简介
2.8.2 快速入门
2.8.2.1 新建LoginCheckInterceptor
2.8.2.2 WebConfig
2.8.2.3 启动服务测试
2.8.3 详解
2.8.3.1 拦截路径
2.8.3.2 拦截器- 执行流程
2.8.4 案例-登录校验-Interceptor
2.8.4.1 LoginCheckInterceptor
2.8.4.2 WebConfig
2.8.4.3 启动服务-测试
三、异常处理
3.1 异常现象--新增重复名称部门
3.2 思考如何处理
3.3 全家异常处理
3.3.1 异常类GlobalExceptionHandler
3.3.2 启动服务-测试
3.3.3 总结
前言:实现案例的登录功能、登录校验和异常处理
一、登录功能
1.1 思路
1.2 LoginController
package com.runa.controller;import com.runa.pojo.Emp;
import com.runa.pojo.Result;
import com.runa.service.EmpService;
import lombok.extern.slf4j.Slf4j;
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;@Slf4j
@RestController
public class LoginController {@Autowiredprivate EmpService empService;@PostMapping("/login")public Result login(@RequestBody Emp emp){log.info("登录的用户:{}",emp);Emp e = empService.login(emp);return e != null ? Result.success():Result.error("用户名或密码错误");}
}
1.3 EmpService
package com.runa.service;import com.runa.pojo.Emp;
import com.runa.pojo.PageBean;
import org.springframework.format.annotation.DateTimeFormat;import java.time.LocalDate;
import java.util.List;public interface EmpService {/*** 分页查询 不带条件* @param page* @param pageSize* @return*/
// PageBean page(Integer page, Integer pageSize);/*** 分页查询 带条件* @param page* @param pageSize* @return*/PageBean page(Integer page, Integer pageSize,String name, Short gender, LocalDate begin, LocalDate end);/*** 批量删除员工* @param ids*/void delete(List<Integer> ids);/*** 新增员工* @param emp*/void save(Emp emp);/*** 根据id查询员工* @param id* @return*/Emp getById(Integer id);/*** 修改员工* @param emp*/void update(Emp emp);/*** 登录* @param emp* @return*/Emp login(Emp emp);
}
1.4 EmpServiceImpl
package com.runa.service.impl;import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.runa.mapper.EmpMapper;
import com.runa.pojo.Emp;
import com.runa.pojo.PageBean;
import com.runa.service.EmpService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;@Service
public class EmpServiceImpl implements EmpService {@Autowiredprivate EmpMapper empMapper;/*** 分页查询 pagehelper+组合查询* @param page* @param pageSize* @param name* @param gender* @param begin* @param end* @return*/@Overridepublic PageBean page(Integer page, Integer pageSize, String name, Short gender, LocalDate begin, LocalDate end) {// 1 设置分页参数PageHelper.startPage(page, pageSize);// 2 执行查询List<Emp> empList = empMapper.list(name, gender, begin, end);Page<Emp> p = (Page<Emp>) empList;// 3 封装PangeBean对象PageBean pageBean = new PageBean(p.getTotal(),((Page<Emp>) empList).getResult());return pageBean;}/*** 批量删除员工* @param ids*/@Overridepublic void delete(List<Integer> ids) {empMapper.delete(ids);}/*** 新增员工* @param emp*/@Overridepublic void save(Emp emp) {emp.setCreateTime(LocalDateTime.now());emp.setUpdateTime(LocalDateTime.now());empMapper.insert(emp);}/*** 根据ID查询员工* @param id* @return*/@Overridepublic Emp getById(Integer id) {return empMapper.getByID(id);}/*** 修改员工* @param emp*/@Overridepublic void update(Emp emp) {emp.setUpdateTime(LocalDateTime.now());empMapper.update(emp);}/*** 登录* @param emp* @return*/@Overridepublic Emp login(Emp emp) {return empMapper.getByUsernameAndPassword(emp);}/*** 分页查询 加pagehelper* @param page* @param pageSize* @return*/
// @Override
// public PageBean page(Integer page, Integer pageSize) {
// // 1 设置分页参数
// PageHelper.startPage(page, pageSize);
//
// // 2 执行查询
// List<Emp> empList = empMapper.list();
// Page<Emp> p = (Page<Emp>) empList;
//
// // 3 封装PangeBean对象
// PageBean pageBean = new PageBean(p.getTotal(),((Page<Emp>) empList).getResult());
// return pageBean;
// }/*** 分页查询* @param page* @param pageSize* @return*/
// @Override
// public PageBean page(Integer page, Integer pageSize) {
// // 1 获取总记录数
// Long count = empMapper.count();
//
// // 2 获取分页查询结果列表
// Integer start = (page - 1) * pageSize;
// List<Emp> empList = empMapper.page(start, pageSize);
//
// // 3 封装PangeBean对象
// PageBean pageBean = new PageBean(count,empList);
// }}
1.5 EmpMapper
package com.runa.mapper;import com.runa.pojo.Emp;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;import java.time.LocalDate;
import java.util.List;/*** 员工管理*/
@Mapper
public interface EmpMapper {/*** 查询总记录数* @return*/
// @Select("select count(*) from emp")
// public Long count();/*** 分页查询 获取列表数据* @param start* @param pageSize* @return*/
// @Select("select * from emp limit #{start}, #{pageSize}")
// public List<Emp> page(Integer start, Integer pageSize);/*** 使用pagehelper的员工信息查询* @return*/
// @Select("select * from emp")
// public List<Emp> list();/*** 使用pagehelper的员工信息查询(带条件)--动态sql* 使用xml注解sql* @return*/public List<Emp> list(String name, Short gender, LocalDate begin, LocalDate end);/*** 批量删除员工* @param ids*/void delete(List<Integer> ids);/*** 新增员工* @param emp*/@Insert("insert into emp(username, name, gender, image, job, entrydate, dept_id, create_time, update_time)" +" values(#{username}, #{name}, #{gender}, #{image}, #{job}, #{entrydate}, #{deptId}, #{createTime}, #{updateTime})")void insert(Emp emp);/*** 根据id查询员工* @param id* @return*/@Select("select * from emp where id = #{id}")Emp getByID(Integer id);/*** 修改员工* @param emp*/void update(Emp emp);/*** 登录* @param emp* @return*/@Select("select * from emp where username = #{username} and password = #{password}")Emp getByUsernameAndPassword(Emp emp);
}
1.6 启动服务-测试
1.7 前后端联调
二、登录校验(重点)
2.1 问题
2.2 问题分析
2.3 登录校验
2.4 会话技术
2.4.1 会话技术
2.4.2 会话跟踪方案对比
Cookies与Session例子,启动服务http://localhost:8080/c1
package com.runa.controller;import com.runa.pojo.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;/*** HttpSession演示*/
@Slf4j
@RestController
public class SessionController {//设置Cookie@GetMapping("/c1")public Result cookie1(HttpServletResponse response){response.addCookie(new Cookie("login_username","itheima")); //设置Cookie/响应Cookiereturn Result.success();}//获取Cookie@GetMapping("/c2")public Result cookie2(HttpServletRequest request){Cookie[] cookies = request.getCookies();for (Cookie cookie : cookies) {if(cookie.getName().equals("login_username")){System.out.println("login_username: "+cookie.getValue()); //输出name为login_username的cookie}}return Result.success();}@GetMapping("/s1")public Result session1(HttpSession session){log.info("HttpSession-s1: {}", session.hashCode());session.setAttribute("loginUser", "tom"); //往session中存储数据return Result.success();}@GetMapping("/s2")public Result session2(HttpServletRequest request){HttpSession session = request.getSession();log.info("HttpSession-s2: {}", session.hashCode());Object loginUser = session.getAttribute("loginUser"); //从session中获取数据log.info("loginUser: {}", loginUser);return Result.success(loginUser);}
}
2.5 JWT令牌
2.5.1 简介
2.5.2 应用场景
2.5.3 jwt-生成
5.5.3.1 引入包
<!--JWT令牌--><dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId><version>0.9.1</version></dependency>
5.5.3.2 生成JWT
记得注释他//@SpringBootTest
package com.runa;import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;import java.util.Date;
import java.util.HashMap;
import java.util.Map;//@SpringBootTest
class SpringBootProjectTestApplicationTests {// @Test
// void contextLoads() {
// }/*** 测试JWT令牌的生成*/@Testpublic void testGenJwt(){Map<String, Object> claims = new HashMap<>();claims.put("id",1);claims.put("name","bocai");String jwt = Jwts.builder().signWith(SignatureAlgorithm.HS256, "runa") // 签名算法 算法有哪些上官网.setClaims(claims) //自定义的内容(载荷).setExpiration(new Date(System.currentTimeMillis() + 3600* 1000)) // 设置有效期为1h.compact();System.out.println(jwt);}}
生成的jwt令牌上官网
5.5.3.3 解析JWT
package com.runa;import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;import java.util.Date;
import java.util.HashMap;
import java.util.Map;//@SpringBootTest
class SpringBootProjectTestApplicationTests {// @Test
// void contextLoads() {
// }/*** 生成Jwt令牌*/@Testpublic void testGenJwt(){Map<String, Object> claims = new HashMap<>();claims.put("id",1);claims.put("name","bocai");String jwt = Jwts.builder().signWith(SignatureAlgorithm.HS256, "runa") // 签名算法 算法有哪些上官网.setClaims(claims) //自定义的内容(载荷).setExpiration(new Date(System.currentTimeMillis() + 3600* 1000)) // 设置有效期为1h.compact();System.out.println(jwt);}/*** 解析Jwt*/@Testpublic void testPareJwt(){Claims claims = Jwts.parser().setSigningKey("runa") //runa要与前面生成一致.parseClaimsJws("eyJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoiYm9jYWkiLCJpZCI6MSwiZXhwIjoxNjkyNzc3MzAwfQ.KPqgKc5JS8j7GN7aPQ0GwQnUaGm78WWbzf2N7LGq34g").getBody();System.out.println(claims);}}
2.6 案例实现JWT
2.6.1 新建JwtUtils工具类
package com.runa.utils;import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import java.util.Date;
import java.util.Map;public class JwtUtils {private static String signKey = "runa";private static Long expire = 43200000L; // 12h/*** 生成JWT令牌* @param claims JWT第二部分负载 payload 中存储的内容* @return*/public static String generateJwt(Map<String, Object> claims){String jwt = Jwts.builder().addClaims(claims).signWith(SignatureAlgorithm.HS256, signKey).setExpiration(new Date(System.currentTimeMillis() + expire)).compact();return jwt;}/*** 解析JWT令牌* @param jwt JWT令牌* @return JWT第二部分负载 payload 中存储的内容*/public static Claims parseJWT(String jwt){Claims claims = Jwts.parser().setSigningKey(signKey).parseClaimsJws(jwt).getBody();return claims;}
}
2.6.2 LoginController
package com.runa.controller;import com.runa.pojo.Emp;
import com.runa.pojo.Result;
import com.runa.service.EmpService;
import com.runa.utils.JwtUtils;
import lombok.extern.slf4j.Slf4j;
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;@Slf4j
@RestController
public class LoginController {@Autowiredprivate EmpService empService;@PostMapping("/login")public Result login(@RequestBody Emp emp){log.info("登录的用户:{}",emp);Emp e = empService.login(emp);// 登录成功,生成令牌,下发令牌if(e != null){Map<String, Object> claims = new HashMap<>();claims.put("id",e.getId());claims.put("name", e.getName());claims.put("username", e.getUsername());String jwt = JwtUtils.generateJwt(claims);return Result.success(jwt);}// 登录失败,返回错误信息return Result.error("用户名或密码错误");}
}
2.6.3 启动服务-测试
2.6.4 前后端联调
2.7 过滤器Filter
2.7.1 概述
2.7.2 快速入门
2.7.2.1 新增DemoFilter
package com.runa.filter;import jakarta.servlet.*;
import jakarta.servlet.annotation.WebFilter;import java.io.IOException;@WebFilter(urlPatterns = "/*")
public class DemoFilter implements Filter {@Override // 初始化方法,只调用一次public void init(FilterConfig filterConfig) throws ServletException {System.out.println("init初始化方法执行了");}@Override // 拦截到请求之后调用,调用多次public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {System.out.println("拦截到请求了~~~");// 放行filterChain.doFilter(servletRequest,servletResponse);}@Override // 销毁方法,只调用一次public void destroy() {System.out.println("destroy方法执行了");}
}
2.7.2.2 SpringBootProjectTestApplication
package com.runa;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;@ServletComponentScan //开启了对servlet组件支持
@SpringBootApplication
public class SpringBootProjectTestApplication {public static void main(String[] args) {SpringApplication.run(SpringBootProjectTestApplication.class, args);}}
2.7.2.3 启动服务-测试
略
2.7.2.4 总结
2.7.3 详解(执行流程、拦截路径、过滤器链)
2.7.3.1 执行流程
2.7.3.2 Filter-拦截路径
2.7.3.3 过滤器链(优先级按过滤器名自然排序)
package com.runa.filter;import jakarta.servlet.*;
import jakarta.servlet.annotation.WebFilter;import java.io.IOException;@WebFilter(urlPatterns = "/*")
public class SecondFilter implements Filter {@Override // 拦截到请求之后调用,调用多次public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {System.out.println("SecondFilter 拦截---2到请求了~~~放行之前逻辑");// 放行filterChain.doFilter(servletRequest,servletResponse);System.out.println("SecondFilter拦截---2到请求了~~~放行之后逻辑");}
}
2.7.3.4 总结
2.7.4 案例-登录校验-Filter
2.7.4.1 思路
2.7.4.2 pom.xml引入依赖fastjson
<!--fastJSON--><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.76</version></dependency>
2.7.4.3 新建工具类拦截器LoginCheckFilter
package com.runa.filter;import com.alibaba.fastjson.JSONObject;
import com.runa.pojo.Result;
import com.runa.utils.JwtUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;import jakarta.servlet.*;
import jakarta.servlet.annotation.WebFilter;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;@Slf4j
//@WebFilter(urlPatterns = "/*")
public class LoginCheckFilter implements Filter {@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {HttpServletRequest req = (HttpServletRequest) request;HttpServletResponse resp = (HttpServletResponse) response;//1.获取请求url。String url = req.getRequestURL().toString();log.info("请求的url: {}",url);//2.判断请求url中是否包含login,如果包含,说明是登录操作,放行。if(url.contains("login")){log.info("登录操作, 放行...");chain.doFilter(request,response);return;}//3.获取请求头中的令牌(token)。String jwt = req.getHeader("token");//4.判断令牌是否存在,如果不存在,返回错误结果(未登录)。if(!StringUtils.hasLength(jwt)){log.info("请求头token为空,返回未登录的信息");Result error = Result.error("NOT_LOGIN");//手动转换 对象--json --------> 阿里巴巴fastJSONString notLogin = JSONObject.toJSONString(error);resp.getWriter().write(notLogin);return;}//5.解析token,如果解析失败,返回错误结果(未登录)。try {JwtUtils.parseJWT(jwt);} catch (Exception e) {//jwt解析失败e.printStackTrace();log.info("解析令牌失败, 返回未登录错误信息");Result error = Result.error("NOT_LOGIN");//手动转换 对象--json --------> 阿里巴巴fastJSONString notLogin = JSONObject.toJSONString(error);resp.getWriter().write(notLogin);return;}//6.放行。log.info("令牌合法, 放行");chain.doFilter(request, response);}
}
2.7.4.4 启动服务-测试
记得将 DemoFilter 与SecondFilter 的@WebFilter(urlPatterns = "/*") 注释掉
2.8 拦截器Interceptor
2.8.1 简介
2.8.2 快速入门
2.8.2.1 新建LoginCheckInterceptor
package com.runa.interceptor;import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;@Component
public class LoginCheckInterceptor implements HandlerInterceptor {@Override //目标资源方法运行前运行, 返回true: 放行, 放回false, 不放行public boolean preHandle(HttpServletRequest req, HttpServletResponse resp, Object handler) throws Exception {System.out.println("preHandle ...");return true;}@Override //目标资源方法运行后运行public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {System.out.println("postHandle ...");}@Override //视图渲染完毕后运行, 最后运行public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {System.out.println("afterCompletion...");}
}
2.8.2.2 WebConfig
package com.runa.config;import com.runa.interceptor.LoginCheckInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;@Configuration //配置类
public class WebConfig implements WebMvcConfigurer {@Autowiredprivate LoginCheckInterceptor loginCheckInterceptor;@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(loginCheckInterceptor).addPathPatterns("/**");}
}
2.8.2.3 启动服务测试
将过滤器 LoginCheckFilter @WebFilter(urlPatterns = "/*") 注释掉
2.8.3 详解
2.8.3.1 拦截路径
2.8.3.2 拦截器- 执行流程
2.8.4 案例-登录校验-Interceptor
2.8.4.1 LoginCheckInterceptor
package com.runa.interceptor;import com.alibaba.fastjson.JSONObject;
import com.runa.pojo.Result;
import com.runa.utils.JwtUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;@Slf4j
@Component
public class LoginCheckInterceptor implements HandlerInterceptor {@Override //目标资源方法运行前运行, 返回true: 放行, 放回false, 不放行public boolean preHandle(HttpServletRequest req, HttpServletResponse resp, Object handler) throws Exception {//1.获取请求url。String url = req.getRequestURL().toString();log.info("请求的url: {}",url);//2.判断请求url中是否包含login,如果包含,说明是登录操作,放行。if(url.contains("login")){log.info("登录操作, 放行...");return true;}//3.获取请求头中的令牌(token)。String jwt = req.getHeader("token");//4.判断令牌是否存在,如果不存在,返回错误结果(未登录)。if(!StringUtils.hasLength(jwt)){log.info("请求头token为空,返回未登录的信息");Result error = Result.error("NOT_LOGIN");//手动转换 对象--json --------> 阿里巴巴fastJSONString notLogin = JSONObject.toJSONString(error);resp.getWriter().write(notLogin);return false;}//5.解析token,如果解析失败,返回错误结果(未登录)。try {JwtUtils.parseJWT(jwt);} catch (Exception e) {//jwt解析失败e.printStackTrace();log.info("解析令牌失败, 返回未登录错误信息");Result error = Result.error("NOT_LOGIN");//手动转换 对象--json --------> 阿里巴巴fastJSONString notLogin = JSONObject.toJSONString(error);resp.getWriter().write(notLogin);return false;}//6.放行。log.info("令牌合法, 放行");return true;}@Override //目标资源方法运行后运行public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {System.out.println("postHandle ...");}@Override //视图渲染完毕后运行, 最后运行public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {System.out.println("afterCompletion...");}
}
2.8.4.2 WebConfig
package com.runa.config;import com.runa.interceptor.LoginCheckInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;@Configuration //配置类
public class WebConfig implements WebMvcConfigurer {@Autowiredprivate LoginCheckInterceptor loginCheckInterceptor;@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(loginCheckInterceptor).addPathPatterns("/**").excludePathPatterns("/login");}
}
2.8.4.3 启动服务-测试
注释Filter
三、异常处理
3.1 异常现象--新增重复名称部门
3.2 思考如何处理
3.3 全家异常处理
3.3.1 异常类GlobalExceptionHandler
package com.runa.exception;import com.runa.pojo.Result;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;/*** 全局异常处理器*/
@RestControllerAdvice
public class GlobalExceptionHandler {@ExceptionHandler(Exception.class)//捕获所有异常public Result ex(Exception ex){ex.printStackTrace();return Result.error("对不起,操作失败,请联系管理员");}}
3.3.2 启动服务-测试
新建重复部门
3.3.3 总结