广告
返回顶部
首页 > 资讯 > 后端开发 > Python >Dubbo服务校验参数的解决方案
  • 862
分享到

Dubbo服务校验参数的解决方案

2024-04-02 19:04:59 862人浏览 八月长安

Python 官方文档:入门教程 => 点击学习

摘要

目录一、背景二、解决方案2.1Maven依赖2.2接口定义2.3dubbo服务提供者端配置2.4Dubbo服务消费者端配置2.5验证参数校验三、定制Dubbo参数校验异常返回3.1V

本文分享了如何对Dubbo服务进行优雅的参数校验,以实现服务端统一的数据返回格式,同时也在一定程度提升开发效率,避免重复简单的参数校验逻辑.

一、背景

服务端在向外提供接口服务时,不管是对前端提供Http接口,还是面向内部其他服务端提供的rpc接口,常常会面对这样一个问题,就是如何优雅的解决各种接口参数校验问题?

早期大家在做面向前端提供的HTTP接口时,对参数的校验可能都会经历这几个阶段:每个接口每个参数都写定制校验代码、提炼公共校验逻辑、自定义切面进行校验、通用标准的校验逻辑。

这边提到的通用标准的校验逻辑指的就是基于jsR303的Java Bean Validation,其中官方指定的具体实现就是 Hibernate Validator,在WEB项目中结合spring可以做到很优雅的去进行参数校验。

本文主要也是想给大家介绍下如何在使用Dubbo时做好优雅的参数校验。

二、解决方案

Dubbo框架本身是支持参数校验的,同时也是基于JSR303去实现的,我们来看下具体是怎么实现的。

2.1 maven依赖

<!-- 定义在facade接口模块的pom文件找那个 -->
<dependency>
    <groupId>javax.validation</groupId>
    <artifactId>validation-api</artifactId>
    <version>2.0.1.Final</version>
<!-- 如果不想facade包有多余的依赖,此处scope设为provided,否则可以删除 -->
    <scope>provided</scope>
</dependency>
 
<!-- 下面依赖通常加在Facade接口实现模块的pom文件中 -->
<dependency>
    <groupId>org.hibernate.validator</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>6.2.0.Final</version>
</dependency>

2.2 接口定义

facade接口定义:

public interface UserFacade {
    FacadeResult<Boolean> updateUser(UpdateUserParam param);
}

参数定义

public class UpdateUserParam implements Serializable {
    private static final long serialVersionUID = 2476922055212727973L;
 
    @NotNull(message = "用户标识不能为空")
    private Long id;
    @NotBlank(message = "用户名不能为空")
    private String name;
    @NotBlank(message = "用户手机号不能为空")
    @Size(min = 8, max = 16, message="电话号码长度介于8~16位")
    private String phone;
 
    // getter and setter ignored
}

公共返回定义


public class FacadeResult<T> implements Serializable {
    private static final long serialVersionUID = 8570359747128577687L;
 
    private int code;
    private T data;
    private String msg;
    // getter and setter ignored
}

2.3 Dubbo服务提供者端配置

Dubbo服务提供者端必须作这个validation="true"的配置,具体示例配置如下:

Dubbo接口服务端配置

<bean class="com.xxx.demo.UserFacadeImpl" id="userFacade"/>
<dubbo:service interface="com.xxx.demo.UserFacade" ref="userFacade" validation="true" />

2.4 Dubbo服务消费者端配置

这个根据业务方使用习惯不作强制要求,但建议配置上都加上validation="true",示例配置如下:

<dubbo:reference id="userFacade" interface="com.xxx.demo.UserFacade" validation="true" />

2.5 验证参数校验

前面几步完成以后,验证这一步就比较简单了,消费者调用该约定接口,接口入参传入UpdateUserParam对象,其中字段不用赋值,然后调用服务端接口就会得到如下的参数异常提示:

Dubbo接口服务端配置

javax.validation.ValidationException: Failed to validate service: com.xxx.demo.UserFacade, method: updateUser, cause: [ConstraintViolationImpl{interpolatedMessage='用户名不能为空', propertyPath=name, rootBeanClass=class com.xxx.demo.UpdateUserParam, messageTemplate='用户名不能为空'}, ConstraintViolationImpl{interpolatedMessage='用户手机号不能为空', propertyPath=phone, rootBeanClass=class com.xxx.demo.UpdateUserParam, messageTemplate='用户手机号不能为空'}, ConstraintViolationImpl{interpolatedMessage='用户标识不能为空', propertyPath=id, rootBeanClass=class com.xxx.demo.UpdateUserParam, messageTemplate='用户标识不能为空'}]
javax.validation.ValidationException: Failed to validate service: com.xxx.demo.UserFacade, method: updateUser, cause: [ConstraintViolationImpl{interpolatedMessage='用户名不能为空', propertyPath=name, rootBeanClass=class com.xxx.demo.UpdateUserParam, messageTemplate='用户名不能为空'}, ConstraintViolationImpl{interpolatedMessage='用户手机号不能为空', propertyPath=phone, rootBeanClass=class com.xxx.demo.UpdateUserParam, messageTemplate='用户手机号不能为空'}, ConstraintViolationImpl{interpolatedMessage='用户标识不能为空', propertyPath=id, rootBeanClass=class com.xxx.demo.UpdateUserParam, messageTemplate='用户标识不能为空'}]
    at org.apache.dubbo.validation.filter.ValidationFilter.invoke(ValidationFilter.java:96)
    at org.apache.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:83)
    ....
    at org.apache.dubbo.remoting.exchange.support.header.HeaderExchangeHandler.received(HeaderExchangeHandler.java:175)
    at org.apache.dubbo.remoting.transport.DecodeHandler.received(DecodeHandler.java:51)
    at org.apache.dubbo.remoting.transport.dispatcher.ChannelEventRunnable.run(ChannelEventRunnable.java:57)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)

三、定制Dubbo参数校验异常返回

从前面内容我们可以很轻松的验证,当消费端调用Dubbo服务时,参数如果不合法就会抛出相关异常信息,消费端调用时也能识别出异常信息,似乎这样就没有问题了。

但从前面所定义的服务接口来看,一般业务开发会定义统一的返回对象格式(如前文示例中的FacadeResult),对于业务异常情况,会约定相关异常码并结合相关性信息提示。因此对于参数校验不合法的情况,服务调用方自然不希望服务端抛出一大段包含堆栈信息的异常信息,而是希望还保持这种统一的返回形式,就如下面这种返回所示:

Dubbo接口服务端配置:

{ 
  "code": 1001,
  "msg": "用户名不能为空",
  "data": null
}

3.1 ValidationFilter & JValidator

想要做到返回格式的统一,我们先来看下前面所抛出的异常是如何来的?

从异常堆栈内容我们可以看出这个异常信息返回是由ValidationFilter抛出的,从名字我们可以猜到这个是采用Dubbo的Filter扩展机制的一个内置实现,当我们对Dubbo服务接口启用参数校验时(即前文Dubbo服务配置中的validation="true"),该Filter就会真正起作用,我们来看下其中的关键实现逻辑:

@Override
public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
    if (validation != null && !invocation.getMethodName().startsWith("$")
            && ConfigUtils.isNotEmpty(invoker.getUrl().getMethodParameter(invocation.getMethodName(), VALIDATION_KEY))) {
        try {
            Validator validator = validation.getValidator(invoker.getUrl());
            if (validator != null) {
                // 注1
                validator.validate(invocation.getMethodName(), invocation.getParameterTypes(), invocation.getArguments());
            }
        } catch (RpcException e) {
            throw e;
        } catch (ValidationException e) {
            // 注2
            return AsyncRpcResult.newDefaultAsyncResult(new ValidationException(e.getMessage()), invocation);
        } catch (Throwable t) {
            return AsyncRpcResult.newDefaultAsyncResult(t, invocation);
        }
    }
    return invoker.invoke(invocation);
}

从前文的异常堆栈信息我们可以知道异常信息是由上述代码「注2」处所产生,这边是因为捕获了ValidationException,通过走读代码或者调试可以得知,该异常是由「注1」处valiator.validate方法所产生。

而Validator接口在Dubbo框架中实现只有JValidator,这个通过idea工具显示Validator所有实现的UML类图可以看出(如下图所示),当然调试代码也可以很轻松定位到。

既然定位到JValidator了,我们就继续看下它里面validate方法的具体实现,关键代码如下所示:

@Override
public void validate(String methodName, Class<?>[] parameterTypes, Object[] arguments) throws Exception {
    List<Class<?>> groups = new ArrayList<>();
    Class<?> methodClass = methodClass(methodName);
    if (methodClass != null) {
        groups.add(methodClass);
    }
    Set<ConstraintViolation<?>> violations = new HashSet<>();
    Method method = clazz.getMethod(methodName, parameterTypes);
    Class<?>[] methodClasses;
    if (method.isAnnotationPresent(MethodValidated.class)){
        methodClasses = method.getAnnotation(MethodValidated.class).value();
        groups.addAll(Arrays.asList(methodClasses));
    }
    groups.add(0, Default.class);
    groups.add(1, clazz);
 
    Class<?>[] classgroups = groups.toArray(new Class[groups.size()]);
 
    Object parameterBean = getMethodParameterBean(clazz, method, arguments);
    if (parameterBean != null) {
        // 注1
        violations.addAll(validator.validate(parameterBean, classgroups ));
    }
 
    for (Object arg : arguments) {
        // 注2
        validate(violations, arg, classgroups);
    }
 
    if (!violations.isEmpty()) {
        // 注3
        logger.error("Failed to validate service: " + clazz.getName() + ", method: " + methodName + ", cause: " + violations);
        throw new ConstraintViolationException("Failed to validate service: " + clazz.getName() + ", method: " + methodName + ", cause: " + violations, violations);
    }
}

从上述代码中可以看出当「注1」和注「2」两处代码进行参数校验时所得到的「违反约束」的信息都被加入到violations集合中,而在「注3」处检查到「违反约束」不为空时,就会抛出包含「违反约束」信息的ConstraintViolationException,该异常继承自ValidationException,这样也就会被ValidationFilter中方法所捕获,进而向调用方返回相关异常信息。

3.2 自定义参数校验异常返回

从前一小节我们可以很清晰的了解到了为什么会抛出那样的异常信息给调用方,如果想做到我们前面想要的诉求:统一返回格式,我们需要按照下面的步骤去实现。

3.2.1 自定义Filter

@Activate(group = {CONSUMER, PROVIDER}, value = "customValidationFilter", order = 10000)
public class CustomValidationFilter implements Filter {
 
    private Validation validation;
 
    public void setValidation(Validation validation) { this.validation = validation; }
 
    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
        if (validation != null && !invocation.getMethodName().startsWith("$")
                && ConfigUtils.isNotEmpty(invoker.getUrl().getMethodParameter(invocation.getMethodName(), VALIDATION_KEY))) {
            try {
                Validator validator = validation.getValidator(invoker.getUrl());
                if (validator != null) {
                    validator.validate(invocation.getMethodName(), invocation.getParameterTypes(), invocation.getArguments());
                }
            } catch (RpcException e) {
                throw e;
            } catch (ConstraintViolationException e) {// 这边细化了异常类型
                // 注1
                Set<ConstraintViolation<?>> violations = e.getConstraintViolations();
                if (CollectionUtils.isNotEmpty(violations)) {
                    ConstraintViolation<?> violation = violations.iterator().next();// 取第一个进行提示就行了
                    FacadeResult facadeResult = FacadeResult.fail(ErrorCode.INVALID_PARAM.getCode(), violation.getMessage());
                    return AsyncRpcResult.newDefaultAsyncResult(facadeResult, invocation);
                }
                return AsyncRpcResult.newDefaultAsyncResult(new ValidationException(e.getMessage()), invocation);
            } catch (Throwable t) {
                return AsyncRpcResult.newDefaultAsyncResult(t, invocation);
            }
        }
        return invoker.invoke(invocation);
    }
}

该自定义filter与内置的ValidationFilter唯一不同的地方就在于「注1」处所新增的针对特定异常ConstraintViolationException的处理,从异常对象中获取包含的「违反约束」信息,并取其中第一个来构造业务上所定义的通用数据格式FacadeResult对象,作为Dubbo服务接口调用返回的信息。

3.2.2 自定义Filter的配置

开发过Dubbo自定义filter的同学都知道,要让它生效需要作一个符合SPI规范的配置,如下所示:

a. 新建两级目录分别是META-INF和dubbo,这个需要特别注意,不能直接新建一个目录名为「META-INFO.dubbo」,否则在初始化启动的时候会失败。

b. 新建一个文件名为com.alibaba.dubbo.rpc.Filter,当然也可以是org.apache.dubbo.rpc.Filter,Dubbo开源到Apache社区后,默认支持这两个名字。

c. 文件中配置内容为:customValidationFilter=com.xxx.demo.dubbo.filter.CustomValidationFilter。

3.3.3 Dubbo服务配置

有了自定义参数校验的Filter配置后,如果只做到这的话,其实还有一个问题,应用启动后会有两个参数校验Filter生效。当然可以通过指定Filter的order来实现自定义Filter先执行,但很显然这种方式不稳妥,而且两个Filter的功能是重复的,因此只需要一个生效就可以了,Dubbo提供了一种机制可以禁用指定的Filter,只需在Dubbo配置文件中作如下配置即可:

<!-- 需要禁用的filter以"-"开头并加上filter名称 -->
<!-- 查看源码,可看到需要禁用的ValidationFilter名为validation-->
<dubbo:provider filter="-validation"/>

但经过上述配置后,发现customValidationFilter并没有生效,经过调试以及对dubbo相关文档的学习,对Filter生效机制有了一定的了解。

a. dubbo启动后,默认会生效框架自带的一系列Filter;

可以在dubbo框架的资源文件org.apache.dubbo.rpc.Filter中看到具体有哪些,不同版本的内容可能会有些许差别。

cache=org.apache.dubbo.cache.filter.CacheFilter
validation=org.apache.dubbo.validation.filter.ValidationFilter  // 注1
echo=org.apache.dubbo.rpc.filter.EchoFilter
generic=org.apache.dubbo.rpc.filter.GenericFilter
genericimpl=org.apache.dubbo.rpc.filter.GenericImplFilter
token=org.apache.dubbo.rpc.filter.TokenFilter
accesslog=org.apache.dubbo.rpc.filter.AccessLogFilter
activelimit=org.apache.dubbo.rpc.filter.ActiveLimitFilter
classloader=org.apache.dubbo.rpc.filter.ClassLoaderFilter
context=org.apache.dubbo.rpc.filter.ContextFilter
consumercontext=org.apache.dubbo.rpc.filter.ConsumerContextFilter
exception=org.apache.dubbo.rpc.filter.ExceptionFilter
executelimit=org.apache.dubbo.rpc.filter.ExecuteLimitFilter
deprecated=org.apache.dubbo.rpc.filter.DeprecatedFilter
compatible=org.apache.dubbo.rpc.filter.CompatibleFilter
timeout=org.apache.dubbo.rpc.filter.TimeoutFilter
tps=org.apache.dubbo.rpc.filter.TpsLimitFilter
trace=org.apache.dubbo.rpc.protocol.dubbo.filter.TraceFilter
future=org.apache.dubbo.rpc.protocol.dubbo.filter.FutureFilter
monitor=org.apache.dubbo.monitor.support.MonitorFilter
metrics=org.apache.dubbo.monitor.dubbo.MetricsFilter

如上「注1」中的Filter就是我们上一步配置中想要禁用的Filter,因为这些filter都是Dubbo内置的,所以这些filter集合有一个统一的名字,default,因此如果想全部禁用,除了一个一个禁用外,也可以直接用'-default'达到目的,这些默认内置的filter只要没有全部或单独禁用,那就会生效。

b. 想要开发的自定义Filter能生效,不并一定要在<dubbo:provider filter="xxxFitler" >中体现;如果我们没有在Dubbo相关的配置文件中去配置Filter相关信息,只要写好自定义filter代码,并在资源文件/META-INF/dubbo/com.alibaba.dubbo.rpc.Filter中按照spi规范定义好即可,这样所有被加载的Filter都会生效。

c. 如果在Dubbo配置文件中配置了Filter信息,那自定义Filter只有显式配置才会生效。

d. Filter配置也可以加在dubbo service配置中(<dubbo:service interface="..." ref="..." validation="true" filter="xFilter,yFilter"/>)。

当dubbo配置文件中provider 和service部分都配置了Filter信息,针对service具体生效的Filter取两者配置的并集。

因此想要自定义的校验Filter在所有服务中都生效,需要作如下配置:

<dubbo:provider filter="-validation, customValidationFilter"/>

四、如何扩展校验注解

前面示例中都是利用参数校验的内置注解去完成,在实际开发中有时候会遇到默认内置的注解无法满足校验需求,这时就需要自定义一些校验注解去满足需求,方便开发。

假设有这样一个场景,某参数值需要校验只能在指定的几个数值范围内,类似于白名单一样,下面就以这个场景来演示下如何扩展校验注解。

4.1 定义校验注解

@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER })
@Retention(RUNTIME)
@Documented
@Constraint(validatedBy = { })// 注1
// @Constraint(validatedBy = {AllowedValueValidator.class}) 注2
public @interface AllowedValue {
 
    String message() default "参数值不在合法范围内";
 
    Class<?>[] groups() default { };
 
    Class<? extends Payload>[] payload() default { };
 
    long[] value() default {};
 
}
public class AllowedValueValidator implements ConstraintValidator<AllowedValue, Long> {
 
    private long[] allowedValues;
    @Override
    public void initialize(AllowedValue constraintAnnotation) {
        this.allowedValues = constraintAnnotation.value();
    }
    public boolean isValid(Long value, ConstraintValidatorContext context) {
        if (allowedValues.length == 0) {
            return true;
        }
        return Arrays.stream(allowedValues).anyMatch(o -> Objects.equals(o, value));
}

「注1」中的校验器(Validator)并没有指定,当然是可以像「注2」中那样直接指定校验器,但考虑到自定义注解有可能是直接暴露在facade包中,而具体的校验器的实现有时候会包含一些业务依赖,所以不建议直接在此处指定,而是通过Hibernate Validator提供的Validator发现机制去完成关联。

4.2 配置定制Validator发现

a. 在resources目录下新建META-INF/services/javax.validation.ConstraintValidator文件。

b. 文件中只需填入相应Validator的全路径:com.xxx.demo.validator.AllowedValueValidator,如果有多个的话,每行一个。

五、总结

本文主要介绍了使用Dubbo框架时如何使用优雅点方式完成参数的校验,首先演示了如何利用Dubbo框架默认支持的校验实现,然后接着演示了如何配合实际业务开发返回统一的数据格式,最后介绍了下如何进行自定义校验注解的实现,方便进行后续自行扩展实现,希望能在实际工作中有一定的帮助。

--结束END--

本文标题: Dubbo服务校验参数的解决方案

本文链接: https://www.lsjlt.com/news/141703.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Dubbo服务校验参数的解决方案
    目录一、背景二、解决方案2.1maven依赖2.2接口定义2.3Dubbo服务提供者端配置2.4Dubbo服务消费者端配置2.5验证参数校验三、定制Dubbo参数校验异常返回3.1V...
    99+
    2022-11-13
  • SpringMVC @NotNull校验不生效的解决方案
    目录SpringMVC @NotNull校验不生效加了两个依赖问题解决@NotNull注解失效原因之一Lombok判断注解怎么使用,总结下来为SpringMVC @NotNull校验...
    99+
    2022-11-12
  • SpringBoot进行参数校验的方法详解
    目录介绍1.SpringBoot中集成参数校验1.1引入依赖1.2定义参数实体类1.3定义校验类进行测试1.4打开接口文档模拟提交数据2.参数异常加入全局异常处理器3.自定义参数校验...
    99+
    2022-11-13
  • 如何使用Bean Validation 解决业务中参数校验
    前言 在开发中经常需要写一些字段校验的代码,比如字段非空,字段长度限制,邮箱格式验证等等,写这些与业务逻辑关系不大的代码个人感觉有点麻烦: 验证代码繁琐,重复劳动 方法内代码显得冗长...
    99+
    2022-11-12
  • 怎么使用Bean Validation解决业务中参数校验
    这篇文章将为大家详细讲解有关怎么使用Bean Validation解决业务中参数校验,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。叙述Bean Validation是一个通过配置注解来验证参数的框架,它包...
    99+
    2023-06-20
  • Java实现优雅的参数校验方法详解
    目录一、引子二、如何优雅地校验参数2.1 官方指导意见2.2 注解用法说明一、引子 要对方法的参数进行校验,最简单暴力的写法是这个样子: public static void...
    99+
    2022-11-13
  • SpringBoot 中使用 Validation 校验参数的方法详解
    目录1. Validation 介绍1.1 Validation 注解1.2 @valid 和 @validated的区别2. SpringBoot 中使用 Validator 校验...
    99+
    2022-11-13
  • vue项目中Eslint校验代码报错的解决方案
    目录vue Eslint校验代码报错1.空格缩进,不让使用tab2.未使用的变量报错3.分号和引号问题vue使用Eslint报错解决办法很简单vue Eslint校验代码报错 在使用...
    99+
    2022-11-13
  • 使用Java校验SQL语句的合法性五种解决方案
    方案一:使用JDBC API中提供的Statement接口的execute()方法 要在Java中校验SQL语句的合法性,可以使用JDBC API中提供的Statement接口的ex...
    99+
    2023-05-14
    java校验sql语句 java校验sql java校验
  • 使用自定义注解进行restful请求参数的校验方式
    目录自定义注解进行restful请求参数的校验1、首先我们使用@interface定义一个注解2、实现注解实现类(和@interface定义的注解在同一个包下)3、在需要校验的对象的...
    99+
    2022-11-12
  • springboot参数传中文乱码的解决方案
    目录前言业务部门的实现思路方案一:方案二:编写字符编码过滤器方案三:在application.yml指定编码格式为utf-8方案四:写个StringHttpMessageConver...
    99+
    2022-11-11
  • 如何用Java校验SQL语句的合法性?有这5种解决方案
    方案一:使用JDBC API中提供的Statement接口的execute()方法 要在Java中校验SQL语句的合法性,可以使用JDBC API中提供的Statement接口的execute()方法。这个方法会尝试执行给定的SQL语句,如...
    99+
    2023-10-02
    java sql python
  • 阿里云服务器下单参数错误原因及解决方案
    阿里云服务器是阿里云提供的一种高性能、稳定可靠的云计算服务。然而,不少用户在下单阿里云服务器时,可能会遇到下单参数错误的问题。本文将详细介绍下单参数错误的原因,并提供解决方案。 一、下单参数错误的原因输入参数错误:这是最常见的原因,用户在输...
    99+
    2023-12-09
    阿里 下单 解决方案
  • feign参数过多导致调用失败的解决方案
    目录feign参数过多调用失败错误信息报这个错误的原因是因为给出了两种解决办法feign多参数传递踩坑记录场景现在的问题是解决方案feign参数过多调用失败 错误信息 JSON pa...
    99+
    2022-11-13
  • Springcloud feign传日期类型参数报错的解决方案
    目录feign传日期类型参数报错Date类型参数报错LocalDate类型报错feign传参问题及传输Date类型参数时差的坑下面说说两种解决方案feign传参时候使用@DateTi...
    99+
    2022-11-13
  • SpringBoot2之PUT请求接收不了参数的解决方案
    目录HiddenHttpMethodFilterHttpPutFormContentFilterSpringBoot2之PUT请求接收不了参数的解决办法,这个问题,关乎两个Filte...
    99+
    2022-11-13
  • 云服务器数据迁移解决方案
    云服务器数据迁移解决方案通常需要包括以下步骤: 数据导入:首先需要在云服务器上进行数据导入工作,可以使用数据迁移工具将服务器端的文件或数据文件导入到云服务器的数据中心,也可以从云服务器的数据中心导入数据。导入过程需要注意数据导入的完整性...
    99+
    2023-10-27
    解决方案 服务器 数据
  • Base64:含中文参数转码,对方接受参数解码后,中文信息乱码的解决方案
    Base64:含中文参数转码,对方接受参数解码后,中文信息乱码的解决方案 前言一、Base64是什么?二、问题解决总结 前言 在用Postman调接口给对方发参数的时候,对方反应含中文参数的字段信息部分乱码(即中文乱码,数字等...
    99+
    2023-08-17
    java spring boot
  • 轻量应用服务器ip搭建方案设置参数错误怎么办解决
    检查应用服务器是否设置了错误的IP地址,如果是,请重新设置。 确认在配置应用服务器的IP地址时设置正确,如果出现错误,请查阅相关文件,以获得更多信息。 如果是因应用服务器配置错误而导致的错误,请检查应用服务器的设置,确保设置正确。 检查应...
    99+
    2023-10-26
    错误 参数 服务器
  • Feign远程调用参数里面内容丢失的解决方案
    目录Feign远程调用参数里面内容丢失举个例子解决方法Feign远程调用细节--丢失数据同步调用异步调用Feign远程调用参数里面内容丢失 举个例子 服务A提供了如下接口(注意这里的...
    99+
    2022-11-13
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作