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

网站建设服务图片google关键词seo

网站建设服务图片,google关键词seo,wordpress edd 卡密,wordpress修改网页SpringBoot 统一功能的处理 文章目录 SpringBoot 统一功能的处理1. 用户登录权限校验1.1 最初用户登录验证1.2 Spring AOP 统一用户登录验证的问题1.3 SpringAOP 拦截器1.3.1 实现自定义拦截器1.3.2 将自定义拦截器加入到系统配置 1.4 拦截器实现原理1.4.1 实现流程图1.4.2 实现…SpringBoot 统一功能的处理 文章目录 SpringBoot 统一功能的处理1. 用户登录权限校验1.1 最初用户登录验证1.2 Spring AOP 统一用户登录验证的问题1.3 SpringAOP 拦截器1.3.1 实现自定义拦截器1.3.2 将自定义拦截器加入到系统配置 1.4 拦截器实现原理1.4.1 实现流程图1.4.2 实现源码剖析 1.5 统一访问前缀添加 2. 统一异常处理2.1 创建一个异常处理类2.2 创建异常检测的类和异常处理方法 3. 统一数据返回3.1为什么需要统一数据返回?3.2 统一数据返回格式的实现3.3 统一异常处理在遇到 String 返回类型时报错的问题3.4 ControllerAdvice 源码剖析 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;} } /** * 某⽅法 2 */ RequestMapping(/m2) public Object method2(HttpServletRequest request) {// 有 session 就获取没有不会创建HttpSession session request.getSession(false);if (session ! null session.getAttribute(userinfo) ! null) {// 说明已经登录业务处理return true;} else {// 未登录return false;} } // 其他⽅法... }从上述代码中可以看出每个方法都相同的登录权限校验 , 这样做的缺点是: 每个方法中都要单独写用户登录验证的方法 , 即使封装成公共方法 , 也一样要在方法中传参判断.添加控制器越多, 调用用户登录的方法也越多 , 这样后期会增大维护成本.用户登录方法与接下来的业务实现没有任何关联 , 但还是要每个方法中写一遍. 因此, 使用 AOP 思想, 进行统一用户登录验证迫在眉睫. 1.2 Spring AOP 统一用户登录验证的问题 一说到用户登录验证 , 第一个想到的方法就是 , 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;} }但是在 Spring AOP 的切面中实现用户登录校验有以下两个缺点: 没法获取到 HttpSession 对象由于需要拦截一部分方法 , 另一部分是不拦截的 , 如注册和登录方法不拦截 , 这样的话排除规则将无法定义. 1.3 SpringAOP 拦截器 Spring 中提供了具体的实现拦截器 HandlerInterceptor , 拦截器的实现分为以下两个步骤: 创建自定义拦截器 , 实现 HandlerInterceptor 接口的 preHandle(执行具体方法之前的预处理) 方法.将自定义拦截器加入 WebMvcConfigurer 的 addInterceptors 方法中. 具体实现如下: 1.3.1 实现自定义拦截器 //定义拦截器 Component public class LoginInterceptor implements HandlerInterceptor { // 调用目标方法之前执行的方法 // 此方法返回 boolean 类型的值 , 如果返回值为 true, 继续执行剩余流程, 否则表示拦截器验证未通过, 剩余的不在执行Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {HttpSession session request.getSession(false);if (session ! null || session.getAttribute(session_userinfo) ! null){return true;}//如果执行失败不能直接给前端返回一个状态码, 后端必须明确告诉前端异常信息, 但状态码必须是200, //原理类似于确认应答, 如果是异常状态码前端无法接收到信息.response.setContentType(application/json;charsetutf8);response.getWriter().println({\code\:-1, \msg\:\登录失败\, \data\:\\});return false;} }1.3.2 将自定义拦截器加入到系统配置 Configuration public class MyConfig implements WebMvcConfigurer {Autowiredprivate LoginInterceptor loginInterceptor;Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(loginInterceptor).addPathPatterns(/**).excludePathPatterns(/user/login)//排除登录.excludePathPatterns(/user/reg);//排除注册} }其中: addPathPatterns() 表示需要拦截的 URLexcludePathPatterns() 表示需要排除的 URL 1.4 拦截器实现原理 1.4.1 实现流程图 Spring 项目中 , 正常的程序调用如下: 然而有了拦截器之后 , 就会在 Controller 之间进行预处理操作: 1.4.2 实现源码剖析 通过观察 Spring Boot 控制台的打印信息可知 , 所有的 Controller 执行都会通过一个调度器 DispatcherServlet 来实现. 所有方法都会执行 DispatcherServlet 中的 doDispatch 调度方法 , doDispatch 源码如下: 通过源码可以看出 , 执行 Controller 之前, 会先调用预处理方法 applyPreHandle() , applyPreHandle() 源码如下: boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {for(int i 0; i this.interceptorList.size(); this.interceptorIndex i) {//获取所有拦截器, 并调用preHandle()方法HandlerInterceptor interceptor (HandlerInterceptor)this.interceptorList.get(i);if (!interceptor.preHandle(request, response, this.handler)) {this.triggerAfterCompletion(request, response, (Exception)null);return false;}}return true;}通过源码可以看出 , applyPreGHandle() 会获取所有拦截器 HandlerInterceptor 并执行其中的 preHandle()方法 , 由此就与上文中的拦截器定义相对应. 通过上述源码分析 , 拦截器也是通过动态代理和环绕通知是思想实现的 , 大体流程如下: 1.5 统一访问前缀添加 在企业开发中 , 如果我们的项目工程较大且多个项目部署到同一台服务器上 , 如果不给具体的项目添加前缀 , 那么就会极大的增加维护成本. eg. 给当前项目所有请求地址添加 api 前缀: Configuaration public class AppConfig implement WebMvcConfigurer(){Overridepublic void configurePathMatch(PathMatchConfigure configure){configure.addPathPrefix(api,c - true)} } 第二个参数为表达式 , 设置 true 表示启动前缀. 那么后续访问时 , URL 都需要加上 api 前缀. 2. 统一异常处理 统一异常处理使用的是 ControllerAdvice ExceptionHandler 来实现的 , ControllerAdvice 表示控制器通知类 , ExceptionHandler 表示异常处理器 , 两个结合表示出现异常时执行某个通知 , 也就是执行某个方法事件 , 具体实现代码如下: 无论后端执行结果如何 , 都会给前端返回一个明确的信息. 2.1 创建一个异常处理类 import java.util.HashMap;ControllerAdvice//针对 Controller 的增强方法, 会检测控制器的异常 public class MyExceptionAdvice{}2.2 创建异常检测的类和异常处理方法 import java.util.HashMap;ControllerAdvice//针对 Controller 的增强方法, 会检测控制器的异常 ResponseBody //返回非静态页面 (数据) public class MyExceptionAdvice{ExceptionHandler(NullPointerException.class)public HashMapString, Object doNullPointerException(NullPointerException e){HashMapString, 0bject result new HashMap();result.put(code, -1);result.put(msg, 空指针: e.getMessage());result.put(data, null);return result;}//默认异常处理, 当具体异常匹配不到时, 执行此方法ExceptionHandler(Exception.class)public HashMapString, Object doException(Exception e){HashMapString, 0bject result new HashMap();result.put(code, -300);result.put(msg, Exception: e.getMessage());result.put(data, null);return result;} }3. 统一数据返回 3.1为什么需要统一数据返回? 方便前端程序员更好的接收和解析数据接口返回的数据降低前后端沟通成本有利于统一的数据维护和修改有利于后端技术部门统一标准的规定 保底策略 , 强制性统一数据返回 , 返回数据之前进行数据重写 3.2 统一数据返回格式的实现 统一返回数据的格式可以使用 ControllerAdvice ResponseBodeyAdvice 的方式实现 , 实现代码如下: ControllerAdvice public class ResponseAdvice implements ResponseBodyAdvice {//只有 true 时, 才会执行 beforeBodyWriter()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 HashMap){return body;}// 重写返回结果, 让其返回一个统一的数据格式HashMapString, Object result new HashMap();result.put(code, 200);result.put(msg, null);result.put(data, body);return result;} }Tips: 实际开发中 , 通常不建议将 HashMap 作为返回类型 , 因为使用 HashMap 作为返回类型无法提供类型信息容易导致数据解析错误或类型转换异常 , 可读性差 , 维护困难. 3.3 统一异常处理在遇到 String 返回类型时报错的问题 当返回类型是 String 时 RequestMapping(/login)public String login(){return login;}控制台抛出异常: 如果剖析一下返回执行流程: 方法返回的是 String统一数据返回之前处理 ---- String 转换为 HashMap将 HashMap 转换为 application/json 字符串给前端 通过抓包可以看出 , 返回给前端的是 json 格式的数据 , 因此异常出现在第三步. 第三步转换时 , 首先查看原 Body 的数据类型: 是 String -- 调用 StringHttpMessageConverter 进行类型转换非 String -- 调用 HttpMessageConverter 进行类型转换 总而言之 , 原本是 HashMap 类型的数据 , 却被判断成 String 类型的数据 , 并调用 StringHttpMessageConverter 进行类型转换 , 于是就出现了 HashMap cannot be cast to java.lang.String 解决方案: 通过修改配置文件将 StringHttpMessageConverter 这个转换器从项目中去除.在统一数据重写时 , 单独处理 String 类型 , 让其返回一个 String 字符串 , 而非 HashMap 解决方案一: Configuration public class MyConfig implements WebMvcConfigurer {/*** 移除 StringHttpMessageConverter()* param converters*/Overridepublic void configureMessageConverters(ListHttpMessageConverter? converters) {converters.removeIf(converter - converters instanceof StringHttpMessageConverter);} }解决方案二: Autowiredprivate ObjectMapper objectMapper;SneakyThrowsOverridepublic Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {//首先判断是否已经是标准格式了if (body instanceof HashMap){return body;}// 重写返回结果, 让其返回一个统一的数据格式HashMapString, Object result new HashMap();result.put(code, 200);result.put(msg, null);result.put(data, body);if (body instanceof HashMap){ // 返回一个 String 字符串objectMapper.writeValueAsString(result);}return result;}3.4 ControllerAdvice 源码剖析 点击 ControllerAdvice 实现源码如下: Target({ElementType.TYPE}) Retention(RetentionPolicy.RUNTIME) Documented Component public interface ControllerAdvice {AliasFor(basePackages)String[] value() default {};AliasFor(value)String[] basePackages() default {};Class?[] basePackageClasses() default {};Class?[] assignableTypes() default {};Class? extends Annotation[] annotations() default {}; }从上述源码中可以看出 ControllerAdvice 派生于 Component 组件 , 而所有的组件初始化都会调用 InitializingBean 接口. 通过查询 InitializingBean , 可以发现其中 Spring MVC 实现子类是 RequestMappingHandlerAdapter , 里面有一个 afterPropertiesSet() 方法 , 表示所有参数设置完成之后执行的方法. package org.springframework.beans.factory;public interface InitializingBean {void afterPropertiesSet() throws Exception; }在 afterPropertiesSet() 中有一个 initControllerAdviceCache 方法, 此方法的源码如下: 分析可知 , 该方法会查找所有的 ControllerAdvice 类 , 这些类未被存入容器中 , 但发生某个时间时 , 会调用相应的 Advice 方法 , 比如返回数据前调用统一数据封装. gHandlerAdapter , 里面有一个 afterPropertiesSet() 方法 , 表示所有参数设置完成之后执行的方法. package org.springframework.beans.factory;public interface InitializingBean {void afterPropertiesSet() throws Exception; }在 afterPropertiesSet() 中有一个 initControllerAdviceCache 方法, 此方法的源码如下: [外链图片转存中…(img-mo8rbC9p-1689386373868)] 分析可知 , 该方法会查找所有的 ControllerAdvice 类 , 这些类未被存入容器中 , 但发生某个时间时 , 会调用相应的 Advice 方法 , 比如返回数据前调用统一数据封装.
http://www.huolong8.cn/news/239766/

相关文章:

  • 做一个网站大概需要多少钱wordpress 商务主题
  • 建开发网站百度竞价排名广告定价鲜花
  • 哪个网站做海南二手房网站导航栏分析
  • 网站建设前台后台设计深圳需要做网站的公司有哪些
  • 学网站开发需要学什么优质企业网站建设
  • 网站空间太小银川市网站建设
  • 网站带支付源码怎么创建网站平台
  • 网站建设效益分析海珠区建网站公司
  • 国外做ui的网站j深圳平台网站建设
  • 企业查询经营异常是怎么回事南昌做网站优化的公司
  • 网站开发员岗位职责天猫网站设计特点
  • 推荐几个看黄的网站静态网站制作视频
  • 智能手机网站开发godaddy如何创建网站
  • 沈阳网站建设包括服务器系统搭建网站源码
  • 自适应网站 seo怎么做郑州seo代理外包
  • 微网站建设哪家优惠编辑wordpress的代码
  • 罗湖附近公司做网站建设哪家好石家庄网站建设优化
  • 网站建设 应酷创意设计椅子
  • 保洁公司网站怎么做鞋店网站建设方案
  • 做网站预算表wordpress内核源码
  • 为什么建设的网站有时候访问慢6石家庄住建局网站
  • sem竞价教程咸阳seo
  • 公司网站维护与更新wordpress语法高亮
  • 常见的网站推广方法有哪些物联网水表
  • 网站管理助手创建数据库福田瑞沃汽车官网
  • 福建专业网站建设公司市场调研公司的最主要职能是
  • 网站营销案例好的优化网站推广公司
  • 永州做网站公司云上城之歌
  • 烟台网站开发网站免费高清素材软件有哪些
  • 自适应网站一般用什么框架做wordpress主页面编辑器