新乡企业网站建设,建设商城网站费用,网站的详情页面,2023小规模企业所得税税率是多少目录
1.用户登陆权限验证
1.1 每个方法验证
1.2 Spring AOP 用户统一登陆验证
1.3 拦截器
1.3.1 自定义拦截器
1.3.2 将自定义拦截器配置到系统设置中#xff0c;并且设置拦截规则
1.3.3 排除所有的静态资源
1.4 登录拦截器#xff08;练习#xff09;
1.5 拦截器原…目录
1.用户登陆权限验证
1.1 每个方法验证
1.2 Spring AOP 用户统一登陆验证
1.3 拦截器
1.3.1 自定义拦截器
1.3.2 将自定义拦截器配置到系统设置中并且设置拦截规则
1.3.3 排除所有的静态资源
1.4 登录拦截器练习
1.5 拦截器原理
2.统一异常处理
3.统一数据返回格式
3.1 统一数据处理强制执行 统一处理的功能包括
统一用户登陆权限验证统一数据格式返回统一异常处理
1.用户登陆权限验证
之前学到的是在每个方法中验证用户登录权限现在是统一的用户登录验证处理
1.1 每个方法验证
最初的验证方法
RestController
RequestMapping(/user)
public class UserController {
/*** 某⽅法 1*/RequestMapping(/m1)public Object method(HttpServletRequest request) {//有 session 就获取没有不会创建HttpSession session request.getSession(false);if(session ! null session.getAttribute(userinfo) ! null) {// 说明已经登录业务处理return true;} else {// 未登录return false;}}
} 每个方法中都有相同的用户登录验证权限它的缺点是 每个方法都要单独写一个用户登录验证的方法添加的控制器越多调⽤⽤户登录验证的⽅法也越多这样就增加了后期的修改成本和维护成本。 这些⽤户登录验证的⽅法和接下来要实现的业务⼏何没有任何关联但每个⽅法中都要写⼀遍 1.2 Spring AOP 用户统一登陆验证
通过前置通知或者环绕通知实现
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
Aspect
Component
public class UserAspect {// 定义切点⽅法 controller 包下、⼦孙包下所有类的所有⽅法Pointcut(execution(* com.example.demo.controller..*.*(..)))public void pointcut(){ }// 前置⽅法Before(pointcut())public void doBefore(){}// 环绕⽅法Around(pointcut())public Object doAround(ProceedingJoinPoint joinPoint){Object obj null;System.out.println(Around ⽅法开始执⾏);try {// 执⾏拦截⽅法obj joinPoint.proceed();} catch (Throwable throwable) {throwable.printStackTrace();}System.out.println(Around ⽅法结束执⾏);return obj;}
} 缺点 无法获取 HttpSession 对象我们要对⼀部分方法机型拦截⽽另⼀部分方法不拦截如注册方法和登录⽅法是不拦截的这样的话排除⽅法的规则很难定义甚⾄没办法定义。 1.3 拦截器
Spring 提供了具体的实现拦截器HandlerInterceptor
创建自定义拦截器实现 HandlerInterceptor 接口的 preHandle执行具体方法之前的预处理方法 将自定义拦截器加入 WebMvcConfigurer 的 addInterceptors 方法中
1.3.1 自定义拦截器 用户登陆拦截器 实现 HandlerInterceptor 接口 的拦截器实现 preHandle执行具体方法之前的预处理方法执行目标方法之前判断是否有登录重新 preHandle 方法返回 true拦截器验证成功继续执行后续的方法返回 false拦截器验证失败不会执行后续目标方法写业务方法得到 Session 对象判断 Session 中是否有登陆用户有——true无——false
package com.example.demo.config;
import com.example.demo.common.AppVar;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
/*** 自定义拦截器*/
public class UserInterceptor implements HandlerInterceptor {/*** 返回 true表示拦截器验证成功继续执行后续的方法* false:拦截器验证失败不会执行后续目标方法* param request* param response* param handler* return* throws Exception*/Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {//业务方法//得到 Session 对象:判断 Session 中是否有登陆用户有——true无——falseHttpSession session request.getSession(false);//默认 trueif (session ! null session.getAttribute(AppVar.SESSION_KEY) ! null) {//用户已经登陆return true;}return false;}
}
定义 Session Key 值
package com.example.demo.common;
//全局变量
public class AppVar {//Session Keypublic static final String SESSION_KEY SESSION_KEY;
}
1.3.2 将自定义拦截器配置到系统设置中并且设置拦截规则
配置文件 AppConfig
实现 WebMvcConfigurer表明是一个系统的配置文件重写 addInterceptors 方法支持添加多个拦截器
添加多个拦截器注入有两种方法
1️⃣
registry.addInterceptor(new UserInterceptor());
2️⃣ UserInterceptor 类中添加 Component 注解随着 spring 启动而启动通过 Autowired 注入进去
Configuration 注解是随着 spring 启动而启动将当前配置设置到系统中
package com.example.demo.config;
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 AppConfig implements WebMvcConfigurer {Autowiredprivate UserInterceptor userInterceptor;Overridepublic void addInterceptors(InterceptorRegistry registry) {//registry.addInterceptor(new UserInterceptor());registry.addInterceptor(userInterceptor).addPathPatterns(/**)//拦截规则/**拦截所有的请求.excludePathPatterns(/user/reg)//不拦截.excludePathPatterns(/user/login);}
}
拦截规则
addPathPatterns表示需要拦截的 URL/**表示拦截任意方法也就是所有方法excludePathPatterns表示需要排除的 URL
新建 Controller 类一个拦截、两个不拦截
package com.example.demo.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
RestController
RequestMapping(/user)
public class UserController {RequestMapping(/getuser)public String getUser() {System.out.println(do getUser());return user;}RequestMapping(/reg)public String reg() {System.out.println(do reg());return reg;}RequestMapping(/login)public String login() {System.out.println(do login());return login;}
}在拦截器里边执行一个 do UserInterceptor
Component
public class UserInterceptor implements HandlerInterceptor {/*** 返回 true表示拦截器验证成功继续执行后续的方法* false:拦截器验证失败不会执行后续目标方法* param request* param response* param handler* return* throws Exception*/Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {System.out.println(do UserInterceptor);//业务方法//得到 Session 对象:判断 Session 中是否有登陆用户有——true无——falseHttpSession session request.getSession(false);//默认 trueif (session ! null session.getAttribute(AppVar.SESSION_KEY) ! null) {//用户已经登陆return true;}return false;}
}运行启动类首先我们先看不拦截的访问 localhost:8080/user/reg 被拦截的访问 localhost:8080/user/getuser 1.3.3 排除所有的静态资源
// 拦截器
Override
public void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new LoginInterceptor()).addPathPatterns(/**) // 拦截所有接⼝.excludePathPatterns(/**/*.js).excludePathPatterns(/**/*.css).excludePathPatterns(/**/*.jpg).excludePathPatterns(/login.html).excludePathPatterns(/**/login); // 排除接⼝
}
/*一级目录/**所有目录
在这里有一个问题就是排除图片图片的格式有很多总不能一个一个排除这样的情况我们可以在 resource 下的 static 创建一个 image 目录把所有图片都放在这里边排除 image 里边的所有东西 .excludePathPatterns(/image/**);1.4 登录拦截器练习
1.登录、注册页面不拦截其他页面拦截
2.当登录成功写入 session 之后拦截的页面也可以正常访问
1.拦截功能
package com.example.demo.config;
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 AppConfig implements WebMvcConfigurer {Autowiredprivate UserInterceptor userInterceptor;Overridepublic void addInterceptors(InterceptorRegistry registry) {//registry.addInterceptor(new UserInterceptor());registry.addInterceptor(userInterceptor).addPathPatterns(/**)//拦截规则/**拦截所有的请求.excludePathPatterns(/login.html).excludePathPatterns(/reg.html).excludePathPatterns(/css/**).excludePathPatterns(/editor/**).excludePathPatterns(/img/**).excludePathPatterns(/js/**).excludePathPatterns(/**/login); // 排除接⼝;}
}2.拦截器
package com.example.demo.config;
import com.example.demo.common.AppVar;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;/*** 自定义拦截器*/
Component
public class UserInterceptor implements HandlerInterceptor {/*** 返回 true表示拦截器验证成功继续执行后续的方法* false:拦截器验证失败不会执行后续目标方法* param request* param response* param handler* return* throws Exception*/Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {System.out.println(do UserInterceptor);//业务方法//得到 Session 对象:判断 Session 中是否有登陆用户有——true无——falseHttpSession session request.getSession(false);//默认 trueif (session ! null session.getAttribute(AppVar.SESSION_KEY) ! null) {//用户已经登陆return true;}return false;}
}
1.5 拦截器原理 所有的 Controller 执行都会通过⼀个调度器 DispatcherServlet 来实现这⼀点可以从 Spring Boot 空制台的打印信息看出 而所有方法都会执行 DispatcherServlet 中的 doDispatch 调度方法源码一部分
//调用预处理【重点】
if (!mappedHandler.applyPreHandle(processedRequest, response)) {return;
} 执行所有的拦截器所有拦截器不等于 false才会进行之后的代码 // 执⾏ Controller 中的业务
mv ha.handle(processedRequest, response, mappedHandler.getHandler());
if (asyncManager.isConcurrentHandlingStarted()) {return;
}
所有的 Controller 执行都会通过⼀个调度器 DispatcherServlet 来实现而所有方法都会执行 DispatcherServlet 中的 doDispatch 调度方法其中会执行 applyPreHandle 方法所有拦截器不等于 false才会执行 Controller 方法
applyPreHandle 源码 boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {for(int i 0; i this.interceptorList.size(); this.interceptorIndex i) {HandlerInterceptor interceptor (HandlerInterceptor)this.interceptorList.get(i);if (!interceptor.preHandle(request, response, this.handler)) {this.triggerAfterCompletion(request, response, (Exception)null);return false;}}return true;} 执行一个目标方法的时候循环所有的拦截器拿到容器中的所有拦截器再去执行拦截器的预执行方法preHandle 方法如果有一个 preHandle 方法为 false就返回 false就不执行后续流程直接返回返回true执行 controller 方法 2.统一异常处理
统⼀异常处理使用的是 ControllerAdvice ExceptionHandler 来实现的ControllerAdvice 表示控制器通知类ExceptionHandler 是异常处理器两个结合表示当出现异常的时候执行某个通知也就是执行某个方法事件 默认返回的是一个页面需要的是一个数据不是页面这个时候需要加 ResponseBody 返回一个数据而 ResponseBody 既可以加到方法上也可以加在类上所以可以直接使用注解 RestControllerAdvice 假设构建一个空指针异常UserController 类
package com.example.demo.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
RestController
RequestMapping(/user)
public class UserController {RequestMapping(/reg)public String reg() {System.out.println(do reg());Object obj null;System.out.println(obj.hashCode());return reg;}
}
定义统一的返回对象
package com.example.demo.common;
import lombok.Data;
//统一的对象
Data
public class ResultAjax {private int code;//状态码private String msg;//状态码的描述信息private Object data;//返回数据
}空指针异常处理
方法名和返回值可以自定义其中最重要的是 ExceptionHandler(Exception.class) 注解
package com.example.demo.config;
import com.example.demo.common.ResultAjax;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
RestControllerAdvice
public class ExceptionAdvice {ExceptionHandler(NullPointerException.class)public ResultAjax doNullPointerException(NullPointerException e) {ResultAjax resultAjax new ResultAjax();resultAjax.setCode(-1);resultAjax.setMsg(空指针异常 e.getMessage());resultAjax.setData(null);return resultAjax;}
}
访问 localhost:8080/user/reg 上述为空指针异常那么异常有很多我们难道全要写这些异常 这个时候我们可以设置一个默认异常所有异常都是基于 Exception
RestControllerAdvice
public class ExceptionAdvice {ExceptionHandler(Exception.class)public ResultAjax doException(Exception e) {ResultAjax resultAjax new ResultAjax();resultAjax.setCode(-1);resultAjax.setMsg(异常 e.getMessage());resultAjax.setData(null);return resultAjax;}
}
3.统一数据返回格式
方便前端程序员更好的接收和解析后端数据接口返回的数据降低前端程序员和后端程序员的沟通成本有利于项⽬统⼀数据的维护和修改有利于后端技术部⻔的统⼀规范的标准制定不会出现稀奇古怪的返回内容
3.1 统一数据处理强制执行
使用 ControllerAdvice实现 ResponseBodyAdvice 接口并重写它的两个方法supports 必须返回 truebeforeBodyWrite 方法中进行重新判断和重写操作
package com.example.demo.config;
import com.example.demo.common.ResultAjax;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
/*** 听译返回值的保底实现类*/
ControllerAdvice
public class ResponseAdvice implements ResponseBodyAdvice {Autowiredprivate ObjectMapper objectMapper;//spring 自带的/*** true - 才会调用 beforeBodyWrite 方法* 反之则永远不会调用 beforeBodyWrite 方法* param returnType* param converterType* return*/Overridepublic boolean supports(MethodParameter returnType, Class converterType) {return true;}Overridepublic Object beforeBodyWrite(Object body, MethodParameter returnType,MediaType selectedContentType, Class selectedConverterType,ServerHttpRequest request, ServerHttpResponse response) {// 已经包装好的对象if (body instanceof ResultAjax) {return body;}//对字符串进行判断和处理if (body instanceof String) {ResultAjax resultAjax ResultAjax.succ(body);try {return objectMapper.writeValueAsString(resultAjax);} catch (JsonProcessingException e) {e.printStackTrace();}}return ResultAjax.succ(body);}
}
RestController
RequestMapping(/user)
public class UserController {RequestMapping(/getnum)public int getNum() {return 1;}RequestMapping(/getstr)public String getStr() {return hello;}
} String 比较特殊既不属于对象也不属于基本数据类型在返回值的时候也是需要单独判断