使用自定义参数解析器同一个参数支持多种Content-Type

目录
  • 一堆废话
  • 探究Springmvc参数解析器工作流程
  • 不想看废话的可以直接进结果
  • 补充

一堆废话

事出有因, 原先上线的接口现在被要求用Java重写,按照原暴露出去的文档然后毫无疑问的,按照Java的惯例,

一定是@RequestBody然后去接收application/json;charset=utf-8,然后一通参数接收处理逻辑。

结果测试都通过了,上线的时候,刚把原接口切到新接口上,日志就狂飙

application/x-www-form-urlencoded;charset=utf-8 NOT SUPPORT

What?然后就一通问号脸。赶紧把接口切回到老接口,然后跑去问PHP的同事,什么情况,原对接参数不是json吗?

然后才明白,草,原来要同时支持application/json;charset=utf-8和application/x-www-form-urlencoded;charset=utf-8

PHP咱是不懂的,但是Java对这个需求的原生支持却不是很好,印象中没有现成的。

因为一般我们定义对象接收参数,如果使用了@RequestBody接收,那么传参一定要使用post+一个对应的参数解析器一个可读的流,按照现在的情况即application/json;charset=utf-8。

要么是直接一个对象接收,不要加任何注解,这个时候对应的Content-Type是application/x-www-form-urlencoded;charset=utf-8则参数可正常解析。

但是这两种情况是矛盾的,如果一个加了@RequestBody的参数对应的Content-Type是application/x-www-form-urlencoded;charset=utf-8, 则最终无法解析。反过来如果一个未加@RequestBody的参数对应的Content-Type是application/json;charset=utf-8则也无法解析。

那么现在就只能来看一下如何定义一个自定义的参数解析器来完成这个需求了。但是这个自定义的参数解析器还有点不太一样,因为数据格式本身不是我们自定义的,本身就存在对应标准的解析器。只是SpringMVC在根据参数去找对应解析器的时候没有对应起来。我们现在只要让自己的解析器能够让这个参数转发到对应可以解析的参数解析器上就可以了。

探究Springmvc参数解析器工作流程

现在就要不怕麻烦的还看一下原来的参数解析器是如何工作的,毕竟不知道它怎么写的我也不知道怎么抄。

SpringMVC项目,二话不说,直接找到org.springframework.web.servlet.DispatcherServlet#doDispatch这个方法,看整个处理器的流程,这里直接简化找到最终映射到方法后的执行

// Actually invoke the handler.
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

方法跳转流程如下

public abstract class AbstractHandlerMethodAdapter extends WebContentGenerator implements HandlerAdapter, Ordered {
 @Override
 @Nullable
 public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
   throws Exception {
  return handleInternal(request, response, (HandlerMethod) handler);
 }
}

我再跳

org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#handleInternal
public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter
  implements BeanFactoryAware, InitializingBean {
 /**
  * 参数解析器列表
  */
 @Nullable
 private HandlerMethodArgumentResolverComposite argumentResolvers;

 @Override
 protected ModelAndView handleInternal(HttpServletRequest request,
   HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
  ModelAndView mav;
  checkRequest(request);
  // 这里删除了大量相关判断方法,只关注实际跳转执行方法
  // No synchronization on session demanded at all...
  mav = invokeHandlerMethod(request, response, handlerMethod);
 }

 /**
  * 上面跳到了这里
  */
 @Nullable
 protected ModelAndView invokeHandlerMethod(HttpServletRequest request,
   HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
  // 这里又删除了大量的代码
  ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);
  // 将本类自己的参数解析器列表赋值给ServletInvocableHandlerMethod
  if (this.argumentResolvers != null) {
   invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
  }
  if (this.returnValueHandlers != null) {
   invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);
  }
  invocableMethod.setDataBinderFactory(binderFactory);
  invocableMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);
  // 带着使命继续往下执行
  invocableMethod.invokeAndHandle(webRequest, mavContainer);
 }
}

接着跳到了

org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod#invokeAndHandle
public class ServletInvocableHandlerMethod extends InvocableHandlerMethod {
 public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer,
   Object... providedArgs) throws Exception {
  Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);
  // 再删除无关代码
 }
}

这里总算看到了一些关键信息了

org.springframework.web.method.support.InvocableHandlerMethod#invokeForRequest
public class InvocableHandlerMethod extends HandlerMethod {
 @Nullable
 public Object invokeForRequest(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer,
   Object... providedArgs) throws Exception {
  // 这里就是解析参数
  Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);
  if (logger.isTraceEnabled()) {
   logger.trace("Arguments: " + Arrays.toString(args));
  }
  return doInvoke(args);
 }

 /**
  * 上面方法跳到了这里
  */
 protected Object[] getMethodArgumentValues(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer,
   Object... providedArgs) throws Exception {
  // 这里就是获取入参的参数类型,如单个字符串的每个参数,或者是某个对象参数,甚至是HttpServletRequest
  MethodParameter[] parameters = getMethodParameters();
  if (ObjectUtils.isEmpty(parameters)) {
   return EMPTY_ARGS;
  }

  Object[] args = new Object[parameters.length];
  // 下面就是遍历每个参数类型,然后挨个解析
  for (int i = 0; i < parameters.length; i++) {
   MethodParameter parameter = parameters[i];
   parameter.initParameterNameDiscovery(this.parameterNameDiscoverer);
   args[i] = findProvidedArgument(parameter, providedArgs);
   if (args[i] != null) {
    continue;
   }
   // org.springframework.web.method.support.HandlerMethodArgumentResolverComposite#supportsParameter
   // 后面就贴出了这个方法的内部,就是遍历所有的参数解析器判断是否能够解析当前参数
   if (!this.resolvers.supportsParameter(parameter)) {
    throw new IllegalStateException(formatArgumentError(parameter, "No suitable resolver"));
   }
   try {
       // 获取参数解析器,解析当前参数
    args[i] = this.resolvers.resolveArgument(parameter, mavContainer, request, this.dataBinderFactory);
   }
   catch (Exception ex) {
    // Leave stack trace for later, exception may actually be resolved and handled...
    if (logger.isDebugEnabled()) {
     String exMsg = ex.getMessage();
     if (exMsg != null && !exMsg.contains(parameter.getExecutable().toGenericString())) {
      logger.debug(formatArgumentError(parameter, exMsg));
     }
    }
    throw ex;
   }
  }
  return args;
 }
}

上面关于找到参数解析器的关键代码

org.springframework.web.method.support.HandlerMethodArgumentResolverComposite
public class HandlerMethodArgumentResolverComposite implements HandlerMethodArgumentResolver {
  private final List<HandlerMethodArgumentResolver> argumentResolvers = new LinkedList<>();
 private final Map<MethodParameter, HandlerMethodArgumentResolver> argumentResolverCache =
   new ConcurrentHashMap<>(256);

 /**
  * 判断参数是否能够找到对应的参数解析器
  */
 @Override
 public boolean supportsParameter(MethodParameter parameter) {
  return getArgumentResolver(parameter) != null;
 }

 @Nullable
 private HandlerMethodArgumentResolver getArgumentResolver(MethodParameter parameter) {
  // 这里指向一个本地缓存,如果一个参数类型可以被某个参数解析器解析,则缓存下次无须遍历
  HandlerMethodArgumentResolver result = this.argumentResolverCache.get(parameter);
  if (result == null) {
      // 遍历所有的参数解析器,判断是否支持当前参数类型
   for (HandlerMethodArgumentResolver resolver : this.argumentResolvers) {
    if (resolver.supportsParameter(parameter)) {
     result = resolver;
     // 如果支持则放入本地缓存,下次直接从缓存中取
     this.argumentResolverCache.put(parameter, result);
     break;
    }
   }
  }
  return result;
 }

 @Override
 @Nullable
 public Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer,
   NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception {
  // 获取该参数类型对应的参数解析器
  HandlerMethodArgumentResolver resolver = getArgumentResolver(parameter);
  if (resolver == null) {
   throw new IllegalArgumentException("Unsupported parameter type [" +
     parameter.getParameterType().getName() + "]. supportsParameter should be called first.");
  }
  // 解析参数
  return resolver.resolveArgument(parameter, mavContainer, webRequest, binderFactory);
 }
}

通过对

org.springframework.web.method.support.HandlerMethodArgumentResolverComposite#getArgumentResolver

的调试, 我们贴出几张图来说明系统中目前所有的参数解析器,以及我们目前需要的用来解析@RequestBody和application/x-www-form-urlencoded对应的参数解析器

application/x-www-form-urlencoded对应的解析器为ServletModelAttributeMethodProcessor
@RequestBody application/json对应的解析器为RequestResponseBodyMethodProcessor
public class RequestResponseBodyMethodProcessor extends AbstractMessageConverterMethodProcessor {
 @Override
 public boolean supportsParameter(MethodParameter parameter) {
     // 可以看到必须要有RequestBody这个注解,该参数解析器才会工作
  return parameter.hasParameterAnnotation(RequestBody.class);
 }
}

顺便说下为什么我们在controller方法入参的时候写HttpServletRequest和HttpServletResponse也能够入参进来,就是因为有对应的参数解析器,这里也给找出来了

org.springframework.web.servlet.mvc.method.annotation.ServletRequestMethodArgumentResolver
org.springframework.web.servlet.mvc.method.annotation.ServletResponseMethodArgumentResolver

不想看废话的可以直接进结果

定义一个注解用于标注在参数上,用以标识这个参数希望用我们的参数解析器进行解析

import java.lang.annotation.*;
/**
 * <p>标识参数可以被多个参数解析器尝试进行参数解析</p >
 *
 * 同一个参数支持application/json和application/x-www-form-urlencoded
 *
 * @see com.company.content.risk.order.common.handle.MultiArgumentResolverMethodProcessor
 * @author Snowball
 * @version 1.0
 * @date 2020/08/31 18:57
 */
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MultiArgumentResolver {
}

实现一个自定义参数解析器,要实现接口org.springframework.web.method.support.HandlerMethodArgumentResolver。在解析方法里我们去判断当前客户端传入的Content-Type, 如果是application/json则将参数解析交给RequestResponseBodyMethodProcessor, 如果是application/x-www-form-urlencoded, 则将参数解析交给ServletModelAttributeMethodProcessor。

HandlerMethodArgumentResolver接口要实现两个方法

  • supportsParameter 判断当前解析器是否支持入参对象
  • resolveArgument 解析逻辑
import com.company.content.risk.order.common.annotation.MultiArgumentResolver;
import com.google.common.collect.ImmutableList;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.MethodParameter;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.HandlerMethodArgumentResolverComposite;
import org.springframework.web.method.support.ModelAndViewContainer;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;
import org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor;
import org.springframework.web.servlet.mvc.method.annotation.ServletModelAttributeMethodProcessor;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
 * 自定义参数解析器用以支持同一个参数支持application/json和application/x-www-form-urlencoded解析
 *
 * @see MultiArgumentResolver
 * @author Snowball
 * @version 1.0
 * @date 2020/08/31 19:00
 */
public class MultiArgumentResolverMethodProcessor implements HandlerMethodArgumentResolver  {
    @Autowired
    private RequestMappingHandlerAdapter requestMappingHandlerAdapter;
    private static final String CONTENT_TYPE_JSON = "application/json";
    private static final String CONTENT_TYPE_FORM_URLENCODED = "application/x-www-form-urlencoded";
    /**
     * 支持的content_type
     */
    private static final ImmutableList<String> SUPPORT_CONTENT_TYPE_LIST = ImmutableList.of(CONTENT_TYPE_JSON, CONTENT_TYPE_FORM_URLENCODED);
    /**
     * 参考这个写法, 同一个类型的参数解析后缓存对应的参数解析器,不过这里的key改为了Content-Type
     * @see HandlerMethodArgumentResolverComposite#argumentResolverCache
     */
    private final Map<String, HandlerMethodArgumentResolver> argumentResolverCache =
            new ConcurrentHashMap<>(8);
    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        return parameter.getParameter().isAnnotationPresent(MultiArgumentResolver.class);
    }
    /**
     * 解析参数
     */
    @Override
    public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
        String contentType = webRequest.getHeader("Content-Type");
        isSupport(contentType);
        List<HandlerMethodArgumentResolver> argumentResolvers = requestMappingHandlerAdapter.getArgumentResolvers();
        HandlerMethodArgumentResolver handlerMethodArgumentResolver = argumentResolverCache.get(contentType);
        if (handlerMethodArgumentResolver != null) {
            return handlerMethodArgumentResolver.resolveArgument(parameter, mavContainer, webRequest, binderFactory);
        }
        for (HandlerMethodArgumentResolver argumentResolver : argumentResolvers) {
            if (isJson(contentType) && argumentResolver instanceof RequestResponseBodyMethodProcessor) {
                argumentResolverCache.put(contentType, argumentResolver);
                return argumentResolver.resolveArgument(parameter, mavContainer, webRequest, binderFactory);
            } else if (isFormUrlEncoded(contentType) && argumentResolver instanceof ServletModelAttributeMethodProcessor) {
                argumentResolverCache.put(contentType, argumentResolver);
                return argumentResolver.resolveArgument(parameter, mavContainer, webRequest, binderFactory);
            }
        }
        return null;
    }
    private boolean isJson(String contentType) {
        return contentType.contains(CONTENT_TYPE_JSON);
    }
    private boolean isFormUrlEncoded(String contentType) {
        return contentType.contains(CONTENT_TYPE_FORM_URLENCODED);
    }
    /**
     * 判断当前参数解析器是否支持解析当前的Content-Type
     * @param contentType
     * @return
     * @throws HttpMediaTypeNotSupportedException
     */
    private boolean isSupport(String contentType) throws HttpMediaTypeNotSupportedException {
        if (contentType == null) {
            throw new HttpMediaTypeNotSupportedException("contentType不能为空");
        }
        boolean isMatch = false;
        for (String item : SUPPORT_CONTENT_TYPE_LIST) {
            if (contentType.contains(item)) {
                isMatch = true;
                break;
            }
        }
        if (!isMatch) {
            throw new HttpMediaTypeNotSupportedException("支持Content-Type" + SUPPORT_CONTENT_TYPE_LIST.toString());
        }
        return true;
    }

将参数解析器注册成bean,添加到系统参数解析器列表即可

import com.company.content.risk.order.common.handle.MultiArgumentResolverMethodProcessor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.util.List;
/**
 * <p>web核心配置</p >
 *
 * @author Snowball
 * @version 1.0
 * @date 2020/08/31 18:57
 */
@Configuration
@Order
public class CoreWebConfig implements WebMvcConfigurer {
    /**
     * 注册自定义参数解析器
     * @return
     */
    @Bean
    public MultiArgumentResolverMethodProcessor multiArgumentResolverMethodProcessor() {
        return new MultiArgumentResolverMethodProcessor();
    }
    /**
     * 添加自定义参数解析器
     * @param resolvers
     */
    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
        resolvers.add(0, multiArgumentResolverMethodProcessor());
    }
}

使用,将@MultiArgumentResolver标识在controller方法的某个入参对象即可

@PostMapping(value = "text/submit")
public OutApiResponse<OutTextResponseBody> submitText(@MultiArgumentResolver OutTextRequest outTextRequest) {
}

补充

在上面自定义参数解析器的类中,注入了一个bean,类为RequestMappingHandlerAdapter, 目的是为了从这个类中获取到目前系统中已有的参数解析器列表。那么如何知道这个类里面包含了哪些参数解析器呢?摘录相关代码如下。这个类实现了接口InitializingBean,在bean初始化完成后调用afterPropertiesSet,然后在里面判断加入了默认的参数解析器列表

public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter
		implements BeanFactoryAware, InitializingBean {
	@Nullable
	private HandlerMethodArgumentResolverComposite argumentResolvers;

	@Override
	public void afterPropertiesSet() {
		// Do this first, it may add ResponseBody advice beans
		initControllerAdviceCache();
		if (this.argumentResolvers == null) {
			List<HandlerMethodArgumentResolver> resolvers = getDefaultArgumentResolvers();
			this.argumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);
		}
	}
	private List<HandlerMethodArgumentResolver> getDefaultArgumentResolvers() {
		List<HandlerMethodArgumentResolver> resolvers = new ArrayList<>();
		// Annotation-based argument resolution
		resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), false));
		resolvers.add(new RequestParamMapMethodArgumentResolver());
		resolvers.add(new PathVariableMethodArgumentResolver());
		resolvers.add(new PathVariableMapMethodArgumentResolver());
		resolvers.add(new MatrixVariableMethodArgumentResolver());
		resolvers.add(new MatrixVariableMapMethodArgumentResolver());
		resolvers.add(new ServletModelAttributeMethodProcessor(false));
		resolvers.add(new RequestResponseBodyMethodProcessor(getMessageConverters(), this.requestResponseBodyAdvice));
		resolvers.add(new RequestPartMethodArgumentResolver(getMessageConverters(), this.requestResponseBodyAdvice));
		resolvers.add(new RequestHeaderMethodArgumentResolver(getBeanFactory()));
		resolvers.add(new RequestHeaderMapMethodArgumentResolver());
		resolvers.add(new ServletCookieValueMethodArgumentResolver(getBeanFactory()));
		resolvers.add(new ExpressionValueMethodArgumentResolver(getBeanFactory()));
		resolvers.add(new SessionAttributeMethodArgumentResolver());
		resolvers.add(new RequestAttributeMethodArgumentResolver());
		// Type-based argument resolution
		resolvers.add(new ServletRequestMethodArgumentResolver());
		resolvers.add(new ServletResponseMethodArgumentResolver());
		resolvers.add(new HttpEntityMethodProcessor(getMessageConverters(), this.requestResponseBodyAdvice));
		resolvers.add(new RedirectAttributesMethodArgumentResolver());
		resolvers.add(new ModelMethodProcessor());
		resolvers.add(new MapMethodProcessor());
		resolvers.add(new ErrorsMethodArgumentResolver());
		resolvers.add(new SessionStatusMethodArgumentResolver());
		resolvers.add(new UriComponentsBuilderMethodArgumentResolver());
		// Custom arguments
		if (getCustomArgumentResolvers() != null) {
			resolvers.addAll(getCustomArgumentResolvers());
		}
		// Catch-all
		resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), true));
		resolvers.add(new ServletModelAttributeMethodProcessor(true));
		return resolvers;
	}
}

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • 详解Http请求中Content-Type讲解以及在Spring MVC中的应用

    详解Http请求中Content-Type讲解以及在Spring MVC中的应用 引言: 在Http请求中,我们每天都在使用Content-type来指定不同格式的请求信息,但是却很少有人去全面了解content-type中允许的值有多少,这里将讲解Content-Type的可用值,以及在spring MVC中如何使用它们来映射请求信息. 1.  Content-Type MediaType,即是Internet Media Type,互联网媒体类型:也叫做MIME类型,在Http协议消息头中,

  • SpringBoot如何解析参数的深入理解

    前言 前几天笔者在写Rest接口的时候,看到了一种传值方式是以前没有写过的,就萌生了一探究竟的想法.在此之前,有篇文章曾涉及到这个话题,但那篇文章着重于处理流程的分析,并未深入. 本文重点来看几种传参方式,看看它们都是如何被解析并应用到方法参数上的. 一.HTTP请求处理流程 不论在SpringBoot还是SpringMVC中,一个HTTP请求会被DispatcherServlet类接收,它本质是一个Servlet,因为它继承自HttpServlet.在这里,Spring负责解析请求,匹配到Co

  • Spring boot中自定义Json参数解析器的方法

    一.介绍 用过springMVC/spring boot的都清楚,在controller层接受参数,常用的都是两种接受方式,如下 /** * 请求路径 http://127.0.0.1:8080/test 提交类型为application/json * 测试参数{"sid":1,"stuName":"里斯"} * @param str */ @RequestMapping(value = "/test",method = Re

  • spring接口通过配置支持返回多种格式(xml,json,html,excel)

    1. 简介 本文主要给大家介绍使用SpringMVC的后端服务如何通过配置来支持多种返回值类型(xml,json,html,excel) 这里的代码使用的是springboot,下载地址:https://github.com/xiagn825/springboot-todolist/tree/springboot-ContentNegotiation 2. 基础概念 2.1 HttpHeader中Content-Type和Accept设置的区别 Accept:接口要返回给客户端的数据格式 cur

  • 使用自定义参数解析器同一个参数支持多种Content-Type

    目录 一堆废话 探究Springmvc参数解析器工作流程 不想看废话的可以直接进结果 补充 一堆废话 事出有因, 原先上线的接口现在被要求用Java重写,按照原暴露出去的文档然后毫无疑问的,按照Java的惯例, 一定是@RequestBody然后去接收application/json;charset=utf-8,然后一通参数接收处理逻辑. 结果测试都通过了,上线的时候,刚把原接口切到新接口上,日志就狂飙 application/x-www-form-urlencoded:charset=utf-

  • SpringBoot项目实用功能之实现自定义参数解析器

    核心点 1.实现接口 org.springframework.web.method.support.HandlerMethodArgumentResolver supportsParameter 方法根据当前方法参数决定是否需要应用当前这个参数解析器 resolveArgument 执行具体的解析过程 2.将自实现的参数解析器类 添加到Spring容器中 3.实现 org.springframework.web.servlet.config.annotation.WebMvcConfigurer

  • Spring自定义参数解析器代码实例

    这篇文章主要介绍了Spring自定义参数解析器代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 结合redis编写User自定义参数解析器UserArgumentResolver import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import org.springframework.beans.factory.annotation

  • 详解如何在SpringBoot中自定义参数解析器

    目录 前言 1.自定义参数解析器 2.PrincipalMethodArgumentResolver 3.RequestParamMapMethodArgumentResolver 4.小结 前言 在一个 Web 请求中,参数我们无非就是放在地址栏或者请求体中,个别请求可能放在请求头中. 放在地址栏中,我们可以通过如下方式获取参数: String javaboy = request.getParameter("name "); 放在请求体中,如果是 key/value 形式,我们可以通

  • Python参数解析器configparser简介

    目录 1.configparser介绍 2.安装: 3.获取所有的section 4.获取指定section下的option 5.获取指定section的K-V 6.获取指定value(1) 7.获取指定value(2) 8.value数据类型 9.value数据类型还原eval() 10.封装 1.configparser介绍 configparser是python自带的配置参数解析器.可以用于解析.config文件中的配置参数.ini文件中由sections(节点)-key-value组成

  • 三种Java自定义DNS解析器方法与实践

    目录 1.InMemoryDnsResolver 2.SystemDefaultDnsResolver 3.自定义DnsResolver 4.连接池管理器 5.测试 前言: 最近终于用上了高性能的测试机(54C96G * 3),相较之前的单机性能提升了三倍,数量提升了三倍,更关键的宽带提单机升了30倍不止,总体讲提升了100多倍,这下再也不用担心单机压力机瓶颈,直接原地起飞. 不过没高兴5分钟,我发现接口居然请求不通,经过一阵拨乱反正终于找到原因:域名无法解析,IP无法直接访问. 自然而然,解决

  • SpringBoot使用自定义json解析器的使用方法

    Spring-Boot是基于Spring框架的,它并不是对Spring框架的功能增强,而是对Spring的一种快速构建的方式. Spring-boot应用程序提供了默认的json转换器,为Jackson.示例: pom.xml中dependency配置: <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

  • python 如何利用argparse解析命令行参数

    命令行参数工具是我们非常常用的工具,比如当我们做实验希望调节参数的时候,如果参数都是通过硬编码写在代码当中的话,我们每次修改参数都需要修改对应的代码和逻辑显然这不太方便.比较好的办法就是把必要的参数设置成通过命令行传入的形式,这样我们只需要在运行的时候修改参数就可以了. sys.argv 解析命令行传入参数最简单的办法就是通过sys.argv,sys.argv可以获取到我们通过命令行传入的参数. import sys print(sys.argv) 用法很简单,只需要调用sys.argv即可.a

  • java SpringBoot自定义注解,及自定义解析器实现对象自动注入操作

    # java-SpringBoot自定义参数解析器实现对象自动注入 解析器逻辑流程图表 后台解析注解的解析器 首先,我在java后台编写了一个解析器,代码如下 import com.ruoyi.framework.interceptor.annotation.LoginUser; import com.ruoyi.project.WebMoudle.WebUser.domain.WebUser; import com.ruoyi.project.WebMoudle.WebUser.service

随机推荐