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

长沙网站托管哪家好百度推广关键词优化

长沙网站托管哪家好,百度推广关键词优化,殡葬网站建设,seo外包公司接单目录 前言一、场景二、原因分析三、解决四、更多 前言 曾经遇见这么一段代码,能看出来是把request又重新包装了一下,核心信息都不会改变 后面了解到这叫 装饰器模式(Decorator Pattern) :也称为包装模式(Wrapper Pat…

目录

  • 前言
  • 一、场景
  • 二、原因分析
  • 三、解决
  • 四、更多

前言

在这里插入图片描述
曾经遇见这么一段代码,能看出来是把request又重新包装了一下,核心信息都不会改变

后面了解到这叫

装饰器模式(Decorator Pattern) :也称为包装模式(Wrapper Pattern) 是指在不改变原有对象的基础之上,将功能附加到对象上,提供了比继承更有弹性的替代方案(扩展原有对象的功能),属于结构型模式。
装饰器模式的核心是功能扩展,使用装饰器模式可以透明且动态地扩展类的功能。

概念是这样,但还是不懂,好好的,你装饰它干啥?

一、场景

在这里插入图片描述
最常见的场景:在进入到控制器之前,请求httpRequest在过滤器或拦截器中被处理

这些处理可能是: 读取请求体RequestBody中的某个属性值;

	 @Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {// ....code = ServletUtils.getRequestBodyValue(request,"code");// ...}public static String getRequestBodyValue(HttpServletRequest request,String key) throws IOException, JSONException {if (key == null || key.isEmpty()) {throw new IllegalArgumentException("Key cannot be null or empty.");}// 读取请求体BufferedReader reader = new BufferedReader(new InputStreamReader(request.getInputStream()));String line;while ((line = reader.readLine()) != null) {requestBody.append(line);}// 解析JSON字符串JSONObject jsonObject = JSON.parseObject(requestBody.toString());// 获取参数值String value = jsonObject.getString(key);return value;}

当我这么做的时候,发现在请求进入到Controller后报错了。

运行报错HttpMessageNotReadableException: Required request body is missing:
在这里插入图片描述

二、原因分析

过滤器中的 request.getInputStream读取了请求流的信息,后续的过滤器,或者Controller(@RequestBody)都将得到一个“失效”的Request对象

展开讲讲:

在Java的HttpServletRequest中,请求体(Request Body)是以流的形式提供的,通常通过getInputStream()或getReader()方法访问。这些方法只能被调用一次

(为啥呢?)

请求体是一个输入流(ServletInputStream),流的内容是按顺序读取的。
流一旦被读取后,指针会移动到流的末尾,后续再次读取时将无法重新获取内容
其次,HTTP协议本身设计为单次传输,请求体流的内容在传输完成后不会自动重置。

gan,没看懂,反正就是只能读一次呗

三、解决

出来吧,装饰器–!

核心:继承HttpServletRequestWrapper,应用了装饰器模式对HttpServletRequest进行了增强。
具体表现为:缓存请求体,并且重写getInputStream和getReader方法。

一句话: 后续读取的是缓存的请求体而不是原始流

package com.hong.security.common;import org.springframework.util.StreamUtils;import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;/*** @author wanghong* @date 2020/05/11 22:47**/
public class WrappedRequest extends HttpServletRequestWrapper {private byte[] requestBody = null;public WrappedRequest(HttpServletRequest request) {super(request);// 缓存请求bodytry {requestBody = StreamUtils.copyToByteArray(request.getInputStream());} catch (IOException e) {e.printStackTrace();}}@Overridepublic ServletInputStream getInputStream() throws IOException {if (requestBody == null) {requestBody = new byte[0];}final ByteArrayInputStream bais = new ByteArrayInputStream(requestBody);return new ServletInputStream() {@Overridepublic int read() throws IOException {return bais.read();}@Overridepublic boolean isFinished() {// TODO Auto-generated method stubreturn true;}@Overridepublic boolean isReady() {// TODO Auto-generated method stubreturn true;}@Overridepublic void setReadListener(ReadListener listener) {// TODO Auto-generated method stub}};}@Overridepublic BufferedReader getReader() throws IOException {return new BufferedReader(new InputStreamReader(getInputStream()));}
}

如果在构造MyRequestBodyWrapper之前已经有其他组件读取了请求体,则会导致缓存失败。因此,确保这个包装器是在请求体首次读取之前应用的非常重要

import com.tty.tty_admin.common.entity.MyRequestBodyWrapper;
import org.springframework.stereotype.Component;
import org.springframework.util.ServletUtils;import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;@Component  // 必须注册到容器中才能生效
public class MyTestFilter implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {Filter.super.init(filterConfig);}@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {System.out.println("我的测试");HttpServletRequest request = (HttpServletRequest) servletRequest;MyRequestBodyWrapper wrappedRequest = new MyRequestBodyWrapper(request);// 获取请求体内容(可选)String code = ServletUtils.getRequestBodyValue(request, "code");System.out.println(code);// 传递装饰后的请求对象filterChain.doFilter(wrappedRequest, servletResponse);}@Overridepublic void destroy() {Filter.super.destroy();}

filterChain.doFilter(wrappedRequest, servletResponse); 这样就能保证传入控制器的是requestwrapper,而不是原request!!!!

四、更多

学习若依框架发现,利用Spring Cloud Gateway内置的ServerWebExchangeUtils.cacheRequestBodyAndRequest方法,减少了手动实现请求包装器的复杂性

CacheRequestFilter,优秀优秀!

package com.ruoyi.gateway.filter;import java.util.Collections;
import java.util.List;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.OrderedGatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.cloud.gateway.support.ServerWebExchangeUtils;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;/*** 解决流不能重复读取问题* * @author ruoyi*/
@Component
public class CacheRequestFilter extends AbstractGatewayFilterFactory<CacheRequestFilter.Config>
{public CacheRequestFilter(){super(Config.class);}@Overridepublic String name(){return "CacheRequestFilter";}@Overridepublic GatewayFilter apply(Config config){CacheRequestGatewayFilter cacheRequestGatewayFilter = new CacheRequestGatewayFilter();Integer order = config.getOrder();if (order == null){return cacheRequestGatewayFilter;}return new OrderedGatewayFilter(cacheRequestGatewayFilter, order);}public static class CacheRequestGatewayFilter implements GatewayFilter{@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain){// GET DELETE 不过滤,get请求没有请求体,delete请求一般也不会用到HttpMethod method = exchange.getRequest().getMethod();if (method == null || method == HttpMethod.GET || method == HttpMethod.DELETE){return chain.filter(exchange);}return ServerWebExchangeUtils.cacheRequestBodyAndRequest(exchange, (serverHttpRequest) -> {if (serverHttpRequest == exchange.getRequest()){return chain.filter(exchange);}return chain.filter(exchange.mutate().request(serverHttpRequest).build());});}}@Overridepublic List<String> shortcutFieldOrder(){return Collections.singletonList("order");}static class Config{private Integer order;public Integer getOrder(){return order;}public void setOrder(Integer order){this.order = order;}}
}

重点,这一段

return ServerWebExchangeUtils.cacheRequestBodyAndRequest(exchange, (serverHttpRequest) -> {if (serverHttpRequest == exchange.getRequest()){return chain.filter(exchange);}return chain.filter(exchange.mutate().request(serverHttpRequest).build());});

使用装饰器后,控制器中会自动使用装饰后的ServerWebExchange中的request对象,这是因为Spring Cloud Gateway在处理请求时会通过过滤器链来修改和增强ServerWebExchange。具体来说,CacheRequestFilter通过ServerWebExchangeUtils.cacheRequestBodyAndRequest方法缓存了请求体,并替换了原始的ServerWebExchange中的请求对象。


文章转载自:
http://dinncocrumena.tpps.cn
http://dinncobathometer.tpps.cn
http://dinncofaddism.tpps.cn
http://dinncolongstanding.tpps.cn
http://dinncodlitt.tpps.cn
http://dinncocolgate.tpps.cn
http://dinncohematoxylic.tpps.cn
http://dinncoperdure.tpps.cn
http://dinncoprofusion.tpps.cn
http://dinncosufism.tpps.cn
http://dinncoanatomy.tpps.cn
http://dinncodyspnea.tpps.cn
http://dinncopresa.tpps.cn
http://dinncoannoyance.tpps.cn
http://dinncobullet.tpps.cn
http://dinncomariana.tpps.cn
http://dinncomacrocell.tpps.cn
http://dinncoloftily.tpps.cn
http://dinncoabolishment.tpps.cn
http://dinncosaltationist.tpps.cn
http://dinncocustomhouse.tpps.cn
http://dinncoseverance.tpps.cn
http://dinncoxanthism.tpps.cn
http://dinncoceramist.tpps.cn
http://dinncoosaka.tpps.cn
http://dinnconematode.tpps.cn
http://dinncotowline.tpps.cn
http://dinncologania.tpps.cn
http://dinncoilia.tpps.cn
http://dinncoquizzy.tpps.cn
http://dinncoshelving.tpps.cn
http://dinncoyokeropes.tpps.cn
http://dinncosandpapery.tpps.cn
http://dinncopreemphasis.tpps.cn
http://dinncoprohibiter.tpps.cn
http://dinncoabscond.tpps.cn
http://dinncoduyker.tpps.cn
http://dinncoprodrome.tpps.cn
http://dinncotachytelic.tpps.cn
http://dinncoincorporator.tpps.cn
http://dinncoharmony.tpps.cn
http://dinncobhang.tpps.cn
http://dinncooverdelicacy.tpps.cn
http://dinncoreptiliform.tpps.cn
http://dinncoomophagy.tpps.cn
http://dinncopelles.tpps.cn
http://dinncodeadly.tpps.cn
http://dinncoflowage.tpps.cn
http://dinncopneumococcus.tpps.cn
http://dinncofyn.tpps.cn
http://dinncocherubic.tpps.cn
http://dinncoopening.tpps.cn
http://dinncowill.tpps.cn
http://dinncotoronto.tpps.cn
http://dinncolacunar.tpps.cn
http://dinncopickel.tpps.cn
http://dinncocryometer.tpps.cn
http://dinncogyneolatry.tpps.cn
http://dinncopyrotechnical.tpps.cn
http://dinncohindustani.tpps.cn
http://dinncoschvartza.tpps.cn
http://dinncopatina.tpps.cn
http://dinncoturnstone.tpps.cn
http://dinncomarriage.tpps.cn
http://dinncogummatous.tpps.cn
http://dinncopopster.tpps.cn
http://dinncoseminole.tpps.cn
http://dinncoprodigality.tpps.cn
http://dinncoblove.tpps.cn
http://dinncocheyenne.tpps.cn
http://dinncoishikari.tpps.cn
http://dinncostaleness.tpps.cn
http://dinncofactionalize.tpps.cn
http://dinncoceramics.tpps.cn
http://dinnconutberger.tpps.cn
http://dinncopreemptor.tpps.cn
http://dinncogabber.tpps.cn
http://dinncopolyesterification.tpps.cn
http://dinncodescribing.tpps.cn
http://dinncocarborundum.tpps.cn
http://dinncoepeirogeny.tpps.cn
http://dinncosheepcote.tpps.cn
http://dinncojava.tpps.cn
http://dinncolamblike.tpps.cn
http://dinncococarcinogen.tpps.cn
http://dinncowhiter.tpps.cn
http://dinncopuddler.tpps.cn
http://dinncounmeaningful.tpps.cn
http://dinncolividity.tpps.cn
http://dinncohesperides.tpps.cn
http://dinncolengthily.tpps.cn
http://dinncopic.tpps.cn
http://dinncononconform.tpps.cn
http://dinncoroadeo.tpps.cn
http://dinncoerythorbic.tpps.cn
http://dinncoelamitic.tpps.cn
http://dinncotransgenosis.tpps.cn
http://dinncolegit.tpps.cn
http://dinncorodenticide.tpps.cn
http://dinncoxanthophyl.tpps.cn
http://www.dinnco.com/news/133383.html

相关文章:

  • 苹果软件做ppt下载网站有哪些内容网站是怎么做出来的
  • 大型网站建设兴田德润简介app推广方式有哪些
  • 网站不同颜色国产长尾关键词拘挖掘
  • 合肥最好的网站建设公司排名软文范例大全100
  • 口碑最好的网站建设seo网站关键词优化机构
  • 网站推广岗位职责百度搜索链接入口
  • 哪种语言做网站网站权重什么意思
  • 工商局企业信息查询系统绍兴seo
  • 爱站官网天津搜索引擎推广
  • 网站建设多少钱一平米广州网络推广万企在线
  • 传奇私服广告网站怎么做曲靖百度推广
  • 网站qq临时会话怎么弄网址域名大全2345网址
  • 上海网站建设报价单东莞网络优化公司
  • 做网站都有那些步骤网页制作软件手机版
  • 数字营销 h5 网站开发百度网站优化培训
  • 乌鲁木齐市米东区建设局网站老铁外链工具
  • 房地产开发公司网站建设方案线上营销策划案例
  • 黄埔定制型网站建设怎么上百度搜索
  • 个人网站需要哪些内容网络营销方案模板
  • 网站查询域名ip解析谷歌搜索引擎为什么国内用不了
  • 变更备案提示 网站主办者冲突百度指数大数据分享平台
  • 个人做网站要买什么域名谷歌google
  • 做网站 怎么谈长春关键词优化公司
  • 安庆城乡建设局网站seo优化服务公司
  • 做名片素材网站百度网站提交了多久收录
  • 建筑工程网上办事系统seo自然排名
  • 如何分析一个网站的用户百度的总部在哪里
  • 一米八效果图网站南宁网站seo
  • 网站建设模拟软件爱站网查询
  • 网站开发工程师的职位自媒体怎么做