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

网站建设维护人员网站网页设计是什么

网站建设维护人员,网站网页设计是什么,郴州新网招聘信息,有关网站建设的app前言#x1f36d; ❤️❤️❤️SSM专栏更新中#xff0c;各位大佬觉得写得不错#xff0c;支持一下#xff0c;感谢了#xff01;❤️❤️❤️ Spring Spring MVC MyBatis_冷兮雪的博客-CSDN博客 本章是讲Spring Boot 统⼀功能处理模块#xff0c;也是 AOP 的实战环节 ❤️❤️❤️SSM专栏更新中各位大佬觉得写得不错支持一下感谢了❤️❤️❤️ Spring Spring MVC MyBatis_冷兮雪的博客-CSDN博客 本章是讲Spring Boot 统⼀功能处理模块也是 AOP 的实战环节要实现的目标有以下 3 个 使用拦截器实现用户登录权限的统一验证 统⼀数据格式返回 统⼀异常处理。 一、用户登录权限效验 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 方法来进行统⼀的用户登录权限验证迫在眉睫。 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 比较难 那这样如何解决呢 Spring 拦截器 对于以上问题 Spring 中提供了具体的实现拦截器HandlerInterceptor拦截器的实现分为以下两个步骤 创建自定义拦截器实现 HandlerInterceptor 接口的 preHandle执行具体方法之前的预处理方法。 将自定义拦截器加入WebMvcConfigurer 的 addInterceptors 方法中。 具体实现如下 目录结构 Ⅰ、实现拦截器 关键步骤: a.实现 HandlerInterceptor 接口 b.重写 preHeadler 方法在方法中编写自己的业务代码 package com.example.demo.config;import org.springframework.web.servlet.HandlerInterceptor;import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession;public class LoginInterceptor implements HandlerInterceptor {/*** 此方法返回一个 boolean如果为 true 表示验证成功可以继续执行后续流程如果是 false 表示验证失败后面的流程不能执行了* param request* param response* param handler* return* throws Exception*/Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {//用户登录业务判断HttpSession sessionrequest.getSession(false);if (session ! null session.getAttribute(userinfo) ! null) {// 说明用户已经登录return true;}// 可以调整到登录页面 or 返回一个 401/403 没有权限码response.sendRedirect(/login.html); // response.setStatus(403);return false;} }Ⅱ、将拦截器添加到配置文件中并且设置拦截的规则 package com.example.demo.config;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 {Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new LoginInterceptor()).addPathPatterns(/**) // 拦截所有请求.excludePathPatterns(/user/login) // 排除的url地址不拦截的url地址.excludePathPatterns(/user/reg);} }其中 addPathPatterns表示需要拦截的 URL**表示拦截任意方法也就是所有方法。 excludePathPatterns表示需要排除的 URL。 说明以上拦截规则可以拦截此项目中的使用 URL包括静态文件图片文件、JS 和 CSS 等文件。 排除所有的静态资源 // 拦截器Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new LoginInterceptor()).addPathPatterns(/**) // 拦截所有接⼝.excludePathPatterns(/**/*.js).excludePathPatterns(/**/*.css).excludePathPatterns(/**/*.jpg).excludePathPatterns(/login.html).excludePathPatterns(/**/login); // 排除接⼝} UserController: package com.example.demo.controller;import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController;RestController RequestMapping(/user) public class UserController {/* GetMappingpublic String getMethod(){return 执行GET请求;}PostMappingpublic String postMethod(){return 执行POST请求;}*/RequestMapping(/getuser)public String getUser() {System.out.println(执行了 get User~);return get user;}RequestMapping(/login)public String login() {System.out.println(执行了 login~);return login~;}RequestMapping(/reg)public String reg() {System.out.println(执行了 reg~);return reg~;} }Ⅲ、启动项目 不拦截  拦截http://localhost:8080/user/getuser  为什么会显示重定向次数过多 这是因为这个login.html页面也被拦截了所以它去访问时候就会一直重定向重定向去访问。 解决方法 Ⅳ、拦截器实现原理 正常情况下的调用顺序 然而有了拦截器之后会在调用 Controller 之前进行相应的业务处理执行的流程如下图所示  所有的 Controller 执行都会通过⼀个调度器 DispatcherServlet 来实现这⼀点可以从 Spring Boot 控制台的打印信息看出如下图所示: 而所有方法都会执行 DispatcherServlet 中的 doDispatch 调度方法doDispatch 源码如下:  protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {HttpServletRequest processedRequest request;HandlerExecutionChain mappedHandler null;boolean multipartRequestParsed false;WebAsyncManager asyncManager WebAsyncUtils.getAsyncManager(request);try {try {ModelAndView mv null;Exception dispatchException null;try {processedRequest this.checkMultipart(request);multipartRequestParsed processedRequest ! request;mappedHandler this.getHandler(processedRequest);if (mappedHandler null) {this.noHandlerFound(processedRequest, response);return;}HandlerAdapter ha this.getHandlerAdapter(mappedHandler.getHandler());String method request.getMethod();boolean isGet HttpMethod.GET.matches(method);if (isGet || HttpMethod.HEAD.matches(method)) {long lastModified ha.getLastModified(request, mappedHandler.getHandler());if ((new ServletWebRequest(request, response)).checkNotModified(lastModified) isGet) {return;}}if (!mappedHandler.applyPreHandle(processedRequest, response)) {return;}mv ha.handle(processedRequest, response, mappedHandler.getHandler());if (asyncManager.isConcurrentHandlingStarted()) {return;}this.applyDefaultViewName(processedRequest, mv);mappedHandler.applyPostHandle(processedRequest, response, mv);} catch (Exception var20) {dispatchException var20;} catch (Throwable var21) {dispatchException new NestedServletException(Handler dispatch failed, var21);}this.processDispatchResult(processedRequest, response, mappedHandler, mv, (Exception)dispatchException);} catch (Exception var22) {this.triggerAfterCompletion(processedRequest, response, mappedHandler, var22);} catch (Throwable var23) {this.triggerAfterCompletion(processedRequest, response, mappedHandler, new NestedServletException(Handler processing failed, var23));}} finally {if (asyncManager.isConcurrentHandlingStarted()) {if (mappedHandler ! null) {mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);}} else if (multipartRequestParsed) {this.cleanupMultipart(processedRequest);}}} 从上述源码可以看出在开始执行 Controller 之前会先调用 预处理方法 applyPreHandle而applyPreHandle 方法的实现源码如下 boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {for(int i 0; i this.interceptorList.size(); this.interceptorIndex i) { // 获取项⽬中使⽤的拦截器 HandlerInterceptorHandlerInterceptor interceptor (HandlerInterceptor)this.interceptorList.get(i);if (!interceptor.preHandle(request, response, this.handler)) {this.triggerAfterCompletion(request, response, (Exception)null);return false;}}return true;} 从上述源码可以看出在 applyPreHandle 中会获取所有的拦截器 HandlerInterceptor 并执行拦截器中的 preHandle 方法这样就和咱们前面定义的拦截器对应上了如下图所示 此时用户登录权限的验证方法就会执行这就是拦截器的实现原理。   二、统⼀异常处理 Ⅰ、实现 统一异常处理使用的是 ControllerAdvice ExceptionHandler 来实现的ControllerAdvice 表示控制器通知类ExceptionHandler 是异常处理器两个结合表示当出现异常的时候执行某个通知 也就是执行某个方法事件具体实现代码如下 package com.example.demo.config;import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseBody;import java.util.HashMap;ControllerAdvice ResponseBody public class MyExHandler {/*** 拦截所有的空指针异常进行统一的数据返回*/ExceptionHandler(NullPointerException.class)public HashMapString, Object nullException(NullPointerException e) {HashMapString, Object result new HashMap();result.put(code, -1);result.put(msg, 空指针异常 e.getMessage()); // 错误码的描述信息result.put(data, null);return result;}ExceptionHandler(Exception.class)//保底的默认异常public HashMapString, Object exception(Exception e) {HashMapString, Object result new HashMap();result.put(code, -1);result.put(msg, 异常 e.getMessage()); // 错误码的描述信息result.put(data, null);return result;}}Ⅱ、添加异常 UserController RequestMapping(/login)public String login() {Object obj null;obj.hashCode();System.out.println(执行了 login~);return login~;}RequestMapping(/reg)public String reg() {int num 10 / 0;System.out.println(执行了 reg~);return reg~;} Ⅲ、启动程序 login  reg 方法名和返回值可以自定义其中最重要的是 ExceptionHandler(Exception.class) 注解。  以上方法表示如果出现了异常就返回给前端⼀个 HashMap 的对象其中包含的字段如代码中定义的那样。 我们可以针对不同的异常返回不同的结果。  三、统一数据返回格式 1.创建一个类并添加 ControllerAdvice 2.实现ResponseBodyAdvice接口并重写supports和beforeBodywrite (统一对象就是此方法中实现的) 1、为什么需要统一数据返回格式 统一数据返回格式的优点有很多比如以下几个 方便前端程序员更好的接收和解析后端数据接口返回的数据。 降低前端程序员和后端程序员的沟通成本按照某个格式实现就行了因为所有接口都是这样返回的。 有利于项目统⼀数据的维护和修改。 有利于后端技术部门的统⼀规范的标准制定不会出现稀奇古怪的返回内容。 2、统一数据返回格式的实现 Ⅰ、实现 统⼀的数据返回格式可以使用 ControllerAdvice ResponseBodyAdvice 的方式实现。 package com.example.demo.config;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;import java.util.HashMap;ControllerAdvice public class ResponseAdvice implements ResponseBodyAdvice {Autowiredprivate ObjectMapper objectMapper;/*** 此方法返回 true 则执行下面 beforeBodyWrite 方法* 反之则不执行*/Overridepublic boolean supports(MethodParameter returnType, Class converterType) {return true;}Overridepublic Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {HashMapString, Object result new HashMap();result.put(code, 200);result.put(msg, );result.put(data, body);// 需要特殊处理因为 String 在转换的时候会报错if (body instanceof String) {try {return objectMapper.writeValueAsString(result);} catch (JsonProcessingException e) {e.printStackTrace();}}return result;} }如果没有对Sting进行特殊处理就会有异常出现  Ⅱ、添加实现类 UserController RequestMapping(/getnum)public Integer getNumber() {return new Random().nextInt(10);}RequestMapping(/getuser)public String getUser() {System.out.println(执行了 get User~);return get user;} Ⅲ、启动程序 Ⅳ、总结 上面只是以一种简单的方式来向大家介绍如何去统一数据返回格式在实际工作中并不会这样去使用 而是将统⼀的返回格式包含status、data、msg 字段进行封装成一个类 根据不同操作成功和操作失败的情况重写了不同的方法 package com.example.demo.common;import lombok.Data;import java.io.Serializable;/*** 统一数据格式返回*/ Data public class AjaxResult implements Serializable {//支持序列化// 状态码private Integer code;// 状态码描述信息private String msg;// 返回的数据private Object data;/*** 操作成功返回的结果需要 data*/public static AjaxResult success(Object data) {AjaxResult result new AjaxResult();result.setCode(200);result.setMsg();result.setData(data);return result;}//重载successpublic static AjaxResult success(int code, Object data) {AjaxResult result new AjaxResult();result.setCode(code);result.setMsg();result.setData(data);return result;}public static AjaxResult success(int code, String msg, Object data) {AjaxResult result new AjaxResult();result.setCode(code);result.setMsg(msg);result.setData(data);return result;}/*** 返回失败结果*/public static AjaxResult fail(int code, String msg) {AjaxResult result new AjaxResult();result.setCode(code);result.setMsg(msg);result.setData(null);return result;}public static AjaxResult fail(int code, String msg, Object data) {AjaxResult result new AjaxResult();result.setCode(code);result.setMsg(msg);result.setData(data);return result;} }
http://www.huolong8.cn/news/1968/

相关文章: