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

商业网站怎么做推广网站大全

商业网站怎么做,推广网站大全,景安香港主机可以做几个网站,网站建设外包行业目录 一、用户登录权限验证 1.1 SpringAOP可以进行处理吗? 1.2 创建自定义拦截器 1.3 将自定义拦截器配置到系统配置项中 1.4 拦截器的实现原理 1.4.1 实现原理源码分析 1.5 统一访问前缀添加 二、统一异常处理 2.1 为什么需要使用统一异常处理?…

目录

一、用户登录权限验证

1.1 SpringAOP可以进行处理吗?

1.2 创建自定义拦截器

 1.3 将自定义拦截器配置到系统配置项中

1.4 拦截器的实现原理

1.4.1 实现原理源码分析

1.5 统一访问前缀添加

二、统一异常处理

2.1 为什么需要使用统一异常处理?

2.2 统一异常处理的实现

三、统一数据返回格式

3.1 为什么需要统一数据返回格式?

3.2 统一数据返回格式的实现

 3.3 返回值为String类型时,应该如何处理?

3.3.1 将 StringHttpMessageConverter 去掉。

3.3.2 在统一数据返回的时候,单独处理String类型,让其返回一个String字符串,而非 HashMap

 总结:


前言:

一般Spring Boot统一功能处理模块,也是AOP的实战环节,要实现课程目标有以下3个:

  • 统一用户登录权限验证
  • 统一数据格式
  • 统一异常处理

一、用户登录权限验证

1.1 SpringAOP可以进行处理吗?

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;}
}

我们知道SpringAOP虽然就提供了对用户登录的处理逻辑,但是存在一些问题:

  • 没有办法获取HttpSession对象
  • 如果要对一部分方法拦截,一部分方法不拦截,这种情况很难处理。(比如注册和登录方法在用户登录权限验证中是不能进行拦截的)

拦截器和SpringAOP虽然都是AOP的实现方式,但是这两个其实是完全不同的技术体系。

Spring提供了具体的实现拦截器:HandlerInterceptor,该SpringBoot 拦截器实现分为以下两个步骤:

  1. 自定义拦截器
  2. 将自定义拦截器配置到系统配置项,并且设置合理的拦截规则

1.2 创建自定义拦截器

自定义拦截器继承HandlerInterceptor后,需要重写相对应的方法,这里我们重写 preHandle方法:

 代码如下:

package com.example.demo.common;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 session = request.getSession(false);if (session != null && session.getAttribute("session_userinfo") != null) {// 用户已经登录return true;}return false;}
}

 1.3 将自定义拦截器配置到系统配置项中

 重写addInterceptors方法:

 设置拦截规则,代码如下

package com.example.demo.config;import com.example.demo.common.LoginInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;public class MyConfig implements WebMvcConfigurer {@AutowiredLoginInterceptor loginInterceptor;@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(loginInterceptor).addPathPatterns("/**") //拦截所有的url.excludePathPatterns("user/login") // url为:user/login 不进行拦截 以下同理.excludePathPatterns("user/reg").excludePathPatterns("image/**"); // image夹目录下的所有url都不进行拦截}
}

或者使用Spring方法,通过DI注入的方式,这样可以实现不用new一个实例:

首先需要将拦截器添加到spring中,也就是给其添加一个五大类注解,这里我们就使用@Component。接着就可以使用@Autowired来得到实例。

 其中:

  • addPathPatterns: 表示需要拦截的URL,“**”表示拦截任意方法(也就是所有方法)。
  • excludePathPatterns: 表示需要排除的URL。

 说明:以上拦截规则可以拦截此项目中的URL,包括静态文件(图片文件,JS和CSS等文件)。

1.4 拦截器的实现原理

下面我们先来看一组正常情况下的调用顺序:

然而有了拦截器之后,会在调用Controller之前进行相应的业务处理,执行的流程如下图所示:

1.4.1 实现原理源码分析

所有的Controller执行都会通过一个调度器DispatcherServlet来实现,这一点可以从Spring Boot控制台的打印信息看出,如下图所示:

在IDEA中,通过全局搜索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;Object 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;}// 实现Controller的业务逻辑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);}}}

观察DispatcherServlet中的某段代码:

我们发现,在执行后续的Controller代码之前,都会先执行这个applyPreHandle方法,于是鼠标双击 applyPreHandle,得到代码如下:

从上述源码可以看出,在applyPreHandle中会获取所有的拦截器HandlerInterceptor并执行拦截器中的preHandle方法,这样就和之前定义的拦截器对应上了,如下图所示:

package com.example.demo.common;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 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 session = request.getSession(false);if (session != null && session.getAttribute("session_userinfo") != null) {// 用户已经登录return true;}response.setContentType("application/json");response.setCharacterEncoding("utf8");response.getWriter().println("asdasd");return false;}
}

1.5 统一访问前缀添加

所有请求地址添加api前缀:

代码如下:

package com.example.demo.config;import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;@Configuration
public class AppConfig implements WebMvcConfigurer {@Overridepublic void configurePathMatch(PathMatchConfigurer configurer) {configurer.addPathPrefix("fox", c -> true);}
}

二、统一异常处理

2.1 为什么需要使用统一异常处理?

通俗来讲,统一异常处理的主要目的是为了方便前端,让其更好的处理后端的信息,尽量将逻辑处理这块放置于后端,前端的目的其实主要是为用户服务。

比如:可以跟前端约定出现异常报错时候的状态码是多少,这样方便前端的处理,也方便后续后端在日志文件中将其找到,并修改异常。

2.2 统一异常处理的实现

统一异常处理使用的是@ControllerAdvice + @ExceptionHandler 来实现的,@ControllerAdvice表示控制器通知类, @ExceptionHandler是异常处理器,两个结合表示当出现异常的时候执行某个通知,也就是执行某个方法事件,具体实现代码如下:

以上方法表示,如果出现了异常就返回给前端一个HashMap对象, 其中包含的字段如代码定义那样。

 注意:

方法名和返回值都是可以自定义的,另外 @ExceptionHandler()中的参数是可以选择的,这里是Exception.class:表示的是可以在程序抛出异常的时候执行这里的代码,让其返回数据给前端,如果填入的参数是NullPointerException:那么表示的是当程序出现空指针异常的时候,会执行这里的代码。

这里的实现逻辑和Java中的异常处理是相似的,如果开发者有对Exception和NullPointerException分别进行了处理,那么当程序出现NullPointerException异常的时候,还是会根据我们写的NullPointerException执行逻辑进行处理,并不会直接走Exception的逻辑。

示例如下:

访问页面后效果如下:

总结:当有多个异常通知时,匹配顺序为当前类及其子类向上依次匹配。

三、统一数据返回格式

3.1 为什么需要统一数据返回格式?

统一数据返回格式的优点如下,比如以下几个:

  • 方便前端程序员更好的接受和解析后端数据接口的数据
  • 降低前端程序员和后端程序员的沟通成本
  • 有利于项目统一数据的维护和修改
  • 有利于后端技术部门的统一规范的标准制定,不会出现稀奇古怪的返回内容

3.2 统一数据返回格式的实现

统一的数据返回格式可以使用@ControllerAdvice + ResponseBodyAdvice 的方式实现,具体实现代码如下:

package com.example.demo.common;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 {/*** 是否执行 beforeBodyWrite 方法, 返回 true 就执行, 返回 false 就不执行* @param returnType* @param converterType* @return*/@Overridepublic boolean supports(MethodParameter returnType, Class converterType) {return true;}/*** 返回数据之前进行数据重写* @param body 原始返回值* @param returnType* @param selectedContentType* @param selectedConverterType* @param request* @param response* @return*/@Overridepublic Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {// 这里我们规定统一的数据返回为HashMapif (body instanceof HashMap) {return body;}// 重写返回结果,让其返回一个统一的数据格式HashMap<String, Object> result = new HashMap<>();result.put("code",200);result.put("data",body);result.put("msg","");return result;}
}

 访问user/login1:

经过统一功能处理后代码展现如下:

 3.3 返回值为String类型时,应该如何处理?

 但是如果将返回值改为String类型,按照以上的执行逻辑,那么就无法走上述的正常数据统一处理:

我们发现,当返回类型为String的时候,程序会抛出异常,从而被我们的 统一异常处理模块拦截。

观察异常信息,发现 抛出异常:java.lang.ClassCastException: java.util.HashMap cannot be cast to java.lang.String

可能会感到奇怪,为什么会抛出这个异常呢?

下面我们来看看后端返回前端时候的执行流程:

1.  一开始,前端访问该网址时,方法返回的是 String:

2. 统一数据返回之前会进行处理,将 String 转换为 HashMap:

3. 将HaspMap转换成 application/json 字符串给前端(接口)

这个步骤有两种情况,先判断原Body的类型:

  • 是 String 类型,那么就会使用 StringHttpMessageConverter 进行类型转换
  • 如果不是 String 类型,那么使用 HttpMessageConverter 进行类型转换

以上报错就是因为原始Body是String类型,所以在类型转换时候报错了

解决方案有如下两种:

  • 将 StringHttpMessageConverter 去掉。
  • 在统一数据返回的时候,单独处理String类型,让其返回一个String字符串,而非HashMap

3.3.1 将 StringHttpMessageConverter 去掉。

在配置文件中使用以下代码即可;

package com.example.demo.config;import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;import java.util.List;@Configuration
public class MyConfig implements WebMvcConfigurer {/*** 移除 StringHttpMessageConverter* @param converters*/@Overridepublic void configureMessageConverters(List<HttpMessageConverter<?>> converters) {converters.removeIf(converter -> converter instanceof StringHttpMessageConverter);}
}

 访问地址后显示如下:

3.3.2 在统一数据返回的时候,单独处理String类型,让其返回一个String字符串,而非 HashMap

引入ObjectMapper(ObjectMapper 是Jackson库中的一个类,用于在Java对象(POJO,Plain Old Java Objects)和JSON数据之间进行相互转换):

对Body为String进行单独处理: 

访问页面如下所示:

 总结:

本文主要介绍了统一用户登录权限的效验,使用WebMvcConfigurer + HandlerInterceptor 来实现。统一异常处理使用 @ControllerAdvice + @ExceptionHandler 来实现,统一返回值处理使用@ControllerAdvice + ResponseBodyAdvice来处理。

http://www.ds6.com.cn/news/114902.html

相关文章:

  • 做视频开头动画网站seo长沙
  • 如何用api做网站网站排名优化软件有哪些
  • 美的公司网站建设的目的网站建设主要推广方式
  • 个人网站建设 免费seo关键词布局案例
  • 汇鑫网站建设设计公司排名
  • 简书网站开发百度搜索使用方法
  • 做网站策划营销型网站的分类不包含
  • 成都软件开发外包公司有哪些济南网站seo哪家公司好
  • 永宝网站建设招聘信息郑州seo外包收费标准
  • 企业微信开发者上海seo推广整站
  • 射阳做网站多少钱哪个网站做推广效果好
  • 网站设计图尺寸网站建设找哪家公司好
  • 许昌哪里做网站58和百度哪个推广效果好
  • 唐山个人网站建设网站关键词优化软件
  • 安宁网站建设深圳外贸网站推广
  • 找网站建设公司哪家好sem竞价托管费用
  • 基于html的网站开发山东疫情最新消息
  • 如何建设网站设计品牌企业seo咨询
  • 用户界面设计模板合肥网站优化推广方案
  • 软文营销的写作技巧有哪些seo搜索引擎优化5
  • 量子秘密网站怎么做线下推广渠道有哪些方式
  • 海纳网站建设百度推广官方网站
  • 为网站做seo需要什么网站推广技术
  • wordpress 4.9 站群热搜关键词
  • 公司网站开发立项文档百度竞价教程
  • h5做网站深圳广告公司
  • 响应式网站自助建站太原百度网站快速优化
  • 洛阳做天然气公司网站欧洲网站服务器
  • 怎么做有趣的视频网站百度推广开户电话
  • 做网站的盈利模式seort什么意思