千家信息网

如何进行Spring MVC框架集成本地HTTP请求和Spring Cloud RPC请求

发表于:2026-11-03 作者:千家信息网编辑
千家信息网最后更新 2026年11月03日,这期内容当中小编将会给大家带来有关如何进行Spring MVC框架集成本地HTTP请求和Spring Cloud RPC请求,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所
千家信息网最后更新 2026年11月03日如何进行Spring MVC框架集成本地HTTP请求和Spring Cloud RPC请求

这期内容当中小编将会给大家带来有关如何进行Spring MVC框架集成本地HTTP请求和Spring Cloud RPC请求,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。

请求区分
  • 请求路径,比如:uri加/rpc前缀用来标识RPC请求

  • 请求头信息,比如:Accept:application/sc-rpc 用来标识RPC请求

输入参数和响应内容

方式一(旧):

对Spring MVC的消息转换进行封装:

  • 输入(@RequestBody): 重写com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter#read方法,对本地请求和RPC请求做兼容。

    @Override    public Object read(Type type, Class contextClass, HttpInputMessage inputMessage) throws IOException {        try {            // transform inputStream to string            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();            IOUtils.copy(inputMessage.getBody(), byteArrayOutputStream);            String str = byteArrayOutputStream.toString(StandardCharsets.UTF_8.name());            // parse json object            JSONObject jsonObject = JSON.parseObject(str, super.getFastJsonConfig().getFeatures());            // if RPC, transform the data format            if (jsonObject.containsKey("data")) {                return JSON.parseObject(jsonObject.getString("data"), type, super.getFastJsonConfig().getFeatures());            }            // otherwise, call super method            return readType(super.getType(type, contextClass), new ByteArrayInputStream(byteArrayOutputStream.toByteArray()));        } catch (JSONException ex) {            throw new HttpMessageNotReadableException("JSON parse error: " + ex.getMessage(), ex);        } catch (IOException ex) {            throw new IOException("I/O error while reading input message", ex);        }    }    private Object readType(Type type, InputStream in) {        try {            return JSON.parseObject(in,                    super.getFastJsonConfig().getCharset(),                    type,                    super.getFastJsonConfig().getParserConfig(),                    super.getFastJsonConfig().getParseProcess(),                    JSON.DEFAULT_PARSER_FEATURE,                    super.getFastJsonConfig().getFeatures());        } catch (JSONException ex) {            throw new HttpMessageNotReadableException("JSON parse error: " + ex.getMessage(), ex);        } catch (IOException ex) {            throw new HttpMessageNotReadableException("I/O error while reading input message", ex);        }    }
  • 输出(@ResponseBody):
    重写com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter#writeInternal方法,本地请求和RPC请求的数据格式保持一致。

package com.caiya.web.base;import com.alibaba.fastjson.JSONPObject;import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;import com.caiya.web.constant.CommonConstant;import com.google.common.base.Joiner;import org.springframework.http.HttpOutputMessage;import org.springframework.http.converter.HttpMessageNotWritableException;import java.io.IOException;/** * fastjson消息转换器. */public class ExtendedFastJsonHttpMessageConverter extends FastJsonHttpMessageConverter {    @Override    protected void writeInternal(Object object, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {        super.writeInternal(wrapResult(object), outputMessage);    }    private Object wrapResult(Object object) {        // 防止json请求重复包装        if (object instanceof ResponseDataWrapper) {            return object;        }        if (object instanceof JSONPObject) {            JSONPObject jsonpObject = (JSONPObject) object;            JSONPObject newJsonpObject = new JSONPObject(jsonpObject.getFunction());            ResponseDataWrapper data;            if (jsonpObject.getParameters().size() == 1) {                // 防止jsonp请求重复包装                if (jsonpObject.getParameters().get(0) instanceof ResponseDataWrapper) {                    return object;                }                data = ResponseDataWrapperBuilder.build(jsonpObject.getParameters().get(0));            } else if (jsonpObject.getParameters().size() > 1) {                data = ResponseDataWrapperBuilder.build(Joiner.on(",").join(jsonpObject.getParameters()));            } else {                data = ResponseDataWrapperBuilder.build(CommonConstant.PLACEHOLDER_OBJECT_EMPTY);            }            newJsonpObject.addParameter(data);            return newJsonpObject;        }        return ResponseDataWrapperBuilder.build(object);    }}

方式二:

  • 输入:
    不需要处理,RPC请求时指定Accept即可:

package com.caiya.test.spring.cloud.configuration;import org.apache.http.HttpHost;import org.apache.http.client.HttpClient;import org.apache.http.client.config.RequestConfig;import org.apache.http.impl.client.DefaultConnectionKeepAliveStrategy;import org.apache.http.impl.client.HttpClientBuilder;import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;import org.apache.http.message.BasicHeader;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import java.util.Collections;import java.util.Timer;import java.util.TimerTask;import java.util.concurrent.TimeUnit;@Configurationpublic class FeignConfig {    @Bean    public HttpClient httpClient() {        System.out.println("init feign httpclient configuration 1111");        // 生成默认请求配置        RequestConfig.Builder requestConfigBuilder = RequestConfig.custom();        // 超时时间        requestConfigBuilder.setSocketTimeout(5 * 1000);        // 连接时间        requestConfigBuilder.setConnectTimeout(5 * 1000);        // 设置代理//        requestConfigBuilder.setProxy(new HttpHost("127.0.0.1", 8880));        RequestConfig defaultRequestConfig = requestConfigBuilder.build();        // 连接池配置        // 长连接保持30秒        final PoolingHttpClientConnectionManager pollingConnectionManager = new PoolingHttpClientConnectionManager(30, TimeUnit.MILLISECONDS);        // 总连接数        pollingConnectionManager.setMaxTotal(5000);        // 同路由的并发数        pollingConnectionManager.setDefaultMaxPerRoute(100);        // httpclient 配置        HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();        // 保持长连接配置,需要在头添加Keep-Alive        httpClientBuilder.setKeepAliveStrategy(new DefaultConnectionKeepAliveStrategy());        httpClientBuilder.setConnectionManager(pollingConnectionManager);        httpClientBuilder.setDefaultRequestConfig(defaultRequestConfig);        httpClientBuilder.setDefaultHeaders(Collections.singleton(new BasicHeader("Accept", "application/sc-rpc")));        HttpClient client = httpClientBuilder.build();        // 启动定时器,定时回收过期的连接        /*Timer timer = new Timer();        timer.schedule(new TimerTask() {            @Override            public void run() {                //        System.out.println("=====closeIdleConnections===");                pollingConnectionManager.closeExpiredConnections();                pollingConnectionManager.closeIdleConnections(5, TimeUnit.SECONDS);            }        }, 10 * 1000, 5 * 1000);*/        System.out.println("===== Apache httpclient 初始化连接池===");        return client;    }}
  • 输出:
    根据mediaType区分消息转换。

package com.caiya.web.configuration;import com.alibaba.fastjson.serializer.SerializerFeature;import com.alibaba.fastjson.support.config.FastJsonConfig;import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;import com.caiya.web.base.ExtendedFastJsonHttpMessageConverter;import org.springframework.boot.autoconfigure.http.HttpMessageConverters;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.http.MediaType;import java.util.Arrays;import java.util.Collections;/** * fastjson消息转换器配置. * * @author caiya * @since 1.0 */@Configurationpublic class FastJsonConfiguration {    @Bean    public HttpMessageConverters extendedFastJsonHttpMessageConverter() {        // for web controller        FastJsonHttpMessageConverter fastJsonHttpMessageConverter = new ExtendedFastJsonHttpMessageConverter();        FastJsonConfig fastJsonConfig = new FastJsonConfig();        fastJsonConfig.setSerializerFeatures(SerializerFeature.DisableCircularReferenceDetect);//      fastJsonConfig.setSerializerFeatures(SerializerFeature.WriteMapNullValue);        fastJsonHttpMessageConverter.setFastJsonConfig(fastJsonConfig);        fastJsonHttpMessageConverter.setSupportedMediaTypes(Arrays.asList(MediaType.APPLICATION_JSON, MediaType.APPLICATION_JSON_UTF8));        // for web resource(Spring Cloud RPC)        FastJsonHttpMessageConverter fastJsonHttpMessageConverterPlain = new FastJsonHttpMessageConverter();        FastJsonConfig fastJsonConfigPlain = new FastJsonConfig();        fastJsonConfigPlain.setSerializerFeatures(SerializerFeature.DisableCircularReferenceDetect);//      fastJsonConfigPlain.setSerializerFeatures(SerializerFeature.WriteMapNullValue);        fastJsonHttpMessageConverterPlain.setFastJsonConfig(fastJsonConfigPlain);        fastJsonHttpMessageConverterPlain.setSupportedMediaTypes(Collections.singletonList(MediaType.valueOf("application/sc-rpc")));        return new HttpMessageConverters(fastJsonHttpMessageConverter, fastJsonHttpMessageConverterPlain);    }}

方式三

在每个controller的method,返回最终响应内容。

方式四

通过aop处理不同的请求(RPC请求不处理即可):

package com.caiya.web.base;import com.alibaba.fastjson.JSONPObject;import com.caiya.web.constant.CommonConstant;import com.google.common.base.Joiner;import org.aspectj.lang.ProceedingJoinPoint;import org.aspectj.lang.annotation.Around;import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.annotation.Pointcut;import org.springframework.stereotype.Component;/** * 对响应内容的包装处理AOP. */@Component@Aspectpublic class ResponseDataWrapperAspect {    @Pointcut("execution(* com.caiya.web.controller.rest..*(..))")    public void aspect() {    }    @Around("aspect()")    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {        Object object = joinPoint.proceed(joinPoint.getArgs());        return wrapResult(object);    }    private Object wrapResult(Object object) {        // 防止json请求重复包装        if (object instanceof ResponseDataWrapper) {            return object;        }        if (object instanceof JSONPObject) {            JSONPObject jsonpObject = (JSONPObject) object;            JSONPObject newJsonpObject = new JSONPObject(jsonpObject.getFunction());            ResponseDataWrapper data;            if (jsonpObject.getParameters().size() == 1) {                // 防止jsonp请求重复包装                if (jsonpObject.getParameters().get(0) instanceof ResponseDataWrapper) {                    return object;                }                data = ResponseDataWrapperBuilder.build(jsonpObject.getParameters().get(0));            } else if (jsonpObject.getParameters().size() > 1) {                data = ResponseDataWrapperBuilder.build(Joiner.on(",").join(jsonpObject.getParameters()));            } else {                data = ResponseDataWrapperBuilder.build(CommonConstant.PLACEHOLDER_OBJECT_EMPTY);            }            newJsonpObject.addParameter(data);            return newJsonpObject;        }        return ResponseDataWrapperBuilder.build(object);    }}
拦截器和过滤器

对RPC请求都不必拦截,放行处理(包括会话拦截器、权限拦截器、XSS过滤器等)

nginx

RPC请求只允许通过Spring Cloud注册中心、网关等调用[schema]://[ip]:[port]/[request_uri] 的形式 ,nginx 需要拦截路径包含 /rpc/ 目录的 RPC 接口调用(彻底隔离只需分离本地请求和RPC请求的应用即可):

    location ~* /rpc/ {            return 403;        }
Spring Cloud 异常处理

服务端异常处理

推荐最外层包裹一层Result对象,表示接口执行结果,包含经过处理的异常信息

客户端异常处理

  • 开启feignclient的hystrix熔断:

feign:  hystrix:    enabled: true
  • 实现接口feign.codec.ErrorDecoder,处理服务端异常:

package com.caiya.web.configuration;import com.alibaba.fastjson.JSON;import com.alibaba.fastjson.JSONObject;import com.netflix.hystrix.exception.HystrixBadRequestException;import feign.Response;import feign.Util;import feign.codec.ErrorDecoder;import org.apache.commons.lang3.StringUtils;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.cloud.openfeign.FeignClientsConfiguration;import org.springframework.context.annotation.Configuration;import java.io.IOException;/** * Spring Cloud(feign with hystrix)自定义异常处理. * * @see FeignClientsConfiguration.HystrixFeignConfiguration#feignHystrixBuilder() 开启hystrix入口 * @see HystrixBadRequestException 此异常类型不会进行熔断操作 * HystrixBadRequestException.message: * {"path":"/rpc/session/user/info","error":"Internal Server Error","message":"Illegal Agument Exception..","timestamp":1540266379459,"status":500} */@Configurationpublic class FeignErrorDecoder implements ErrorDecoder {    private static final Logger logger = LoggerFactory.getLogger(FeignErrorDecoder.class);    @Override    public Exception decode(String methodKey, Response response) {        String message = null;        if (response.status() >= 400 && response.status() <= 500) {            try {                if (response.body() != null) {                    String body = Util.toString(response.body().asReader());                    try {                        JSONObject jsonObject = JSON.parseObject(body);                        if (jsonObject.containsKey("data")) {                            JSONObject content = jsonObject.getJSONObject("data");                            if (StringUtils.isNotBlank(content.getString("message"))) {                                message = content.getString("message");                                if ("connect timed out".equals(message)) {                                    return feign.FeignException.errorStatus(methodKey, response);                                }                            } else {                                message = content.getString("error");                            }                        }                        if (message == null) {                            message = jsonObject.getString("message");                        }                    } catch (Exception e) {                        logger.error(e.getMessage(), e);                        message = body;                    }                }            } catch (IOException e) {                logger.error(e.getMessage(), e);            }            return new HystrixBadRequestException(message);        }        return feign.FeignException.errorStatus(methodKey, response);    }}
  • 处理超时异常,实现@FeignClient注解中的属性fallback或fallbackFactory的相关类,进行熔断处理

其他补充

上述就是小编为大家分享的如何进行Spring MVC框架集成本地HTTP请求和Spring Cloud RPC请求了,如果刚好有类似的疑惑,不妨参照上述分析进行理解。如果想知道更多相关知识,欢迎关注行业资讯频道。

处理 内容 包装 配置 方式 消息 接口 拦截器 输入 框架 信息 方法 时间 标识 路径 转换器 过滤器 分析 服务 输出 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 上海挚品互联网科技有限公司 华服互联网科技怎么样 互联网 科技公司 互联网金融 金融科技 小马过河互联网科技 赫美联合互联网科技 顺玮阁互联网科技 深圳互联网科技怎么样 银川新华互联网科技学校地址 开启互联网科技时代小说 中国的互联网科技企业的崛起 银川新华互联网科技职业技术培训学校图片 新兴科技互联网创新大赛颁奖典礼 燊美集互联网科技有限公司 互联网数据科技专业 上海钢联属于互联网科技股吗 同城互联网络科技 北京天晋互联网科技有限公司 杭州融税互联网科技有限公司 山东亿川互联网科技有限责任公司 广东万易互联网科技有限公司惠州分公司 平安科技 互联网 美国互联网黑科技 多迪互联网科技有限公司 山东吉时兔互联网科技有限公司 欧洲十大科技互联网公司 彤创互联网科技有限公司 企晟互联网信息科技有限公司 云鲸互联网络科技有限公司 互联网科技博主张洲
0