当前位置: 首页 > news >正文

上海环球金融中心造价珠海seo推广

上海环球金融中心造价,珠海seo推广,深圳企易科技有限公司,机械网站建设营销目录 1.用户登陆权限验证 1.1 每个方法验证 1.2 Spring AOP 用户统一登陆验证 1.3 拦截器 1.3.1 自定义拦截器 1.3.2 将自定义拦截器配置到系统设置中,并且设置拦截规则 1.3.3 排除所有的静态资源 1.4 登录拦截器(练习) 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

  1. 创建自定义拦截器,实现 HandlerInterceptor 接口的 preHandle(执行具体方法之前的预处理)方法
  2. 将自定义拦截器加入 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 必须返回 true,beforeBodyWrite 方法中进行重新判断和重写操作
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 比较特殊,既不属于对象,也不属于基本数据类型,在返回值的时候也是需要单独判断

http://www.hrbkazy.com/news/8632.html

相关文章:

  • 用网站模板建站网络热词2021
  • 在国外做盗版网站吗百度seo引流
  • 一个空间怎么做两个网站百度搜索量排名
  • 网上怎么接单做网站天津网络广告公司
  • 珠海一元夺宝网站建设百度竞价包年推广是怎么回事
  • 网站导航app关键词搜索工具爱站网
  • 专业做包装的电商网站河南品牌网络推广外包
  • 广州英文建站公司网页制作软件下载
  • 中国网站建设网页设计百度竞价优化排名
  • java公司网站怎么做广东seo网站推广代运营
  • 网站开发项目答辩主持词网络营销环境分析
  • 公司网站建设与管理的作用网页百度网盘
  • 个人网站备案网站内容网络营销的优缺点
  • 虚拟主机做视频网站可以吗百度搜索百度
  • 叶县网站建设猪肉价格最新消息
  • 网站免费做招生宣传丽水百度seo
  • 自制聊天软件网站标题优化排名
  • 企业自建网站青岛seo经理
  • 免费做网站平台谷歌浏览器直接打开
  • 网站建设建站知识上海网站快速排名提升
  • 国内跨境电商建站系统百度关键词搜索推广
  • 重庆市网站建设百度快照怎么优化排名
  • php做网站首页的代码口碑营销的主要手段有哪些
  • 网络域名的网站如何宣传推广产品
  • 深圳b2b2c网站建设如何做好关键词的优化
  • 做教育网站还挣钱吗百度seo收费
  • 成武县住房和城乡建设厅网站百度搜索引擎使用技巧
  • 天津塘沽网站建设谷歌sem推广
  • 深圳网站建设设计科技有限公司什么优化
  • 安溪人做的网站长沙做引流推广的公司