??xml version="1.0" encoding="utf-8" standalone="yes"?>日韩欧美一区二区三区久久婷婷 ,校园春色亚洲色图,青春草免费在线视频http://www.aygfsteel.com/paulwong/category/55116.htmlzh-cnWed, 01 Dec 2021 16:36:18 GMTWed, 01 Dec 2021 16:36:18 GMT60SPRING CLOUD - REACTIVE FEIGNhttp://www.aygfsteel.com/paulwong/archive/2021/12/01/436078.htmlpaulwongpaulwongWed, 01 Dec 2021 08:45:00 GMThttp://www.aygfsteel.com/paulwong/archive/2021/12/01/436078.htmlhttp://www.aygfsteel.com/paulwong/comments/436078.htmlhttp://www.aygfsteel.com/paulwong/archive/2021/12/01/436078.html#Feedback0http://www.aygfsteel.com/paulwong/comments/commentRss/436078.htmlhttp://www.aygfsteel.com/paulwong/services/trackbacks/436078.html
pom.xml
<dependency>
    <groupId>com.playtika.reactivefeign</groupId>
    <artifactId>feign-reactor-spring-cloud-starter</artifactId>
    <version>3.1.2</version>
    <type>pom</type>
</dependency>


LoanDecisionClientReactive.java
package com.paul.testspringcloudstream.loancheck.service;

import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;

import com.paul.testspringcloudstream.common.model.Loan;

import reactivefeign.spring.config.ReactiveFeignClient;
import reactor.core.publisher.Mono;

@ReactiveFeignClient(name = "loan-decision")
public interface LoanDecisionClientReactive {
    
    @PostMapping("/loan-decision")
    public Mono<Loan> getDecision(@RequestBody Loan loan);

}

LoanCheckConfiguration.java
@Configuration
@Import({
    MongoDbConsumerConfiguration.class,
})
@EnableDiscoveryClient
@EnableReactiveFeignClients("com.paul.testspringcloudstream.loancheck.service")
public class LoanCheckConfiguration {
}


使用同feign
@Autowired
private LoanDecisionClientReactive loanDecisionClientReactive;

Reference
https://blog.csdn.net/LCBUSHIHAHA/article/details/113817966

官方SAMPLE
https://github.com/kptfh/feign-reactive-sample

paulwong 2021-12-01 16:45 发表评论
]]>
Spring bootstrap.yml 不管用,失效解决ҎQspring cloud 2020.x.xQ?/title><link>http://www.aygfsteel.com/paulwong/archive/2021/12/01/436076.html</link><dc:creator>paulwong</dc:creator><author>paulwong</author><pubDate>Wed, 01 Dec 2021 02:29:00 GMT</pubDate><guid>http://www.aygfsteel.com/paulwong/archive/2021/12/01/436076.html</guid><wfw:comment>http://www.aygfsteel.com/paulwong/comments/436076.html</wfw:comment><comments>http://www.aygfsteel.com/paulwong/archive/2021/12/01/436076.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/paulwong/comments/commentRss/436076.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/paulwong/services/trackbacks/436076.html</trackback:ping><description><![CDATA[<div>升spring cloud版本之后发现bootstrap.yml 失效了,阅读官方文档得知Q需要新增一个引用来开启bootstrap.xml文g的读取,新版spring cloud默认是关闭读取了?/div><div></div><div>增加依赖如下卛_Q?/div><div><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000FF; "><</span><span style="color: #800000; ">dependency</span><span style="color: #0000FF; ">></span><br />    <span style="color: #0000FF; "><</span><span style="color: #800000; ">groupId</span><span style="color: #0000FF; ">></span>org.springframework.cloud<span style="color: #0000FF; "></</span><span style="color: #800000; ">groupId</span><span style="color: #0000FF; ">></span><br />    <span style="color: #0000FF; "><</span><span style="color: #800000; ">artifactId</span><span style="color: #0000FF; ">></span>spring-cloud-starter-bootstrap<span style="color: #0000FF; "></</span><span style="color: #800000; ">artifactId</span><span style="color: #0000FF; ">></span><br /><span style="color: #0000FF; "></</span><span style="color: #800000; ">dependency</span><span style="color: #0000FF; ">></span></div></div><div></div><div></div><div>官方文档Q?/div><div>https://docs.spring.io/spring-cloud-config/docs/current/reference/html/#config-first-bootstrap</div><div><img src="https://img-blog.csdnimg.cn/20210306153131455.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3hxOTI5NjA5OTY4,size_16,color_FFFFFF,t_70" width="985" height="278" alt="" /></div><div><br /></div><img src ="http://www.aygfsteel.com/paulwong/aggbug/436076.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/paulwong/" target="_blank">paulwong</a> 2021-12-01 10:29 <a href="http://www.aygfsteel.com/paulwong/archive/2021/12/01/436076.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>EVEN DRIVEN - SPRING CLOUD STREAM - @PollableBean for Reactive Suppliershttp://www.aygfsteel.com/paulwong/archive/2021/11/23/436060.htmlpaulwongpaulwongTue, 23 Nov 2021 02:03:00 GMThttp://www.aygfsteel.com/paulwong/archive/2021/11/23/436060.htmlhttp://www.aygfsteel.com/paulwong/comments/436060.htmlhttp://www.aygfsteel.com/paulwong/archive/2021/11/23/436060.html#Feedback0http://www.aygfsteel.com/paulwong/comments/commentRss/436060.htmlhttp://www.aygfsteel.com/paulwong/services/trackbacks/436060.htmlSupplier beans, or functions that only publish messages in Spring Cloud Stream, are a bit special in that they aren't triggered by the receiving of events like Function or Consumer beans. This means that you often need a way to trigger them to be executed periodically.

For imperative functions the framework by default "polls" a Supplier function every 1 second, but that duration is configurable using the spring.cloud.stream.poller.fixed-delay property.

However, for reactive functions supplying a Flux it is only triggered once by default. This is because a Flux itself is potentially an infinite stream of events so in many cases it will only need to be triggered once. But don't worry, if you want to periodically trigger a reactive Supplier because you are producing a finite stream of events you can still do so using @PollableBean. This annotation then allows you to configure how often the function is triggered using the same spring.cloud.stream.poller.fixed-delay property!

One example use case here could be periodically querying a data store and publishing each entry/row as an event. The number of rows in your data store is a finite number at any given time.

Example code:

@PollableBean 
public Supplier<Flux<String>> stringSupplier() { return () -> Flux.just("foo","bar","baz"); }


Reference:
https://solace.community/discussion/360/pollablebean-for-reactive-suppliers-in-spring-cloud-stream

paulwong 2021-11-23 10:03 发表评论
]]>
EVEN DRIVEN - SPRING CLOUD STREAM - 从非SCSlg发送消息到SCSlghttp://www.aygfsteel.com/paulwong/archive/2021/11/19/436054.htmlpaulwongpaulwongFri, 19 Nov 2021 03:47:00 GMThttp://www.aygfsteel.com/paulwong/archive/2021/11/19/436054.htmlhttp://www.aygfsteel.com/paulwong/comments/436054.htmlhttp://www.aygfsteel.com/paulwong/archive/2021/11/19/436054.html#Feedback0http://www.aygfsteel.com/paulwong/comments/commentRss/436054.htmlhttp://www.aygfsteel.com/paulwong/services/trackbacks/436054.html
那么在SPRING CLOUD STREAM中,如果要从非SPRING CLOUD STREAM代码发送MESSAGE到SPRING CLOUD STREAME序Q通常p先通知框架自动生成一个SOURCE?br />
application.property
spring.cloud.stream.source=supplier
spring.cloud.stream.bindings.supplier-out-0.destination=notification-events

java
streamBridge.send("supplier-out-0", userDto);

Reference:
https://blog.devgenius.io/event-driven-microservices-with-spring-cloud-stream-e034eee3f394


paulwong 2021-11-19 11:47 发表评论
]]>
EVEN DRIVEN - SPRING CLOUD STREAM - Error Handlinghttp://www.aygfsteel.com/paulwong/archive/2021/11/17/436052.htmlpaulwongpaulwongWed, 17 Nov 2021 02:50:00 GMThttp://www.aygfsteel.com/paulwong/archive/2021/11/17/436052.htmlhttp://www.aygfsteel.com/paulwong/comments/436052.htmlhttp://www.aygfsteel.com/paulwong/archive/2021/11/17/436052.html#Feedback0http://www.aygfsteel.com/paulwong/comments/commentRss/436052.htmlhttp://www.aygfsteel.com/paulwong/services/trackbacks/436052.html
@ServiceActivator(inputChannel = "my-destination.my-group.errors")
    public void handleError(ErrorMessage message) {
        Throwable throwable = message.getPayload();
        log.error("截获异常", throwable);

        Message<?> originalMessage = message.getOriginalMessage();
        assert originalMessage != null;

        log.info("原始消息?nbsp;= {}", new String((byte[]) originalMessage.getPayload()));
    }

详情参考:
https://www.itmuch.com/spring-cloud/spring-cloud-stream-error-handling/

paulwong 2021-11-17 10:50 发表评论
]]>
EVEN DRIVEN - SPRING CLOUD STREAM - Function Componenthttp://www.aygfsteel.com/paulwong/archive/2021/11/15/436051.htmlpaulwongpaulwongMon, 15 Nov 2021 09:40:00 GMThttp://www.aygfsteel.com/paulwong/archive/2021/11/15/436051.htmlhttp://www.aygfsteel.com/paulwong/comments/436051.htmlhttp://www.aygfsteel.com/paulwong/archive/2021/11/15/436051.html#Feedback0http://www.aygfsteel.com/paulwong/comments/commentRss/436051.htmlhttp://www.aygfsteel.com/paulwong/services/trackbacks/436051.html
lg地址Q?br />https://github.com/spring-cloud/stream-applications/tree/main/functions

ҎlgQ将FUNCTION变成HTTP ENDPOINTSQ?br />https://github.com/spring-cloud/spring-cloud-function/tree/main/spring-cloud-starter-function-web
https://github.com/spring-cloud/spring-cloud-function/tree/main/spring-cloud-starter-function-webflux



paulwong 2021-11-15 17:40 发表评论
]]>
EVEN DRIVEN - SPRING CLOUD STREAM - Routing Functionhttp://www.aygfsteel.com/paulwong/archive/2021/11/15/436050.htmlpaulwongpaulwongMon, 15 Nov 2021 06:46:00 GMThttp://www.aygfsteel.com/paulwong/archive/2021/11/15/436050.htmlhttp://www.aygfsteel.com/paulwong/comments/436050.htmlhttp://www.aygfsteel.com/paulwong/archive/2021/11/15/436050.html#Feedback0http://www.aygfsteel.com/paulwong/comments/commentRss/436050.htmlhttp://www.aygfsteel.com/paulwong/services/trackbacks/436050.htmlҎRoutingFunction可发送消息到其外部DESTINATION中或?#8220;?#8221;q接W连接?br />
application.yaml
# This setting can increase or decrease the rate of message production (1000 = 1s)
#
 spring.cloud.stream.poller.fixed-delay=1000
#
 DefaultPollerProperties

# This setting can control which function method in our code will be triggered if there are multiple
#
 spring.cloud.function.definition=supplyLoan

# Give the autogenerated binding a friendlier name
spring:
   application:
      name: loan-check-rabbit
   banner:
      location: classpath:/banner-rabbit.txt
   cloud:
      #BindingServiceProperties
      stream:
         #StreamFunctionProperties
         function:
            definition: loadCheckerFunction;loanCheckerDecieder;loanCheckerConsumer;\
                        loanDeclinedConsumer;loanApprovedConsumer;loanCheckerProcessor|functionRouter
            routing:
               enabled: true
         #BindingProperties
         bindings:
            loanCheckerProcessor|functionRouter-in-0:
               destination: queue.pretty.log.messages
               binder: local_rabbit
               
            loanApprovedConsumer-in-0:
               destination: load.approved
               binder: local_rabbit
            loanDeclinedConsumer-in-0:
               destination: load.declined
               binder: local_rabbit
               
            loanCheckerDecieder-in-0:
               destination: queue.pretty.log.messages.222
               binder: local_rabbit
            loanCheckerDecieder-out-0:
               destination: queue.pretty.approved.messages
               binder: local_rabbit
            loanCheckerConsumer-in-0:
               destination: queue.pretty.approved.messages
               binder: local_rabbit
         #BinderProperties
         binders:
            local_rabbit:
               type: rabbit
               environment:
                  spring:
                     rabbitmq:
                        host: 10.80.27.69
                        port: 5672
                        username: guest
                        password: guest
                        virtual-host: my-virtual-host
                        
                        
logging:
   level:
      root: info
      org.springframework:
         cloud.function: debug
         #retry: debug


LoanCheckConfiguration.java
package com.paul.testspringcloudstream.loancheck.config;

import java.util.function.Consumer;
import java.util.function.Function;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.function.context.MessageRoutingCallback;
import org.springframework.cloud.stream.function.StreamBridge;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.integration.support.MessageBuilder;
import org.springframework.messaging.Message;

import com.paul.testspringcloudstream.common.model.Loan;
import com.paul.testspringcloudstream.common.model.Status;
import com.paul.testspringcloudstream.loancheck.router.LoanCheckerRouter;
import com.paul.testspringcloudstream.loancheck.service.LoanProcessor;
import com.paul.testspringcloudstream.loancheck.service.LoanService;

@Configuration
public class LoanCheckConfiguration {
    
    private static final Logger log = LoggerFactory.getLogger(LoanCheckConfiguration.class);
    private static final Long MAX_AMOUNT = 10000L;
    private static final String LOG_PATTERN = "{} - {} {} for ${} for {}";
    
    @Autowired
    public void test(Consumer<Loan> loanCheckerConsumer) {
        log.info("{}", loanCheckerConsumer.getClass());
    }
    
    
    @Bean
    public Consumer<Loan> loanCheckerConsumer(){
        return loan -> 
            log.info(LOG_PATTERN, "loanCheckerConsumer", loan.getStatus(), loan.getUuid(), loan.getAmount(), loan.getName());
    }
    
    @Bean
    public Consumer<Loan> loanDeclinedConsumer(){
        return loan -> 
            log.info(LOG_PATTERN, "loanDeclinedConsumer", loan.getStatus(), loan.getUuid(), loan.getAmount(), loan.getName());
    }
    
    @Bean
    public Consumer<Loan> loanApprovedConsumer(){
        return loan -> 
            log.info(LOG_PATTERN, "loanApprovedConsumer", loan.getStatus(), loan.getUuid(), loan.getAmount(), loan.getName());
    }
    
    @Bean
    public MessageRoutingCallback loanCheckerRouter() {
        return new LoanCheckerRouter();
    }
    
    @Bean
    public Function<Loan, Loan> loanCheckerProcessor(
        LoanService loanService
    ){
        return loan -> loanService.check(loan);
    }
    
    @Bean
    public Function<Loan, Message<Loan>> loanCheckerProcessorBak(
        LoanService loanService
    ){
        return loan -> {
            Loan result = loanService.check(loan);
            String sendTo = Status.DECLINED.name().equals(result.getStatus()) ? 
                        LoanProcessor.DECLINED_OUT : LoanProcessor.APPROVED_OUT;
            
            return MessageBuilder.withPayload(result)
                        .setHeader("spring.cloud.stream.sendto.destination", sendTo)
                        .build();
        };
    }
    
    @Bean
    public Consumer<Loan> loanCheckerDecieder(StreamBridge streamBridge){
        return loan -> {
            log.info(LOG_PATTERN, "loanCheckerDecieder", loan.getStatus(), loan.getUuid(), loan.getAmount(), loan.getName());

            if (loan.getAmount() > MAX_AMOUNT) {
                loan.setStatus(Status.DECLINED.name());
                streamBridge.send(LoanProcessor.DECLINED_OUT, "local_rabbit", loan);
            } else {
                loan.setStatus(Status.APPROVED.name());
                streamBridge.send(LoanProcessor.APPROVED_OUT, "local_rabbit", loan);
            }

            log.info(LOG_PATTERN, "loanCheckerDecieder", loan.getStatus(), loan.getUuid(), loan.getAmount(), loan.getName());
        };
    }

}


LoanCheckerRouter.javaQ将路由条gl一在此?br />
package com.paul.testspringcloudstream.loancheck.router;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.function.context.MessageRoutingCallback;
import org.springframework.messaging.Message;

import com.paul.testspringcloudstream.common.model.Loan;
import com.paul.testspringcloudstream.common.model.Status;

public class LoanCheckerRouter implements MessageRoutingCallback{
    
    private static final Logger log = LoggerFactory.getLogger(LoanCheckerRouter.class);

    @Override
    public String functionDefinition(Message<?> message) {
        
//        byte[] resultByte = (byte[])message.getPayload();
//        String resultString = new String(resultByte);
//        
//        return "loanDeclinedConsumer";
        
        Loan result = (Loan)message.getPayload();
        
        log.info("Loan status: {}", result.getStatus());
        
        return Status.DECLINED.name().equals(result.getStatus()) ? 
                    "loanDeclinedConsumer" : "loanApprovedConsumer";
    }

}


paulwong 2021-11-15 14:46 发表评论
]]>
EVEN DRIVEN - SPRING CLOUD STREAM 3.x - Functional Programming Modelhttp://www.aygfsteel.com/paulwong/archive/2021/11/10/436035.htmlpaulwongpaulwongWed, 10 Nov 2021 07:10:00 GMThttp://www.aygfsteel.com/paulwong/archive/2021/11/10/436035.htmlhttp://www.aygfsteel.com/paulwong/comments/436035.htmlhttp://www.aygfsteel.com/paulwong/archive/2021/11/10/436035.html#Feedback0http://www.aygfsteel.com/paulwong/comments/commentRss/436035.htmlhttp://www.aygfsteel.com/paulwong/services/trackbacks/436035.htmlSPRING CLOUD STREAM 3.x 版本Ӟ之前的一些编E模式,如@EnablebinddingQ@StreamListenner{注释被废弃了,q是׃一些框架的代码必需qL写,如配|框架用的Input MessageChannelQOutput  MessageChannelQ连接MessageHandler与MessageChannel{,被视Z必要的动作。ؓ了简化用户代码,于是推出Functional Programming Model?br />
引入了新名词QSupplier、Function与Consumer。实际上q几个类可视为AdapterQ如果之前已l有存在的Servicec,且方法名为各U各P可以重新包装成Supplier、Function与ConsumerQƈ在固定的Ҏ名:apply/get/accept中调用Service的方法?br />

Supplier

当在配置文g中注入此cd的BeanQƈ在spring.cloud.stream.function.definition加入此Bean的名UͼSPRING CLOUD STREAM׃帮你生成一个Output  MessageChannelQƈq接上此BeanQ后l只需要在BINDDING中加入对应的Destination NameQ即可向BROKER发消息了?br />

Consumer

当在配置文g中注入此cd的BeanQƈ在spring.cloud.stream.function.definition加入此Bean的名UͼSPRING CLOUD STREAM׃帮你生成一个Input  MessageChannelQƈq接上此BeanQ后l只需要在BINDDING中加入对应的Destination NameQ即可收到BROKER推送关于此Destination的消息了?br />

Function

当在配置文g中注入此cd的BeanQƈ在spring.cloud.stream.function.definition加入此Bean的名UͼSPRING CLOUD STREAM׃帮你生成一个Input和Output  MessageChannelQƈq接上此BeanQ后l只需要在BINDDING中分别对Input和Output MessageChannel加入对应的Destination Name1/Name2Q即可收到BROKER推送关于此Destination的消息,也可以向BROKER发消息了?br />

与SPRING INTEGRATION的整?/h2>如果要对消息q行复杂处理Q如拆分消息、聚合消息、IF ELSE消息{,p借助SPRING INTEGRATION了?br />
@Bean
    public IntegrationFlow upperCaseFlow(LoanService loanService) {
        return IntegrationFlows
                    //turn this IntegrationFlow as a gateway, here is a Function interface 
                    
//with loadCheckerFunction as bean name
                    .from(LoadCheckerFunction.class, gateway -> gateway.beanName("loadCheckerFunction"))
                    .handle(loanService, "check")
                    .logAndReply(LoggingHandler.Level.WARN);
    }

    public interface LoadCheckerFunction extends Function<Loan, Loan>{

    }

IntegrationFlows.from(Class<?> serviceInterface)是可以将本IntegrationFlow包装成serviceInterface的实现类Q如果调用此接口Q最l会q回IntegrationFlow最后一个步骤的实体Q如果这个serviceInterface是Function的话Q刚好和SPRING CLOUD STREAMҎ上?br />
后箋在spring.cloud.stream.function.definition加入此Bean的名UloadCheckerFunctionQSPRING CLOUD STREAM׃帮你生成一个Input和Output  MessageChannelQƈq接上此BeanQ再在BINDDING中分别对Input和Output MessageChannel加入对应的Destination Name1/Name2Q即可收到BROKER推送关于此Destination的消息,也可以向BROKER发消息?br />
application.yaml
# This setting can increase or decrease the rate of message production (1000 = 1s)
# spring.cloud.stream.poller.fixed-delay=1000

# This setting can control which function method in our code will be triggered if there are multiple
# spring.cloud.function.definition=supplyLoan

# Give the autogenerated binding a friendlier name

spring:
   application:
      name: loan-check-rabbit
   banner:
      location: classpath:/banner-rabbit.txt
   cloud:
      stream:
         function.definition: loadCheckerFunction
         #BindingProperties
         bindings:
            loadCheckerFunction-in-0:
               destination: queue.pretty.log.messages
               binder: local_rabbit
            loadCheckerFunction-out-0:
               destination: queue.pretty.approved.messages
               binder: local_rabbit
         #BinderProperties
         binders:
            local_rabbit:
               type: rabbit
               environment:
                  spring:
                     rabbitmq:
                        host: 10.80.27.69
                        port: 5672
                        username: guest
                        password: guest
                        virtual-host: my-virtual-host

Reference

https://spring.io/blog/2019/10/25/spring-cloud-stream-and-spring-integration

paulwong 2021-11-10 15:10 发表评论
]]>
EVEN DRIVEN - SPRING CLOUD STREAM - SPRING CLOUD微服务的EVEN DRIVEN框架http://www.aygfsteel.com/paulwong/archive/2021/11/05/436031.htmlpaulwongpaulwongFri, 05 Nov 2021 06:58:00 GMThttp://www.aygfsteel.com/paulwong/archive/2021/11/05/436031.htmlhttp://www.aygfsteel.com/paulwong/comments/436031.htmlhttp://www.aygfsteel.com/paulwong/archive/2021/11/05/436031.html#Feedback0http://www.aygfsteel.com/paulwong/comments/commentRss/436031.htmlhttp://www.aygfsteel.com/paulwong/services/trackbacks/436031.html
即A微服务应用将数据发送到MESSAGE BROKER中的某个DESTINATIONQ此DESTINATION是广播型Q非点对点型。B微服务应用订阅此DESTINATIONQ当有新MESSAGE到达此DESTINATIONӞMESSAGE BROKER会将此MESSAGE推送给B应用。所有对此MESSAGE有需要的应用均可订阅Q从而收到此MESSAGE?br />
SPRING CLOUD 中EVENT DRIVEN的框架就是SPRING CLOUD STREAM。其底层是用SPRING INTEGRATION实现?br />
SPRING CLOUD STREAM有以下新名词Q?br />
  • BINDERQ?/li>
是对MESSAGE BROKER操作Ҏ的抽象,卛_用通过此BINDER操作MESSAGE BROKER。目前只实现了RABITMQ和KAFKA?br />
  • CHANNEL
MESSAGE从SPRING CLOUD STREAM传给应用或相反是通过CHANNEL传递的Q这点和SPRING INTEGRATION是一L?br />
  • SOURCE
MESSAGE从应用传lSPRING CLOUD STREAM的CHANNELQ叫@INPUTQ包含这UCHANNEL的接口叫SOURCE?br />
  • SINK
MESSAGE从SPRING CLOUD STREAM传给应用的CHANNELQ叫@OUPUTQ包含这UCHANNEL的接口叫SINK?br />
  • BIDDING
l定哪个@INPUT或哪个@OUPUT与哪个DESTINATION发送或接收关系的MAPPING?br />
  • EnableBinding
应用启动时就会徏立EnableBinding指定的接口中的CHANNEL
  • 消费者群l?/li>
默认下如果同一个应用部|了多个实例Q则每个实例都会收到MESSAGEQ这时如果设|了消费者群l名Uͼ则同一个名UC的多个实例,只有一个能收到MESSAGE?br />
  • PARTITION
如果为MESSAGE指定规则Q如MESSAGE某个字段gA开头ؓ一个规则,以B开头ؓ一个规则,那么以A开头的MESSAGE会放到同一个分Z?br />
q样使用很单了Q只要取得OUTPUT CHANNELQ就可以发送MESSAGEQ将代码兌到INPUT CHANNELQ就能在收到MESSAGEӞ相关代码׃被执行?br />


paulwong 2021-11-05 14:58 发表评论
]]>
SPRING CLOUD ALIBABAhttp://www.aygfsteel.com/paulwong/archive/2021/05/11/435871.htmlpaulwongpaulwongTue, 11 May 2021 06:04:00 GMThttp://www.aygfsteel.com/paulwong/archive/2021/05/11/435871.htmlhttp://www.aygfsteel.com/paulwong/comments/435871.htmlhttp://www.aygfsteel.com/paulwong/archive/2021/05/11/435871.html#Feedback0http://www.aygfsteel.com/paulwong/comments/commentRss/435871.htmlhttp://www.aygfsteel.com/paulwong/services/trackbacks/435871.htmlhttps://mp.weixin.qq.com/mp/appmsgalbum?__biz=MzAwMTk4NjM1MA==&action=getalbum&album_id=1418244755364134912&scene=173&from_msgid=2247484698&from_itemidx=1&count=3&nolastread=1#wechat_redirect

SpringCloud alibaba实战pd文章汇?/span>
https://segmentfault.com/a/1190000023541535?utm_source=sf-similar-article

paulwong 2021-05-11 14:04 发表评论
]]>
SPRING CLOUD JWT资源http://www.aygfsteel.com/paulwong/archive/2017/03/24/432401.htmlpaulwongpaulwongFri, 24 Mar 2017 15:11:00 GMThttp://www.aygfsteel.com/paulwong/archive/2017/03/24/432401.htmlhttp://www.aygfsteel.com/paulwong/comments/432401.htmlhttp://www.aygfsteel.com/paulwong/archive/2017/03/24/432401.html#Feedback0http://www.aygfsteel.com/paulwong/comments/commentRss/432401.htmlhttp://www.aygfsteel.com/paulwong/services/trackbacks/432401.htmlhttps://github.com/thomas-kendall/trivia-microservices


一个Spring BootQ?JWTQAugularJS接口安全验证的简单例?br />http://blog.csdn.net/offbye/article/details/47607711



https://github.com/tuanngda/spring-boot-oauth2-demo


Spring Oauth2 with JWT Sample
http://www.tuicool.com/articles/EjUFZj7


http://stackoverflow.com/questions/38156213/spring-cloud-zuul-jwt-for-value-reference-tokens

paulwong 2017-03-24 23:11 发表评论
]]>
使用Spring Cloud Security OAuth2搭徏授权服务http://www.aygfsteel.com/paulwong/archive/2016/09/16/431797.htmlpaulwongpaulwongFri, 16 Sep 2016 10:22:00 GMThttp://www.aygfsteel.com/paulwong/archive/2016/09/16/431797.htmlhttp://www.aygfsteel.com/paulwong/comments/431797.htmlhttp://www.aygfsteel.com/paulwong/archive/2016/09/16/431797.html#Feedback0http://www.aygfsteel.com/paulwong/comments/commentRss/431797.htmlhttp://www.aygfsteel.com/paulwong/services/trackbacks/431797.htmlSpring Cloud Security OAuth2 ?Spring ?OAuth2 的开源实玎ͼ优点是能与Spring Cloud技术线无缝集成Q如果全部用默认配|,开发者只需要添加注解就能完?OAuth2 授权服务的搭建?/p>

1. d依赖

授权服务是基于Spring Security的,因此需要在目中引入两个依赖:

<dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-security</artifactId>
</dependency>

<dependency>
         <groupId>org.springframework.cloud</groupId>
         <artifactId>spring-cloud-starter-oauth2</artifactId>
 </dependency>


前者ؓ SecurityQ后者ؓSecurity的OAuth2扩展?/p>

2. d注解和配|?/h1>

在启动类中添?code style="box-sizing: border-box; font-family: "Source Code Pro", monospace; font-size: 13.5px; padding: 2px 4px; color: #3f3f3f; white-space: nowrap; border-radius: 0px; margin: 0px; border: 0px; outline: 0px; vertical-align: baseline; word-break: break-word; background: rgba(128, 128, 128, 0.0745098);">@EnableAuthorizationServer注解Q?br />

@SpringBootApplication
@EnableAuthorizationServer
public class AlanOAuthApplication {
    public static void main(String[] args) {
        SpringApplication.run(AlanOAuthApplication.class, args);
    }
}


完成q些我们的授权服务最基本的骨架就已经搭徏完成了。但是要惌通整个流E,我们必须分配 client_idclient_secret才行。Spring Security OAuth2的配|方法是~写@Configurationcȝ?code style="box-sizing: border-box; font-family: "Source Code Pro", monospace; font-size: 13.5px; padding: 2px 4px; color: #3f3f3f; white-space: nowrap; border-radius: 0px; margin: 0px; border: 0px; outline: 0px; vertical-align: baseline; word-break: break-word; background: rgba(128, 128, 128, 0.0745098);">AuthorizationServerConfigurerAdapterQ然后重?code style="box-sizing: border-box; font-family: "Source Code Pro", monospace; font-size: 13.5px; padding: 2px 4px; color: #3f3f3f; white-space: nowrap; border-radius: 0px; margin: 0px; border: 0px; outline: 0px; vertical-align: baseline; word-break: break-word; background: rgba(128, 128, 128, 0.0745098);">void configure(ClientDetailsServiceConfigurer clients)ҎQ如Q?br />

@Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.inMemory() // 使用in-memory存储
                .withClient("client") // client_id
                .secret("secret") // client_secret
                .authorizedGrantTypes("authorization_code") // 该client允许的授权类?/span>
                .scopes("app"); // 允许的授权范?/span>
    }


3. 授权程

讉K授权面Q?br />

localhost:8080/oauth/authorize?client_id=client&response_type=code&redirect_uri=http://www.baidu.com


此时览器会让你输入用户名密码,q是因ؓ Spring Security 在默认情况下会对所有URLdBasic Auth认证。默认的用户名ؓuser, 密码是随机生成的Q在控制台日志中可以看到?/p>

oauth2

画风虽然很简陋,但是基本功能都具备了。点?code style="box-sizing: border-box; font-family: "Source Code Pro", monospace; font-size: 13.5px; padding: 2px 4px; color: #3f3f3f; white-space: nowrap; border-radius: 0px; margin: 0px; border: 0px; outline: 0px; vertical-align: baseline; word-break: break-word; background: rgba(128, 128, 128, 0.0745098);">Authorize后,览器就会重定向到百度,q带?code style="box-sizing: border-box; font-family: "Source Code Pro", monospace; font-size: 13.5px; padding: 2px 4px; color: #3f3f3f; white-space: nowrap; border-radius: 0px; margin: 0px; border: 0px; outline: 0px; vertical-align: baseline; word-break: break-word; background: rgba(128, 128, 128, 0.0745098);">code参数Q?/p>

q里写图片描q? title=

拿到code以后Q就可以调用

POST/GET http://client:secret@localhost:8080/oauth/token
  • 1

来换?code style="box-sizing: border-box; font-family: "Source Code Pro", monospace; font-size: 13.5px; padding: 2px 4px; color: #3f3f3f; white-space: nowrap; border-radius: 0px; margin: 0px; border: 0px; outline: 0px; vertical-align: baseline; word-break: break-word; background: rgba(128, 128, 128, 0.0745098);">access_token了:

curl -X POST -H "Cache-Control: no-cache" -H "Content-Type: application/x-www-form-urlencoded" -d 'grant_type=authorization_code&code=Li4NZo&redirect_uri=http://www.baidu.com' "http://client:secret@localhost:8080/oauth/token"

q回如下Q?br />

{
  "access_token": "32a1ca28-bc7a-4147-88a1-c95abcc30556",
  "token_type": "bearer",
  "expires_in": 2591999,
  "scope": "app"
}

到此我们最最基本的授权服务就搭徏完成了。然而,q仅仅是个demoQ如果要在生产环境中使用Q还需要做更多的工作?/p>

4. 使用MySQL存储access_token和client信息

把授权服务器中的数据存储到数据库中ƈ不难Q因?Spring Cloud Security OAuth 已经为我们设计好了一套Schema和对应的DAO对象。但在用之前,我们需要先对相关的cL一定的了解?/p>

4.1 相关接口

Spring Cloud Security OAuth2通过DefaultTokenServicescL完成token生成、过期等 OAuth2 标准规定的业务逻辑Q?code style="box-sizing: border-box; font-family: "Source Code Pro", monospace; font-size: 13.5px; padding: 2px 4px; color: #3f3f3f; white-space: nowrap; border-radius: 0px; margin: 0px; border: 0px; outline: 0px; vertical-align: baseline; word-break: break-word; background: rgba(128, 128, 128, 0.0745098);">DefaultTokenServices又是通过TokenStore接口完成对生成数据的持久化。在上面的demo中,TokenStore的默认实CؓInMemoryTokenStoreQ即内存存储?对于Client信息Q?code style="box-sizing: border-box; font-family: "Source Code Pro", monospace; font-size: 13.5px; padding: 2px 4px; color: #3f3f3f; white-space: nowrap; border-radius: 0px; margin: 0px; border: 0px; outline: 0px; vertical-align: baseline; word-break: break-word; background: rgba(128, 128, 128, 0.0745098);">ClientDetailsService接口负责从存储仓库中d数据Q在上面的demo中默认用的也是InMemoryClientDetialsService实现cR说到这里就能看出,要想使用数据库存储,只需要提供这些接口的实现cd可。庆q的是,框架已经为我们写好JDBC实现了,?code style="box-sizing: border-box; font-family: "Source Code Pro", monospace; font-size: 13.5px; padding: 2px 4px; color: #3f3f3f; white-space: nowrap; border-radius: 0px; margin: 0px; border: 0px; outline: 0px; vertical-align: baseline; word-break: break-word; background: rgba(128, 128, 128, 0.0745098);">JdbcTokenStore?code style="box-sizing: border-box; font-family: "Source Code Pro", monospace; font-size: 13.5px; padding: 2px 4px; color: #3f3f3f; white-space: nowrap; border-radius: 0px; margin: 0px; border: 0px; outline: 0px; vertical-align: baseline; word-break: break-word; background: rgba(128, 128, 128, 0.0745098);">JdbcClientDetailsService?/p>

4.2

要想使用q些JDBC实现Q首先要。框架ؓ我们提前设计好了schema, 在github上:https://github.com/spring-projects/spring-security-oauth/blob/master/spring-security-oauth2/src/test/resources/schema.sql

在用这套表l构之前要注意的是,对于MySQL来说Q默认徏表语句中主键是varchar(255)cdQ在mysql中执行会报错Q原因是mysql对varchar主键长度有限制。所以这里改?28卛_。其ơ,语句中会有某些字DؓLONGVARBINARYcdQ它对应mysql?code style="box-sizing: border-box; font-family: "Source Code Pro", monospace; font-size: 13.5px; padding: 2px 4px; color: #3f3f3f; white-space: nowrap; border-radius: 0px; margin: 0px; border: 0px; outline: 0px; vertical-align: baseline; word-break: break-word; background: rgba(128, 128, 128, 0.0745098);">blobcdQ也需要修改一下?/p>

4.3 配置

数据库徏好后Q下一步就是配|框架用JDBC实现。方法还是编?code style="box-sizing: border-box; font-family: "Source Code Pro", monospace; font-size: 13.5px; padding: 2px 4px; color: #3f3f3f; white-space: nowrap; border-radius: 0px; margin: 0px; border: 0px; outline: 0px; vertical-align: baseline; word-break: break-word; background: rgba(128, 128, 128, 0.0745098);">@Configurationcȝ?code style="box-sizing: border-box; font-family: "Source Code Pro", monospace; font-size: 13.5px; padding: 2px 4px; color: #3f3f3f; white-space: nowrap; border-radius: 0px; margin: 0px; border: 0px; outline: 0px; vertical-align: baseline; word-break: break-word; background: rgba(128, 128, 128, 0.0745098);">AuthorizationServerConfigurerAdapterQ?br />

@Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    private DataSource dataSource;
    @Bean // 声明TokenStore实现
    public TokenStore tokenStore() {
        return new JdbcTokenStore(dataSource);
    }
    @Bean // 声明 ClientDetails实现
    public ClientDetailsService clientDetails() {
        return new JdbcClientDetailsService(dataSource);
    }
    @Override // 配置框架应用上述实现
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints.authenticationManager(authenticationManager);
        endpoints.tokenStore(tokenStore());

        // 配置TokenServices参数
        DefaultTokenServices tokenServices = new DefaultTokenServices();
        tokenServices.setTokenStore(endpoints.getTokenStore());
        tokenServices.setSupportRefreshToken(false);
        tokenServices.setClientDetailsService(endpoints.getClientDetailsService());
        tokenServices.setTokenEnhancer(endpoints.getTokenEnhancer());
        tokenServices.setAccessTokenValiditySeconds( (int) TimeUnit.DAYS.toSeconds(30)); // 30?/span>
        endpoints.tokenServices(tokenServices);
    }

完成q些后,框架׃中间生的数据写到mysql中了?code style="box-sizing: border-box; font-family: "Source Code Pro", monospace; font-size: 13.5px; padding: 2px 4px; color: #3f3f3f; white-space: nowrap; border-radius: 0px; margin: 0px; border: 0px; outline: 0px; vertical-align: baseline; word-break: break-word; background: rgba(128, 128, 128, 0.0745098);">oauth_client_details是client表,可以直接在该表中d记录来添加client: 
q里写图片描q? title=

4.4 需要注意的地方

q里不得不说 Spring 设计有一个奇葩地的方。注意看oauth_access_token表是存放讉K令牌的,但是q没有直接在字段中存放token。Spring 使用OAuth2AccessToken来抽象与令牌有关的所有属性,在写入到数据库时Q?strong style="box-sizing: border-box; margin: 0px; padding: 0px; border: 0px; outline: 0px; font-size: 16px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;">Spring该对象通过JDK自带的序列化机制序列成字?/strong>直接保存C该表?code style="box-sizing: border-box; font-family: "Source Code Pro", monospace; font-size: 13.5px; padding: 2px 4px; color: #3f3f3f; white-space: nowrap; border-radius: 0px; margin: 0px; border: 0px; outline: 0px; vertical-align: baseline; word-break: break-word; background: rgba(128, 128, 128, 0.0745098);">token字段中。也是_如果只看数据表你是看不出access_token的值是多少Q过期时间等信息的。这q资源服务器的实现带来了麻烦。我们的资源提供方ƈ没有使用Spring SecurityQ也不想引入 Spring Security 的Q何依赖,q时候就只能?nbsp;DefaultOAuth2AccessToken的源码copy到资源提供方的项目中Q然后读?code style="box-sizing: border-box; font-family: "Source Code Pro", monospace; font-size: 13.5px; padding: 2px 4px; color: #3f3f3f; white-space: nowrap; border-radius: 0px; margin: 0px; border: 0px; outline: 0px; vertical-align: baseline; word-break: break-word; background: rgba(128, 128, 128, 0.0745098);">token字段q反序列化还原对象来获取token信息。但是如果这样做q会遇到反序列化兼容性的问题Q具体解x法参考我另一博?http://blog.csdn.net/neosmith/article/details/52539614

5. ȝ

x一个能在生产环境下使用的授权服务就搭徏好了。其实我们在实际使用时应该适当定制JdbcTokenStore?code style="box-sizing: border-box; font-family: "Source Code Pro", monospace; font-size: 13.5px; padding: 2px 4px; color: #3f3f3f; white-space: nowrap; border-radius: 0px; margin: 0px; border: 0px; outline: 0px; vertical-align: baseline; word-break: break-word; background: rgba(128, 128, 128, 0.0745098);">ClientDetailsService来实适应业务需要,甚至可以直接?开始实现接口,完全不用框架提供的实现。另外,Spring 直接?code style="box-sizing: border-box; font-family: "Source Code Pro", monospace; font-size: 13.5px; padding: 2px 4px; color: #3f3f3f; white-space: nowrap; border-radius: 0px; margin: 0px; border: 0px; outline: 0px; vertical-align: baseline; word-break: break-word; background: rgba(128, 128, 128, 0.0745098);">DefaultOAuth2AccessToken序列化成字节保存到数据库中的设计Q我认ؓ是非怸合理的。或许设计者的初衷是保?code style="box-sizing: border-box; font-family: "Source Code Pro", monospace; font-size: 13.5px; padding: 2px 4px; color: #3f3f3f; white-space: nowrap; border-radius: 0px; margin: 0px; border: 0px; outline: 0px; vertical-align: baseline; word-break: break-word; background: rgba(128, 128, 128, 0.0745098);">access_tokenQ但是通过加密的方法也可以实现Q完全不应该直接扔字节。不q通过定制TokenStore接口Q我们可以用自q表结构而不拘惔于默认实现?br />
http://blog.csdn.net/tracker_w/article/category/6360121

http://blog.csdn.net/neosmith/article/details/52539927



paulwong 2016-09-16 18:22 发表评论
]]>
使用Spring Cloud Feign作ؓHTTP客户端调用远EHTTP服务http://www.aygfsteel.com/paulwong/archive/2016/09/16/431796.htmlpaulwongpaulwongFri, 16 Sep 2016 10:13:00 GMThttp://www.aygfsteel.com/paulwong/archive/2016/09/16/431796.htmlhttp://www.aygfsteel.com/paulwong/comments/431796.htmlhttp://www.aygfsteel.com/paulwong/archive/2016/09/16/431796.html#Feedback0http://www.aygfsteel.com/paulwong/comments/commentRss/431796.htmlhttp://www.aygfsteel.com/paulwong/services/trackbacks/431796.html在Spring Cloud Netflix栈中Q各个微服务都是以HTTP接口的Ş式暴露自w服务的Q因此在调用q程服务时就必须使用HTTP客户端。我们可以用JDK原生?code style="box-sizing: border-box; font-family: "Source Code Pro", monospace; font-size: 13.5px; padding: 2px 4px; color: #3f3f3f; white-space: nowrap; border-radius: 0px; margin: 0px; border: 0px; outline: 0px; vertical-align: baseline; word-break: break-word; background: rgba(128, 128, 128, 0.0745098);">URLConnection、Apache?code style="box-sizing: border-box; font-family: "Source Code Pro", monospace; font-size: 13.5px; padding: 2px 4px; color: #3f3f3f; white-space: nowrap; border-radius: 0px; margin: 0px; border: 0px; outline: 0px; vertical-align: baseline; word-break: break-word; background: rgba(128, 128, 128, 0.0745098);">Http Client、Netty的异步HTTP Client, Spring?code style="box-sizing: border-box; font-family: "Source Code Pro", monospace; font-size: 13.5px; padding: 2px 4px; color: #3f3f3f; white-space: nowrap; border-radius: 0px; margin: 0px; border: 0px; outline: 0px; vertical-align: baseline; word-break: break-word; background: rgba(128, 128, 128, 0.0745098);">RestTemplate。但是,用v来最方便、最优雅的还是要属Feign了?/p>

Feign?/h1>

Feign是一U声明式、模板化的HTTP客户端。在Spring Cloud中用Feign, 我们可以做到使用HTTPhq程服务时能与调用本地方法一L~码体验Q开发者完全感知不到这是远E方法,更感知不到这是个HTTPh。比如:

@Autowired
private AdvertGropRemoteService service; // q程服务

public AdvertGroupVO foo(Integer groupId) {
    return service.findByGroupId(groupId); // 通过HTTP调用q程服务
}

开发者通过service.findByGroupId()p完成发送HTTPh和解码HTTPq回l果q封装成对象的过E?/p>

Feign的定?/h1>

Z让Feign知道在调用方法时应该向哪个地址发请求以及请求需要带哪些参数Q我们需要定义一个接口:

@FeignClient(name = "ea")  //  [A]
public interface AdvertGroupRemoteService {

    @RequestMapping(value = "/group/{groupId}", method = RequestMethod.GET) // [B]
    AdvertGroupVO findByGroupId(@PathVariable("groupId") Integer adGroupId) // [C]

    @RequestMapping(value = "/group/{groupId}", method = RequestMethod.PUT)
    void update(@PathVariable("groupId") Integer groupId, @RequestParam("groupName") String groupName)

A: @FeignClient用于通知Feignlg对该接口q行代理(不需要编写接口实?Q用者可直接通过@Autowired注入?/p>

B: @RequestMapping表示在调用该Ҏ旉要向/group/{groupId}发?code style="box-sizing: border-box; font-family: "Source Code Pro", monospace; font-size: 13.5px; padding: 2px 4px; color: #3f3f3f; white-space: nowrap; border-radius: 0px; margin: 0px; border: 0px; outline: 0px; vertical-align: baseline; word-break: break-word; background: rgba(128, 128, 128, 0.0745098);">GETh?/p>

C: @PathVariable?code style="box-sizing: border-box; font-family: "Source Code Pro", monospace; font-size: 13.5px; padding: 2px 4px; color: #3f3f3f; white-space: nowrap; border-radius: 0px; margin: 0px; border: 0px; outline: 0px; vertical-align: baseline; word-break: break-word; background: rgba(128, 128, 128, 0.0745098);">SpringMVC中对应注解含义相同?/p>

Spring Cloud应用在启动时QFeign会扫描标?code style="box-sizing: border-box; font-family: "Source Code Pro", monospace; font-size: 13.5px; padding: 2px 4px; color: #3f3f3f; white-space: nowrap; border-radius: 0px; margin: 0px; border: 0px; outline: 0px; vertical-align: baseline; word-break: break-word; background: rgba(128, 128, 128, 0.0745098);">@FeignClient注解的接口,生成代理Qƈ注册到Spring容器中。生成代理时Feign会ؓ每个接口Ҏ创徏一?code style="box-sizing: border-box; font-family: "Source Code Pro", monospace; font-size: 13.5px; padding: 2px 4px; color: #3f3f3f; white-space: nowrap; border-radius: 0px; margin: 0px; border: 0px; outline: 0px; vertical-align: baseline; word-break: break-word; background: rgba(128, 128, 128, 0.0745098);">RequetTemplate对象Q该对象装了HTTPh需要的全部信息Q请求参数名、请求方法等信息都是在这个过E中定的,Feign的模板化׃现在q里?/p>

在本例中Q我们将Feign与Eureka和Ribbonl合使用Q?code style="box-sizing: border-box; font-family: "Source Code Pro", monospace; font-size: 13.5px; padding: 2px 4px; color: #3f3f3f; white-space: nowrap; border-radius: 0px; margin: 0px; border: 0px; outline: 0px; vertical-align: baseline; word-break: break-word; background: rgba(128, 128, 128, 0.0745098);">@FeignClient(name = "ea")意ؓ通知Feign在调用该接口Ҏ时要向Eureka中查询名?code style="box-sizing: border-box; font-family: "Source Code Pro", monospace; font-size: 13.5px; padding: 2px 4px; color: #3f3f3f; white-space: nowrap; border-radius: 0px; margin: 0px; border: 0px; outline: 0px; vertical-align: baseline; word-break: break-word; background: rgba(128, 128, 128, 0.0745098);">ea的服务,从而得到服务URL?/p>

Feign的Encoder、Decoder和ErrorDecoder

Feign方法签名中Ҏ参数对象序列化ؓh参数攑ֈHTTPh中的q程Q是q码器(Encoder)完成的。同理,HTTP响应数据反序列化为java对象是由解码?Decoder)完成的?/p>

默认情况下,Feign会将标有@RequestParam注解的参数{换成字符串添加到URL中,没有注解的参数通过Jackson转换成json攑ֈh体中。注意,如果?code style="box-sizing: border-box; font-family: "Source Code Pro", monospace; font-size: 13.5px; padding: 2px 4px; color: #3f3f3f; white-space: nowrap; border-radius: 0px; margin: 0px; border: 0px; outline: 0px; vertical-align: baseline; word-break: break-word; background: rgba(128, 128, 128, 0.0745098);">@RequetMapping中的method请求方式指定ؓPOSTQ那么所有未标注解的参数会被忽略,例如Q?br />

@FeignClient(name = "ea")  //  [A]
public interface AdvertGroupRemoteService {

    @RequestMapping(value = "/group/{groupId}", method = RequestMethod.GET) // [B]
    AdvertGroupVO findByGroupId(@PathVariable("groupId") Integer adGroupId) // [C]

    @RequestMapping(value = "/group/{groupId}", method = RequestMethod.PUT)
    void update(@PathVariable("groupId") Integer groupId, @RequestParam("groupName") String groupName)

此时因ؓ声明的是GETh没有h体,所?code style="box-sizing: border-box; font-family: "Source Code Pro", monospace; font-size: 13.5px; padding: 2px 4px; color: #3f3f3f; white-space: nowrap; border-radius: 0px; margin: 0px; border: 0px; outline: 0px; vertical-align: baseline; word-break: break-word; background: rgba(128, 128, 128, 0.0745098);">obj参数׃被忽略?/p>

在Spring Cloud环境下,Feign的Encoder*只会用来~码没有d注解的参?。如果你自定义了Encoder, 那么只有在编?code style="box-sizing: border-box; font-family: "Source Code Pro", monospace; font-size: 13.5px; padding: 2px 4px; color: #3f3f3f; white-space: nowrap; border-radius: 0px; margin: 0px; border: 0px; outline: 0px; vertical-align: baseline; word-break: break-word; background: rgba(128, 128, 128, 0.0745098);">obj参数时才会调用你的Encoder。对于Decoder, 默认会委托给SpringMVC中的MappingJackson2HttpMessageConverterc进行解码。只有当状态码不在200 ~ 300之间时ErrorDecoder才会被调用。ErrorDecoder的作用是可以ҎHTTP响应信息q回一个异常,该异常可以在调用Feign接口的地方被捕获到。我们目前就通过ErrorDecoder来Feign接口抛出业务异常以供调用者处理?/p>

Feign的HTTP Client

Feign在默认情况下使用的是JDK原生?code style="box-sizing: border-box; font-family: "Source Code Pro", monospace; font-size: 13.5px; padding: 2px 4px; color: #3f3f3f; white-space: nowrap; border-radius: 0px; margin: 0px; border: 0px; outline: 0px; vertical-align: baseline; word-break: break-word; background: rgba(128, 128, 128, 0.0745098);">URLConnection发送HTTPhQ没有连接池Q但是对每个地址会保持一个长q接Q即利用HTTP?code style="box-sizing: border-box; font-family: "Source Code Pro", monospace; font-size: 13.5px; padding: 2px 4px; color: #3f3f3f; white-space: nowrap; border-radius: 0px; margin: 0px; border: 0px; outline: 0px; vertical-align: baseline; word-break: break-word; background: rgba(128, 128, 128, 0.0745098);">persistence connection 。我们可以用Apache的HTTP Client替换Feign原始的http client, 从而获取连接池、超时时间等与性能息息相关的控制能力。Spring Cloud?code style="box-sizing: border-box; font-family: "Source Code Pro", monospace; font-size: 13.5px; padding: 2px 4px; color: #3f3f3f; white-space: nowrap; border-radius: 0px; margin: 0px; border: 0px; outline: 0px; vertical-align: baseline; word-break: break-word; background: rgba(128, 128, 128, 0.0745098);">Brixtion.SR5版本开始支持这U替换,首先在项目中声明Apache HTTP Client?code style="box-sizing: border-box; font-family: "Source Code Pro", monospace; font-size: 13.5px; padding: 2px 4px; color: #3f3f3f; white-space: nowrap; border-radius: 0px; margin: 0px; border: 0px; outline: 0px; vertical-align: baseline; word-break: break-word; background: rgba(128, 128, 128, 0.0745098);">feign-httpclient依赖Q?br />

@RequestMapping(value = "/group/{groupId}", method = RequestMethod.GET)
void update(@PathVariable("groupId") Integer groupId, @RequestParam("groupName") String groupName, DataObject obj);

然后?code style="box-sizing: border-box; font-family: "Source Code Pro", monospace; font-size: 13.5px; padding: 2px 4px; color: #3f3f3f; white-space: nowrap; border-radius: 0px; margin: 0px; border: 0px; outline: 0px; vertical-align: baseline; word-break: break-word; background: rgba(128, 128, 128, 0.0745098);">application.properties中添加:

feign.httpclient.enabled=true

ȝ

通过FeignQ?我们能把HTTPq程调用对开发者完全透明Q得C调用本地Ҏ一致的~码体验。这一点与阉KDubbo中暴露远E服务的方式cMQ区别在于Dubbo是基于私有二q制协议Q而Feign本质上还是个HTTP客户端。如果是在用Spring Cloud Netflix搭徏微服务,那么Feign无疑是最佳选择?br />
http://blog.csdn.net/tracker_w/article/category/6360121
http://blog.csdn.net/neosmith/article/details/52449921



paulwong 2016-09-16 18:13 发表评论
]]>
微服务框架Spring Cloudhttp://www.aygfsteel.com/paulwong/archive/2016/09/11/431788.htmlpaulwongpaulwongSun, 11 Sep 2016 12:49:00 GMThttp://www.aygfsteel.com/paulwong/archive/2016/09/11/431788.htmlhttp://www.aygfsteel.com/paulwong/comments/431788.htmlhttp://www.aygfsteel.com/paulwong/archive/2016/09/11/431788.html#Feedback0http://www.aygfsteel.com/paulwong/comments/commentRss/431788.htmlhttp://www.aygfsteel.com/paulwong/services/trackbacks/431788.html2016

paulwong 2016-09-11 20:49 发表评论
]]>
JHipsterhttp://www.aygfsteel.com/paulwong/archive/2016/09/11/431787.htmlpaulwongpaulwongSun, 11 Sep 2016 08:40:00 GMThttp://www.aygfsteel.com/paulwong/archive/2016/09/11/431787.htmlhttp://www.aygfsteel.com/paulwong/comments/431787.htmlhttp://www.aygfsteel.com/paulwong/archive/2016/09/11/431787.html#Feedback0http://www.aygfsteel.com/paulwong/comments/commentRss/431787.htmlhttp://www.aygfsteel.com/paulwong/services/trackbacks/431787.htmlhttp://jhipster.cn/

paulwong 2016-09-11 16:40 发表评论
]]>
spring cloud目d配置理http://www.aygfsteel.com/paulwong/archive/2016/09/11/431785.htmlpaulwongpaulwongSun, 11 Sep 2016 08:26:00 GMThttp://www.aygfsteel.com/paulwong/archive/2016/09/11/431785.htmlhttp://www.aygfsteel.com/paulwong/comments/431785.htmlhttp://www.aygfsteel.com/paulwong/archive/2016/09/11/431785.html#Feedback0http://www.aygfsteel.com/paulwong/comments/commentRss/431785.htmlhttp://www.aygfsteel.com/paulwong/services/trackbacks/431785.htmlspring cloud config server配置好了数据库连接信息,q个目dconfigQ获取连接信息。这里以mybtis作ؓ列子。从服务器读取jdbc信息后,q行mybatisE序?br />
认服务是否成功
http://localhost:8888/demo-config/test
{"name":"demo-config","profiles":["test"],"label":"master","version":"02d28ad4925aa9bd1bf8a48d2edbf04ce61aa45a","propertySources":[{"name":"https://git.oschina.net/penghaozhong/demo.git/demo-config-repo/demo-config-test.properties","source":{"jdbc.url":"jdbc:mysql://localhost:3306/demo?characterEncoding=UTF-8","jdbc.username":"root","jdbc.driver":"com.mysql.jdbc.Driver","jdbc.password":"xxxxxx","jdbc.type":"mysql"}}]}

    2. 配置d配置文g

  



在bootstrap.properties中添加读取配|管理的地址?br />
3. d配置文g属性,q里采用@ConfigurationProperties
/**
 * d数据库配|文?br /> * 
@author penghaozhong
 *
 
*/
@ConfigurationProperties(prefix = DataSourceProperties.PREFIX, ignoreUnknownFields = false)
public  class  DataSourceProperties {
    
        public DataSourceProperties() {
        super();
    }
        //对应配置文g里的配置?/span>
        public final static String PREFIX="jdbc";    
        
        private String type; 
        private String driver; 
        private String url; 
        private String username; 
        private String password;
        
        public String getType() {
            return type;
        }
        public void setType(String type) {
            this.type = type;
        }
        public String getDriver() {
            return driver;
        }
        public void setDriver(String driver) {
            this.driver = driver;
        }
        public String getUrl() {
            return url;
        }
        public void setUrl(String url) {
            this.url = url;
        }
        public String getUsername() {
            return username;
        }
        public void setUsername(String username) {
            this.username = username;
        }
        public String getPassword() {
            return password;
        }
        public void setPassword(String password) {
            this.password = password;
        }

}


4. 配置mybatis
@Configuration
@MapperScan("com.phz.test.spring.cloud.demo")
@EnableConfigurationProperties(DataSourceProperties.class)
@EnableTransactionManagement
public class MybatisDataSource {

    // mybaits mapper xml搜烦路径
    private final static String MAPPERLOCATIONS = "classpath:/mappings/**/*.xml";
    private final static String CONFIGLOCATION = "classpath:/mybatis-config.xml";

    @Autowired
    private  DataSourceProperties dataSourceProperties;
    private DruidDataSource datasource = null;

    @Bean(destroyMethod = "close")
    public  DataSource dataSource(){
        datasource = new DruidDataSource();  
        datasource.setUrl(dataSourceProperties.getUrl());
        datasource.setDbType(dataSourceProperties.getType());
        datasource.setDriverClassName(dataSourceProperties.getDriver());
        datasource.setUsername(dataSourceProperties.getUsername());
        datasource.setPassword(dataSourceProperties.getPassword());
        return datasource;
    }

    @PreDestroy
    public void close() {
        if(datasource != null){
            datasource.close();
        }
    }

    @Bean
    public SqlSessionFactory sqlSessionFactoryBean() throws Exception {
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(dataSource());
        PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        sqlSessionFactoryBean.setMapperLocations(resolver.getResources(MAPPERLOCATIONS));
        sqlSessionFactoryBean.setConfigLocation(resolver.getResource(CONFIGLOCATION));
        sqlSessionFactoryBean.setTypeAliasesPackage("com.phz.test.spring.cloud.demo.entity");
        return sqlSessionFactoryBean.getObject();
    }

    @Bean
    public PlatformTransactionManager transactionManager() {
        return new DataSourceTransactionManager(dataSource());
    }

}













paulwong 2016-09-11 16:26 发表评论
]]>
վ֩ģ壺 Ԫ| ̩| | Ȫ| | | | | | ͼ| | | | º| е| ʯ| | ɽ| ÷| Ȫ| | | ء| IJ| | | | Ͼ| ָ| ϴ| ̨| | α| ڶ| | 㽭ʡ| | ľ| °Ͷ| | |