최신 dubbo 2.6.2 버 전에 서 @ Service 주해 의 parameters 설정 BUG 와 솔 루 션
public interface DemoService {
String sayHello(String name);
String sayHello2(String name);
}
우 리 는 이 두 가지 방법의 시간 초과 시간 을 단독으로 설정 하고 싶 습 니 다. 어떻게 설정 해 야 합 니까?
물론 저 희 는 consumer 에서 @ Reference 주해 의 parameters 주 해 를 통 해 이 루어 질 수 있 습 니 다.(PS: XML 설정 을 기반 으로 MethodConfig 요 소 를 설정 할 수 있 습 니 다. 그러나 주 해 를 기반 으로 한 설정 은 특정한 method 설정 을 따로 설정 하지 않 고 곡선 으로 나 라 를 구 할 수 있 습 니 다. 우 리 는 모든 설정 이 url 매개 변수의 일부분 이 될 수 있다 는 것 을 잘 알 고 있 기 때문에 주 해 를 설정 한 parameters 매개 변 수 를 통 해 url 에 추가 적 인 파 라 메 터 를 추가 하여 같은 목적 을 달성 할 수 있 습 니 다)
@RestController
public class DemoConsumerController {
@Reference(
version = "${demo.service.version}",
application = "${dubbo.application.id}",
registry = "${dubbo.registry.id}",
parameters = {"sayHello.timeout", "3000", "sayHello2.timeout", "5000"}
)
private DemoService demoService;
@RequestMapping("/sayHello")
public String sayHello(@RequestParam String name) throws ExecutionException, InterruptedException {
return demoService.sayHello(name);
}
@RequestMapping("/sayHello2")
public String sayHello2(@RequestParam String name) throws ExecutionException, InterruptedException {
return demoService.sayHello2(name);
}
}
sayHello. timeout 에 3000 밀리초, sayHello 2. timeout 에 5000 밀리초 를 설 치 했 습 니 다. 프로그램 을 실행 하 는 데 아무런 문제 가 없습니다.
그러나 dubbo 공식 추천 방법 은 가능 한 한 provider 측 에서 설정 을 많이 하 는 것 입 니 다. 예 를 들 어 timeout 같은 설정 은 소비자 측 에서 설정 하 는 것 이 아니 라 서비스 제공 자 측 에서 설정 해 야 합 니 다. 공급 자 는 그 가 제공 하 는 방법 이 얼마나 걸 리 는 지 더 잘 알 고 있 기 때 문 입 니 다. (dubbo 의 설정 커버 규칙 에 따라 consumer 측 에서 의 설정 은 provider 측의 설정 을 덮어 씁 니 다)
좋 습 니 다. 그럼 공식 적 인 건의 에 따라 이 설정 을 조정 하고 timeout 을 @ Service 주석 에 설정 합 니 다.
@Service(
version = "${demo.service.version}",
application = "${dubbo.application.id}",
protocol = "${dubbo.protocol.id}",
registry = "${dubbo.registry.id}"
, parameters = {"sayHello.timeout", "3100", "sayHello2.timeout", "5000"}
)
public class DefaultDemoService implements DemoService {
@Override
public String sayHello(String name) {
System.out.println("get request");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "sayHello Hello, " + name + " (from Spring Boot)";
}
@Override
public String sayHello2(String name) {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "sayHello2 Hello, " + name + " (from Spring Boot)";
}
}
프로그램 을 시작 하면 오류 가 발생 했 습 니 다.
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'ServiceBean:defaultDemoService:com.kingnet.blockdata.service.DemoService:${demo.service.version}': Initialization of bean failed; nested exception is org.springframework.beans.ConversionNotSupportedException: Failed to convert property value of type 'java.lang.String[]' to required type 'java.util.Map' for property 'parameters'; nested exception is java.lang.IllegalStateException: Cannot convert value of type 'java.lang.String[]' to required type 'java.util.Map' for property 'parameters': no matching editors or conversion strategy found
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:589) ~[spring-beans-5.0.7.RELEASE.jar:5.0.7.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:503) ~[spring-beans-5.0.7.RELEASE.jar:5.0.7.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:317) ~[spring-beans-5.0.7.RELEASE.jar:5.0.7.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory$$Lambda$97/1279271200.getObject(Unknown Source) ~[na:na]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222) ~[spring-beans-5.0.7.RELEASE.jar:5.0.7.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:315) ~[spring-beans-5.0.7.RELEASE.jar:5.0.7.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199) ~[spring-beans-5.0.7.RELEASE.jar:5.0.7.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:760) ~[spring-beans-5.0.7.RELEASE.jar:5.0.7.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:869) ~[spring-context-5.0.7.RELEASE.jar:5.0.7.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:550) ~[spring-context-5.0.7.RELEASE.jar:5.0.7.RELEASE]
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:140) ~[spring-boot-2.0.3.RELEASE.jar:2.0.3.RELEASE]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:759) ~[spring-boot-2.0.3.RELEASE.jar:2.0.3.RELEASE]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:395) ~[spring-boot-2.0.3.RELEASE.jar:2.0.3.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:327) ~[spring-boot-2.0.3.RELEASE.jar:2.0.3.RELEASE]
at org.springframework.boot.builder.SpringApplicationBuilder.run(SpringApplicationBuilder.java:137) [spring-boot-2.0.3.RELEASE.jar:2.0.3.RELEASE]
at com.kingnet.blockdata.DubboProviderDemo.main(DubboProviderDemo.java:20) [classes/:na]
Caused by: org.springframework.beans.ConversionNotSupportedException: Failed to convert property value of type 'java.lang.String[]' to required type 'java.util.Map' for property 'parameters'; nested exception is java.lang.IllegalStateException: Cannot convert value of type 'java.lang.String[]' to required type 'java.util.Map' for property 'parameters': no matching editors or conversion strategy found
at org.springframework.beans.AbstractNestablePropertyAccessor.convertIfNecessary(AbstractNestablePropertyAccessor.java:590) ~[spring-beans-5.0.7.RELEASE.jar:5.0.7.RELEASE]
at org.springframework.beans.AbstractNestablePropertyAccessor.convertForProperty(AbstractNestablePropertyAccessor.java:604) ~[spring-beans-5.0.7.RELEASE.jar:5.0.7.RELEASE]
at org.springframework.beans.BeanWrapperImpl.convertForProperty(BeanWrapperImpl.java:219) ~[spring-beans-5.0.7.RELEASE.jar:5.0.7.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.convertForProperty(AbstractAutowireCapableBeanFactory.java:1660) ~[spring-beans-5.0.7.RELEASE.jar:5.0.7.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1616) ~[spring-beans-5.0.7.RELEASE.jar:5.0.7.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1363) ~[spring-beans-5.0.7.RELEASE.jar:5.0.7.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:580) ~[spring-beans-5.0.7.RELEASE.jar:5.0.7.RELEASE]
... 15 common frames omitted
Caused by: java.lang.IllegalStateException: Cannot convert value of type 'java.lang.String[]' to required type 'java.util.Map' for property 'parameters': no matching editors or conversion strategy found
at org.springframework.beans.TypeConverterDelegate.convertIfNecessary(TypeConverterDelegate.java:299) ~[spring-beans-5.0.7.RELEASE.jar:5.0.7.RELEASE]
at org.springframework.beans.AbstractNestablePropertyAccessor.convertIfNecessary(AbstractNestablePropertyAccessor.java:585) ~[spring-beans-5.0.7.RELEASE.jar:5.0.7.RELEASE]
... 21 common frames omitted
이 유 는 분명 합 니 다. @ Service 에 있 는 parameters 는 String [] 형식 이지 만 ServiceBean 에 비 치 는 parameters 속성 은 Map 형식 으로 맵 을 자동 으로 변환 할 수 없어 서 이 오 류 를 보 고 했 습 니 다.
그렇다면 이 문 제 를 어떻게 해결 할 것 인가?
우 리 는 소스 코드 를 살 펴 보 니 ServiceBean 이 통과 한 것 을 발견 했다.
com.alibaba.dubbo.config.spring.beans.factory.annotation.ServiceAnnotationBeanPostProcessor#registerServiceBean
이 BeanPostProcessor 가 등 록 했 습 니 다. 이 안 에는 @ Service 를 걸 었 던 모든 종 류 를 스 캔 하여 ServiceBean 으로 등 록 했 습 니 다.
그래서 우 리 는 곡선 으로 나 라 를 구 하 는 방법 이 생 겼 다. 우 리 는 BeanPost Processor 를 정의 하고 ServiceAnnotation BeanPost Processor 이후 에 실행 한 다음 에 ServiceBean 이 진정 으로 예화 되 기 전에 parameters 라 는 매개 변 수 를 Map 으로 바 꾸 면 된다.
import com.alibaba.dubbo.config.spring.ServiceBean;
import com.alibaba.dubbo.config.spring.convert.converter.StringArrayToMapConverter;
import com.alibaba.dubbo.config.spring.convert.converter.StringArrayToStringConverter;
import org.springframework.beans.BeansException;
import org.springframework.beans.PropertyValue;
import org.springframework.beans.PropertyValues;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter;
import org.springframework.core.PriorityOrdered;
import org.springframework.core.convert.ConversionService;
import org.springframework.core.convert.support.DefaultConversionService;
import java.beans.PropertyDescriptor;
import java.util.Map;
/**
* @Service parameters String[] Map bug
*
* @author : xiaojun
* @since 13:16 2018/7/23
*/
public class ServiceParameterBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter implements PriorityOrdered {
@Override
public int getOrder() {
return PriorityOrdered.LOWEST_PRECEDENCE;
}
@Override
public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
// pvs.getPropertyValue("parameter")
if (bean instanceof ServiceBean) {
PropertyValue propertyValue = pvs.getPropertyValue("parameters");
ConversionService conversionService = getConversionService();
if (propertyValue != null && propertyValue.getValue() != null && conversionService.canConvert(propertyValue.getValue().getClass(), Map.class)) {
Map parameters = conversionService.convert(propertyValue.getValue(), Map.class);
propertyValue.setConvertedValue(parameters);
}
}
return pvs;
}
private ConversionService getConversionService() {
DefaultConversionService conversionService = new DefaultConversionService();
conversionService.addConverter(new StringArrayToStringConverter());
conversionService.addConverter(new StringArrayToMapConverter());
return conversionService;
}
}
세심 한 독자 들 이 실 마 리 를 발 견 했 을 수도 있 습 니 다. 모 @ Reference 주석 에 있 는 parameters 는 Reference Bean 의 Map 에 정확하게 반영 할 수 있 습 니 다. parameters 올 라 와...............................................................................
com.alibaba.dubbo.config.spring.convert.converter.StringArrayToMapConverter;
우리 도 이 converter 로 원본 Property Source 의 String [] parameters 를 Map parameters 로 바 꾸 면 됩 니 다.
여기에 Ordered 인 터 페 이 스 를 실현 하여 우리 의 이 BeanPostProcessor 의 우선 순위 가 가장 낮 습 니 다. 이렇게 하면 dubbo 자신의 BeanPostProcessor 이후 에 실 행 될 수 있 고 이 속성 을 순조롭게 전환 할 수 있 습 니 다.
물론, 빈 등록 잊 지 마 세 요.
@Bean
ServiceParameterBeanPostProcessor serviceParameterBeanPostProcessor() {
return new ServiceParameterBeanPostProcessor();
}
시작 프로그램 에서 console 의 url 정 보 를 봅 니 다:
dubbo://192.168.56.1:12345/com.kingnet.blockdata.service.DemoService?anyhost=true&application=dubbo-provider-demo&dubbo=2.6.2&generic=false&interface=com.kingnet.blockdata.service.DemoService&methods=sayHello,sayHello2&pid=9052&revision=1.0.0&sayHello.timeout=3100&sayHello2.timeout=5000&side=provider&status=server×tamp=1532588660430&version=1.0.0
parameters 의 설정 정 보 를 url 의 매개 변수 에 성공 적 으로 추가 한 것 을 발견 하 였 습 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
thymeleaf로 HTML 페이지를 동적으로 만듭니다 (spring + gradle)지난번에는 에서 화면에 HTML을 표시했습니다. 이번에는 화면을 동적으로 움직여보고 싶기 때문에 입력한 문자를 화면에 표시시키고 싶습니다. 초보자의 비망록이므로 이상한 점 등 있으면 지적 받을 수 있으면 기쁩니다! ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.