GithubHelp home page GithubHelp logo

advanced-springcloud / cloud-book Goto Github PK

View Code? Open in Web Editor NEW
167.0 23.0 108.0 248 KB

《Spring Cloud 微服务架构进阶》各章节附录源码

Java 97.99% Kotlin 0.44% Shell 1.57%
spring-cloud spring-boot spring-security microservice middleware

cloud-book's Introduction

Spring Cloud 微服务架构进阶

《Spring Cloud 微服务架构进阶》,重点介绍微服务架构的Spring Cloud框架,在实践的基础上进行用法的拓展与相关组件的源码分析,包括:服务发现、负载均衡、断路、声明式HTTP调用客户端、网关、分布式配置中心、安全权限、消息总线等组件。本书适合Java开发人员,特别适合正在进行微服务化改造的开发人员、架构师,在改造过程中进行参考与进阶应用。

本项目为《Spring Cloud 微服务架构进阶》各章节附录源码。我们为项目中每个章节涉及到的组件(redis、rabbitmq、consul等)提供了docker-compose一键启动,进入项目根目录运行即可。

谢谢支持正版图书,购买链接:https://item.jd.com/12453340.html

如遇刊印和错误,请加入读者群核实和校正,感谢您的支持。

12/11 更新

修复第八章,Hystrix过滤器使用过程产生的com.netflix.hystrix.exception.HystrixRuntimeException: fallbackcmd failed and fallback failed.

增加 - RemoveRequestHeader=Origin过滤器。

加入读者交流群

微信公众号

cloud-book's People

Contributors

keets2012 avatar ztelur avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

cloud-book's Issues

自定义Gatewayfilter获取body第一次请求无法执行

###问题描述
我自定义了一个GatewayFilter用于校验post请求数据的合法性,做了一下操作:

  • 获取头部
  • 获取body
  • 校验头部和body

但是测试的时候发现,获取body的代码,在第一次请求时不执行,之后测试都是可以执行的。

###源码

package com.learn.filter;

import com.google.gson.Gson;
import com.learn.utils.ErrorType;
import com.learn.utils.MD5Util;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.cloud.gateway.filter.factory.rewrite.RewriteFunction;
import org.springframework.cloud.gateway.support.BodyInserterContext;
import org.springframework.cloud.gateway.support.CachedBodyOutputMessage;
import org.springframework.cloud.gateway.support.DefaultServerRequest;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DefaultDataBufferFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.server.reactive.ServerHttpRequestDecorator;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.BodyInserter;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.server.ServerRequest;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;

@Component
public class CtokenGatewayFilter extends AbstractGatewayFilterFactory<CtokenGatewayFilter.Config> {


    public CtokenGatewayFilter() {
        super(Config.class);
    }


    @Override
    public GatewayFilter apply(Config config) {
        return (exchange, chain) -> {

            ServerRequest serverRequest = new DefaultServerRequest(exchange);

            System.out.println("访问路径============" + serverRequest.uri().getPath());
            HttpHeaders headers = exchange.getRequest().getHeaders();

            List<String> errorList = headers.get("bodystr");


            if (null == errorList || errorList.size() == 0) {

                Flux<HashMap> bodyToFlux = serverRequest.bodyToFlux(config.inClass);

                Gson gson = new Gson();

                AtomicReference<String> bodyRef = new AtomicReference<>();
                DefaultDataBufferFactory defaultDataBuffer = new DefaultDataBufferFactory();


                bodyToFlux.map(o -> {
                    System.out.println("class=======" + o.getClass());
                    System.out.println("o 的value=====" + gson.toJson(o));
                    return o;
                }).subscribe();

                String bodyStr = bodyRef.get();
                Message message = checkCtoken(headers, bodyStr);
                System.out.println("请求数据===========" + bodyStr);
                if (null != message) {
                    // 写出校验错误结果
                    return exchange.getResponse().writeWith(messageBufferFlux);
                } else {
                    // 重建请求 防止报错
                    return chain.filter(exchange.mutate().request(decorator).build());
                }

            } else {

                return chain.filter(exchange);
            }
        };
    }

    /**
     * 检查ctoken
     * @param headers 请求头
     * @return 校验结果
     */
    @SuppressWarnings("unchecked")
    private Message checkCtoken(HttpHeaders headers, String httpEntity) {

        Message message;

        List<String> tokenList = headers.get("token");
        List<String> partneridList = headers.get("partnerid");
        List<String> memberidList = headers.get("memberid");
        List<String> timestampList = headers.get("timestamp");
        List<String> ctokenList = headers.get("ctoken");

        message = validParams(tokenList, partneridList, memberidList, ctokenList);
        if (null != message) {
            return message;
        }


        String token = tokenList.get(0);
        String partnerid = partneridList.get(0);
        String memberid = memberidList.get(0);
        String timestamp = timestampList.get(0);
        String ctoken = ctokenList.get(0);

        String validCToken = getCtoken(partnerid, memberid, timestamp, token, httpEntity);
        if (!validCToken.equalsIgnoreCase(ctoken)) {
            message = new Message();
            message.setResult(ErrorType.CH_PAEAM_ERROR);
            message.setMsg("非法的参数");
        }

        return message;
    }




    @Override
    public String name() {
        return "ctoken";
    }

    @Override
    public List<String> shortcutFieldOrder() {
        return Collections.singletonList("ctoken");
    }


    public static class Config {

        private boolean enabled;
        private Class inClass = HashMap.class;
        private Class outClass = HashMap.class;

        private RewriteFunction rewriteFunction = (exchange, bodyMap) -> {


            HashMap<String, Object> valueMap = (HashMap<String, Object>) bodyMap;
            String vin = (String) valueMap.get("vin");       
           
            System.out.println("uname===========" + valueMap.get("uname"));
            valueMap.put("name", "zhangsan");
            valueMap.put("age", 18);

            Map<String, Object> resultMap = new HashMap<>();
            resultMap.put("msg", "校验错误");
            resultMap.put("result", 99);


            return Mono.just(resultMap);
        };

        public RewriteFunction getRewriteFunction() {
            return rewriteFunction;
        }

        public void setRewriteFunction(RewriteFunction rewriteFunction) {
            this.rewriteFunction = rewriteFunction;
        }

        public Class getInClass() {
            return inClass;
        }

        public void setInClass(Class inClass) {
            this.inClass = inClass;
        }

        public Class getOutClass() {
            return outClass;
        }

        public void setOutClass(Class outClass) {
            this.outClass = outClass;
        }

        public boolean isEnabled() {
            return enabled;
        }

        public void setEnabled(boolean enabled) {
            this.enabled = enabled;
        }
    }

}

错误日志

访问路径============/user/getUserById  // 这是第一次请求
请求数据===========null
判断结果{"msg":"非法参数","result":99}

//下面的错误时其它代码导致的
2019-01-10 22:01:42.237  WARN 35400 --- [ctor-http-nio-3] io.netty.util.concurrent.DefaultPromise  : An exception was thrown by reactor.ipc.netty.http.server.HttpServerHandler$TerminateHttpHandler.operationComplete()

reactor.core.Exceptions$ErrorCallbackNotImplemented: org.springframework.core.codec.DecodingException: JSON decoding error: Unexpected end-of-input: was expecting rest of token (internal state: 4); nested exception is com.fasterxml.jackson.core.io.JsonEOFException: Unexpected end-of-input: was expecting rest of token (internal state: 4)
 at [Source: UNKNOWN; line: 28, column: 5]
Caused by: org.springframework.core.codec.DecodingException: JSON decoding error: Unexpected end-of-input: was expecting rest of token (internal state: 4); nested exception is com.fasterxml.jackson.core.io.JsonEOFException: Unexpected end-of-input: was expecting rest of token (internal state: 4)
 at [Source: UNKNOWN; line: 28, column: 5]
	at org.springframework.http.codec.json.Jackson2Tokenizer.endOfInput(Jackson2Tokenizer.java:117) ~[spring-web-5.0.10.RELEASE.jar:5.0.10.RELEASE]
	at reactor.core.publisher.FluxMapSignal$FluxMapSignalSubscriber.onComplete(FluxMapSignal.java:199) ~[reactor-core-3.1.10.RELEASE.jar:3.1.10.RELEASE]
	at reactor.core.publisher.FluxMap$MapSubscriber.onComplete(FluxMap.java:130) ~[reactor-core-3.1.10.RELEASE.jar:3.1.10.RELEASE]
	at reactor.core.publisher.FluxPeek$PeekSubscriber.onComplete(FluxPeek.java:245) ~[reactor-core-3.1.10.RELEASE.jar:3.1.10.RELEASE]
	at reactor.core.publisher.FluxMap$MapSubscriber.onComplete(FluxMap.java:130) ~[reactor-core-3.1.10.RELEASE.jar:3.1.10.RELEASE]
	at reactor.ipc.netty.channel.FluxReceive.terminateReceiver(FluxReceive.java:380) ~[reactor-netty-0.7.10.RELEASE.jar:0.7.10.RELEASE]
	at reactor.ipc.netty.channel.FluxReceive.drainReceiver(FluxReceive.java:204) ~[reactor-netty-0.7.10.RELEASE.jar:0.7.10.RELEASE]
	at reactor.ipc.netty.channel.FluxReceive.onInboundComplete(FluxReceive.java:345) ~[reactor-netty-0.7.10.RELEASE.jar:0.7.10.RELEASE]
	at reactor.ipc.netty.channel.ChannelOperations.onInboundComplete(ChannelOperations.java:338) [reactor-netty-0.7.10.RELEASE.jar:0.7.10.RELEASE]
	at reactor.ipc.netty.channel.ChannelOperations.onHandlerTerminate(ChannelOperations.java:404) [reactor-netty-0.7.10.RELEASE.jar:0.7.10.RELEASE]
	at reactor.ipc.netty.http.server.HttpServerOperations.cleanHandlerTerminate(HttpServerOperations.java:473) [reactor-netty-0.7.10.RELEASE.jar:0.7.10.RELEASE]
	at reactor.ipc.netty.http.server.HttpServerHandler$TerminateHttpHandler.operationComplete(HttpServerHandler.java:330) ~[reactor-netty-0.7.10.RELEASE.jar:0.7.10.RELEASE]
	at reactor.ipc.netty.http.server.HttpServerHandler$TerminateHttpHandler.operationComplete(HttpServerHandler.java:320) ~[reactor-netty-0.7.10.RELEASE.jar:0.7.10.RELEASE]
	at io.netty.util.concurrent.DefaultPromise.notifyListener0(DefaultPromise.java:511) [netty-common-4.1.29.Final.jar:4.1.29.Final]
	at io.netty.util.concurrent.DefaultPromise.notifyListenersNow(DefaultPromise.java:485) [netty-common-4.1.29.Final.jar:4.1.29.Final]
	at io.netty.util.concurrent.DefaultPromise.notifyListeners(DefaultPromise.java:424) [netty-common-4.1.29.Final.jar:4.1.29.Final]
	at io.netty.util.concurrent.DefaultPromise.trySuccess(DefaultPromise.java:103) [netty-common-4.1.29.Final.jar:4.1.29.Final]
	at io.netty.util.internal.PromiseNotificationUtil.trySuccess(PromiseNotificationUtil.java:48) [netty-common-4.1.29.Final.jar:4.1.29.Final]
	at io.netty.channel.ChannelOutboundBuffer.safeSuccess(ChannelOutboundBuffer.java:696) [netty-transport-4.1.29.Final.jar:4.1.29.Final]
	at io.netty.channel.ChannelOutboundBuffer.remove(ChannelOutboundBuffer.java:258) [netty-transport-4.1.29.Final.jar:4.1.29.Final]
	at io.netty.channel.ChannelOutboundBuffer.removeBytes(ChannelOutboundBuffer.java:338) [netty-transport-4.1.29.Final.jar:4.1.29.Final]
	at io.netty.channel.socket.nio.NioSocketChannel.doWrite(NioSocketChannel.java:411) [netty-transport-4.1.29.Final.jar:4.1.29.Final]
	at io.netty.channel.AbstractChannel$AbstractUnsafe.flush0(AbstractChannel.java:934) [netty-transport-4.1.29.Final.jar:4.1.29.Final]
	at io.netty.channel.nio.AbstractNioChannel$AbstractNioUnsafe.flush0(AbstractNioChannel.java:360) [netty-transport-4.1.29.Final.jar:4.1.29.Final]
	at io.netty.channel.AbstractChannel$AbstractUnsafe.flush(AbstractChannel.java:901) [netty-transport-4.1.29.Final.jar:4.1.29.Final]
	at io.netty.channel.DefaultChannelPipeline$HeadContext.flush(DefaultChannelPipeline.java:1396) [netty-transport-4.1.29.Final.jar:4.1.29.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeFlush0(AbstractChannelHandlerContext.java:776) [netty-transport-4.1.29.Final.jar:4.1.29.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeFlush(AbstractChannelHandlerContext.java:768) [netty-transport-4.1.29.Final.jar:4.1.29.Final]
	at io.netty.channel.AbstractChannelHandlerContext.flush(AbstractChannelHandlerContext.java:749) [netty-transport-4.1.29.Final.jar:4.1.29.Final]
	at io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.flush(CombinedChannelDuplexHandler.java:533) [netty-transport-4.1.29.Final.jar:4.1.29.Final]
	at io.netty.channel.ChannelOutboundHandlerAdapter.flush(ChannelOutboundHandlerAdapter.java:115) [netty-transport-4.1.29.Final.jar:4.1.29.Final]
	at io.netty.channel.CombinedChannelDuplexHandler.flush(CombinedChannelDuplexHandler.java:358) [netty-transport-4.1.29.Final.jar:4.1.29.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeFlush0(AbstractChannelHandlerContext.java:776) [netty-transport-4.1.29.Final.jar:4.1.29.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeFlush(AbstractChannelHandlerContext.java:768) [netty-transport-4.1.29.Final.jar:4.1.29.Final]
	at io.netty.channel.AbstractChannelHandlerContext.flush(AbstractChannelHandlerContext.java:749) [netty-transport-4.1.29.Final.jar:4.1.29.Final]
	at io.netty.channel.ChannelDuplexHandler.flush(ChannelDuplexHandler.java:117) [netty-transport-4.1.29.Final.jar:4.1.29.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeFlush0(AbstractChannelHandlerContext.java:776) [netty-transport-4.1.29.Final.jar:4.1.29.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeFlush(AbstractChannelHandlerContext.java:768) [netty-transport-4.1.29.Final.jar:4.1.29.Final]
	at io.netty.channel.AbstractChannelHandlerContext.flush(AbstractChannelHandlerContext.java:749) [netty-transport-4.1.29.Final.jar:4.1.29.Final]
	at reactor.ipc.netty.channel.ChannelOperationsHandler.doWrite(ChannelOperationsHandler.java:300) [reactor-netty-0.7.10.RELEASE.jar:0.7.10.RELEASE]
	at reactor.ipc.netty.channel.ChannelOperationsHandler.drain(ChannelOperationsHandler.java:476) [reactor-netty-0.7.10.RELEASE.jar:0.7.10.RELEASE]
	at reactor.ipc.netty.channel.ChannelOperationsHandler.flush(ChannelOperationsHandler.java:194) [reactor-netty-0.7.10.RELEASE.jar:0.7.10.RELEASE]
	at io.netty.channel.AbstractChannelHandlerContext.invokeFlush0(AbstractChannelHandlerContext.java:776) [netty-transport-4.1.29.Final.jar:4.1.29.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeWriteAndFlush(AbstractChannelHandlerContext.java:802) [netty-transport-4.1.29.Final.jar:4.1.29.Final]
	at io.netty.channel.AbstractChannelHandlerContext.write(AbstractChannelHandlerContext.java:814) [netty-transport-4.1.29.Final.jar:4.1.29.Final]
	at io.netty.channel.AbstractChannelHandlerContext.writeAndFlush(AbstractChannelHandlerContext.java:794) [netty-transport-4.1.29.Final.jar:4.1.29.Final]
	at io.netty.channel.AbstractChannelHandlerContext.writeAndFlush(AbstractChannelHandlerContext.java:831) [netty-transport-4.1.29.Final.jar:4.1.29.Final]
	at io.netty.channel.DefaultChannelPipeline.writeAndFlush(DefaultChannelPipeline.java:1071) [netty-transport-4.1.29.Final.jar:4.1.29.Final]
	at io.netty.channel.AbstractChannel.writeAndFlush(AbstractChannel.java:300) [netty-transport-4.1.29.Final.jar:4.1.29.Final]
	at reactor.ipc.netty.http.server.HttpServerOperations.onOutboundComplete(HttpServerOperations.java:451) [reactor-netty-0.7.10.RELEASE.jar:0.7.10.RELEASE]
	at reactor.ipc.netty.channel.ChannelOperations.onComplete(ChannelOperations.java:221) [reactor-netty-0.7.10.RELEASE.jar:0.7.10.RELEASE]
	at reactor.core.publisher.MonoPeekTerminal$MonoTerminalPeekSubscriber.onComplete(MonoPeekTerminal.java:321) [reactor-core-3.1.10.RELEASE.jar:3.1.10.RELEASE]
	at reactor.core.publisher.FluxPeekFuseable$PeekFuseableConditionalSubscriber.onComplete(FluxPeekFuseable.java:555) [reactor-core-3.1.10.RELEASE.jar:3.1.10.RELEASE]
	at reactor.core.publisher.Operators$MonoSubscriber.onComplete(Operators.java:1121) [reactor-core-3.1.10.RELEASE.jar:3.1.10.RELEASE]
	at reactor.core.publisher.MonoIgnoreThen$ThenAcceptInner.onComplete(MonoIgnoreThen.java:313) [reactor-core-3.1.10.RELEASE.jar:3.1.10.RELEASE]
	at reactor.core.publisher.Operators.complete(Operators.java:128) [reactor-core-3.1.10.RELEASE.jar:3.1.10.RELEASE]
	at reactor.core.publisher.MonoEmpty.subscribe(MonoEmpty.java:45) [reactor-core-3.1.10.RELEASE.jar:3.1.10.RELEASE]
	at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:53) [reactor-core-3.1.10.RELEASE.jar:3.1.10.RELEASE]
	at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.drain(MonoIgnoreThen.java:153) [reactor-core-3.1.10.RELEASE.jar:3.1.10.RELEASE]
	at reactor.core.publisher.MonoIgnoreThen.subscribe(MonoIgnoreThen.java:56) [reactor-core-3.1.10.RELEASE.jar:3.1.10.RELEASE]
	at reactor.core.publisher.MonoPeekFuseable.subscribe(MonoPeekFuseable.java:70) [reactor-core-3.1.10.RELEASE.jar:3.1.10.RELEASE]
	at reactor.core.publisher.MonoPeekTerminal.subscribe(MonoPeekTerminal.java:61) [reactor-core-3.1.10.RELEASE.jar:3.1.10.RELEASE]
	at reactor.ipc.netty.channel.ChannelOperations.applyHandler(ChannelOperations.java:381) [reactor-netty-0.7.10.RELEASE.jar:0.7.10.RELEASE]
	at reactor.ipc.netty.http.server.HttpServerOperations.onHandlerStart(HttpServerOperations.java:399) [reactor-netty-0.7.10.RELEASE.jar:0.7.10.RELEASE]
	at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:163) ~[netty-common-4.1.29.Final.jar:4.1.29.Final]
	at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:404) ~[netty-common-4.1.29.Final.jar:4.1.29.Final]
	at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:446) ~[netty-transport-4.1.29.Final.jar:4.1.29.Final]
	at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:884) ~[netty-common-4.1.29.Final.jar:4.1.29.Final]
	at java.lang.Thread.run(Thread.java:748) ~[na:1.8.0_181]
Caused by: com.fasterxml.jackson.core.io.JsonEOFException: Unexpected end-of-input: was expecting rest of token (internal state: 4)
 at [Source: UNKNOWN; line: 28, column: 5]
	at com.fasterxml.jackson.core.base.ParserMinimalBase._reportInvalidEOF(ParserMinimalBase.java:594) ~[jackson-core-2.9.7.jar:2.9.7]
	at com.fasterxml.jackson.core.json.async.NonBlockingJsonParser._finishTokenWithEOF(NonBlockingJsonParser.java:399) ~[jackson-core-2.9.7.jar:2.9.7]
	at com.fasterxml.jackson.core.json.async.NonBlockingJsonParser.nextToken(NonBlockingJsonParser.java:162) ~[jackson-core-2.9.7.jar:2.9.7]
	at org.springframework.http.codec.json.Jackson2Tokenizer.parseTokenBufferFlux(Jackson2Tokenizer.java:128) ~[spring-web-5.0.10.RELEASE.jar:5.0.10.RELEASE]
	at org.springframework.http.codec.json.Jackson2Tokenizer.endOfInput(Jackson2Tokenizer.java:113) ~[spring-web-5.0.10.RELEASE.jar:5.0.10.RELEASE]
	... 68 common frames omitted

访问路径============/user/getUserById   //这是第二次请求
class=======class java.util.HashMap
o 的value====={"result":0,"msg":"获取订单列表成功","data":{}
请求数据===========null
判断结果{"msg":"非法参数","result":99}

现状

为了校验body和header,所以自定义了一个Filter,但是这个filter存在第一次调用无法获取body的bug,所以只好使用下面的方案。

首先定义一个filter,在这个Filter中获取body,实现方式和官方的ModifyRequestBodyGatewayFilterFactory类几乎一样,在这个实现中,把读取到的body放到header中,如下:

 public GatewayFilter apply(Config config) {
        return (exchange, chain) -> {

            ServerRequest request = new DefaultServerRequest(exchange);


            Class inClass = config.getInClass();

            Gson gson = new Gson();
            AtomicReference<String> bodyStr = new AtomicReference<>();
            Mono<?> modifiedBody = request.bodyToMono(inClass).flatMap(o -> {

                bodyStr.set(gson.toJson(o));
                return config.rewriteFunction.apply(exchange, o);
            });



            BodyInserter bodyInserter = BodyInserters.fromPublisher(modifiedBody, config.outClass);
            CachedBodyOutputMessage outputMessage = new CachedBodyOutputMessage(exchange, exchange.getRequest().getHeaders());



            HttpHeaders headers = new HttpHeaders();
            headers.putAll(exchange.getRequest().getHeaders());
            headers.remove("Content-Length");
            if (config.getContentType() != null) {
                headers.set("Content-Type", config.getContentType());
            }


            return bodyInserter.insert(outputMessage, new BodyInserterContext()).then(Mono.defer(() -> {
                ServerHttpRequestDecorator decorator = new ServerHttpRequestDecorator(exchange.getRequest()) {
                    public HttpHeaders getHeaders() {

                        String str = bodyStr.get();
                        System.out.println("str===========" + str); // 这里

                        long contentLength = headers.getContentLength();
                        HttpHeaders httpHeaders = new HttpHeaders();
                        httpHeaders.putAll(super.getHeaders());
                        httpHeaders.set("bodystr", str); // 这里
                        if (contentLength > 0L) {
                            httpHeaders.setContentLength(contentLength);
                        } else {
                            httpHeaders.set("Transfer-Encoding", "chunked");
                        }

                        return httpHeaders;
                    }

                    public Flux<DataBuffer> getBody() {
                        return outputMessage.getBody();
                    }
                };
                return chain.filter(exchange.mutate().request(decorator).build());
            }));
        };
    }

然后在校验数据的Filter中不再获取body,直接从header中获取,完成校验,这样就基本实现我的需求了。

疑问

  • 为什么第一次请求无法执行
  • 我现在使用的两种方案是不是不合适,有没有其它的实现方案。

linux 文件系统是区分大小写的

[ERROR] The build could not read 1 project -> [Help 1]
[ERROR]
[ERROR] The project com.blueskykong:cloud-book:1.0-SNAPSHOT (/home/wujiatong/gitlab/cloud-book/pom.xml) has 1 error
[ERROR] Child module /home/wujiatong/gitlab/cloud-book/chapter5-openfeign of /home/wujiatong/gitlab/cloud-book/pom.xml does not exist
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]

请将chapter5-openFeign 文件夹名修改成 chapter5-openfeign

关于原书101页中ParseHandlerByName.java的讲解

作者您好!读到此章时发现一些问题,不知是否为个人理解的问题,如有时间,烦请解答一下
问题为:ParseHandlerByName.java源代码中对于contract.parseAndValidatateMetadata(key.type())的函数返回值为List,但后面讲解时SpringMvcContract中此函数的返回值为MethodMetadata,并没有返回值为List的函数,但在BaseContract中有返回值为List的函数,不知此处是否并没有调用SpringMvcContract的函数,而是直接调用的BaseContract中的函数?

Whitelabel Error Page

hello,I down the code, and run the chapter4-eurkea.when i type http://localhost:8765/ask in my browser,i get the error

Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback.

Sun Dec 15 18:58:43 CST 2019
There was an unexpected error (type=Internal Server Error, status=500).
I/O error on GET request for "http://EUREKA-CLIENT-SERVICE/hello/eureka-client": Unexpected end of file from server; nested exception is java.net.SocketException: Unexpected end of file from server

my os is MAC, java version is 1.8. can you tell mw how to solve the error? thank you

关于本书的一点吐槽

作者在本书中跟我们埋了很多坑,根据案例很多情况下运行报错,12章12.1.5访问受限资源
授权码类型请求
书上写的是
http://localhost:8766/oauth/authorize?client_id=client&amp;response_type=code&amp;redirect_uri=http://localhost:8888/login
参数中回调地址写的是http://localhost:8888/login,然后你认证服务器AuthorizationServerConfig中配置的回调地址为 http://localhost:8888/
@OverRide
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory().withClient("client")
.authorizedGrantTypes("authorization_code","password", "refresh_token")
.scopes("all")
.secret("secret")
.redirectUris("http://localhost:8888/")
;
}
请求中带的回调地址和你后台配置的都不一样,怎么可能正常访问到请求授权页面???
应该会报错
error="invalid_grant", error_description="Invalid redirect: http://localhost:8888/login does not match one of the registered values."
这种情况让我困扰了很久!!!!!

12章配置jwt转换器出错

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerEndpointsConfiguration': Invocation of init method failed; nested exception is java.lang.IllegalStateException: Cannot configure enpdoints
at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:139) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:419) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1737) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:576) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:498) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:320) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:846) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:863) ~[spring-context-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:546) ~[spring-context-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:142) ~[spring-boot-2.1.2.RELEASE.jar:2.1.2.RELEASE]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:775) [spring-boot-2.1.2.RELEASE.jar:2.1.2.RELEASE]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397) [spring-boot-2.1.2.RELEASE.jar:2.1.2.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:316) [spring-boot-2.1.2.RELEASE.jar:2.1.2.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1260) [spring-boot-2.1.2.RELEASE.jar:2.1.2.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1248) [spring-boot-2.1.2.RELEASE.jar:2.1.2.RELEASE]
at com.cloud.authorizationserver.AuthorizationServerApplication.main(AuthorizationServerApplication.java:10) [classes/:na]
Caused by: java.lang.IllegalStateException: Cannot configure enpdoints
at org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerEndpointsConfiguration.init(AuthorizationServerEndpointsConfiguration.java:81) ~[spring-security-oauth2-2.3.5.RELEASE.jar:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_101]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_101]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_101]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_101]
at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleElement.invoke(InitDestroyAnnotationBeanPostProcessor.java:363) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleMetadata.invokeInitMethods(InitDestroyAnnotationBeanPostProcessor.java:307) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:136) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
... 18 common frames omitted
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'accessTokenConverter' defined in class path resource [com/cloud/authorizationserver/config/AuthorizationServerConfig.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter]: Factory method 'accessTokenConverter' threw exception; nested exception is java.lang.NoClassDefFoundError: org/springframework/security/jwt/crypto/sign/MacSigner
at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:627) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:456) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1288) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1127) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:538) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:498) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:320) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.resolveBeanReference(ConfigurationClassEnhancer.java:394) ~[spring-context-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:366) ~[spring-context-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at com.cloud.authorizationserver.config.AuthorizationServerConfig$$EnhancerBySpringCGLIB$$ec3a246f.accessTokenConverter() ~[classes/:na]
at com.cloud.authorizationserver.config.AuthorizationServerConfig.configure(AuthorizationServerConfig.java:36) ~[classes/:na]
at org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerEndpointsConfiguration.init(AuthorizationServerEndpointsConfiguration.java:79) ~[spring-security-oauth2-2.3.5.RELEASE.jar:na]
... 25 common frames omitted
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter]: Factory method 'accessTokenConverter' threw exception; nested exception is java.lang.NoClassDefFoundError: org/springframework/security/jwt/crypto/sign/MacSigner
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:185) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:622) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
... 39 common frames omitted
Caused by: java.lang.NoClassDefFoundError: org/springframework/security/jwt/crypto/sign/MacSigner
at org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter.(JwtAccessTokenConverter.java:74) ~[spring-security-oauth2-2.3.5.RELEASE.jar:na]
at com.cloud.authorizationserver.config.AuthorizationServerConfig.accessTokenConverter(AuthorizationServerConfig.java:41) ~[classes/:na]
at com.cloud.authorizationserver.config.AuthorizationServerConfig$$EnhancerBySpringCGLIB$$ec3a246f.CGLIB$accessTokenConverter$3() ~[classes/:na]
at com.cloud.authorizationserver.config.AuthorizationServerConfig$$EnhancerBySpringCGLIB$$ec3a246f$$FastClassBySpringCGLIB$$297b96cd.invoke() ~[classes/:na]
at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:244) ~[spring-core-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:363) ~[spring-context-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at com.cloud.authorizationserver.config.AuthorizationServerConfig$$EnhancerBySpringCGLIB$$ec3a246f.accessTokenConverter() ~[classes/:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_101]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_101]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_101]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_101]
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
... 40 common frames omitted
Caused by: java.lang.ClassNotFoundException: org.springframework.security.jwt.crypto.sign.MacSigner
at java.net.URLClassLoader.findClass(URLClassLoader.java:381) ~[na:1.8.0_101]
at java.lang.ClassLoader.loadClass(ClassLoader.java:424) ~[na:1.8.0_101]
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331) ~[na:1.8.0_101]
at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ~[na:1.8.0_101]
... 52 common frames omitted

第七章代码示例

请问作者:第七章代码示例说明了在没有eureka的使用情况。该如何进行本地测试?以及官网代码直接copy过来如何进行运行?

第四章eureka.instance.hostname配置问题

在书上p42-p43的配置中有eureka.instance.hostname=client的配置
我配了这个之后访问 /say 就会报java.net.UnknownHostException: client 这个错。
但是看到github源码里并没有这个配置。我把这个删了就正常了。这个是什么问题呢?

还有p44 2.服务间调用 那个地方 应该是调用8765这个端口吧 书上写的8762

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.