做网站 pc端与手机端兼容,一站式网页设计服务平台,快消品网站建设,pythom+网站开发规范服务提供和消费脑图 服务提供和消费脑图 参见: 服务提供者, 服务消费者, 服务注册中心 服务提供者 1.服务提供者启动#xff0c;解析xml文件中配置的服务#xff0c;这里使用Dom4j解析。 2.将服务的一些相关信息注册到 服务注册中心。 注#xff1a;服务相关信息#xff1a… 服务提供和消费脑图 服务提供和消费脑图 参见: 服务提供者, 服务消费者, 服务注册中心 服务提供者 1.服务提供者启动解析xml文件中配置的服务这里使用Dom4j解析。 2.将服务的一些相关信息注册到 服务注册中心。 注服务相关信息服务中心接口url接口名称方法名称参数信息。 3.提供一个接口服务消费者通过调用这个接口url来调用相应的服务。 参见: 服务提供和消费脑图, 服务注册中心 (1.注册服务), 服务消费者 (3.调用服务) 服务消费者 1.服务消费者启动使用dom4j解析xml获取要消费的服务相关接口。 2.根据接口信息去服务注册中心判断是否有对应的注册信息如果有则通过jdk动态代理生成相应的代理类并注册到spring中代理方法中会根据服务中心返回的信息服务提供者的url去调用服务提供者对应的服务。 参见: 服务提供和消费脑图, 服务注册中心 (2.消费服务), 服务提供者 (3.调用服务) 服务注册中心 1.将来自服务提供者信息存储到redis。 2.将服务信息提供给服务消费者。 参见: 服务提供者 (1.注册服务), 服务消费者 (2.消费服务), 服务提供和消费脑图 工程示例 注示例中为了简单采用rest请求方式来代替socket连接 注册中心 RestController
RequestMapping(index)
public class IndexController {Autowiredprivate RedisCacheTemplate redisCacheTemplate;//注册服务提供者信息将信息放到redis中RequestMapping(value register, method RequestMethod.POST)public SimpleResponse register(RequestBody RegisterMessage registerMessage) {try {MapString, Object map new HashMap();for (InterfaceMessage interfaceMessage : registerMessage.getInterfaceMessageList()) {interfaceMessage.setProviderUrl(registerMessage.getProviderUrl());map.put(ToStringBuilder.reflectionToString(interfaceMessage, ToStringStyle.SHORT_PREFIX_STYLE), true);}redisCacheTemplate.batchPut(map);return SimpleResponse.success(map.size());} catch (Exception e) {e.printStackTrace();return SimpleResponse.error(e.getMessage());}}//消费者拿到配置的服务信息到注册中心来匹配验证是否存在这个服务RequestMapping(value contains, method RequestMethod.POST)public SimpleResponse contains(RequestBody InterfaceMessage interfaceMessage) {try {if(redisCacheTemplate.exist(ToStringBuilder.reflectionToString(interfaceMessage, ToStringStyle.SHORT_PREFIX_STYLE))) {return SimpleResponse.success(true);} else {return SimpleResponse.error(null);}} catch (Exception e) {e.printStackTrace();return SimpleResponse.error(e.getMessage());}}RequestMapping(value test, method {RequestMethod.GET, RequestMethod.POST})public SimpleResponse test(RequestParam String providerUrl){return SimpleResponse.success(providerUrl);}
} 服务提供者 ?xml version1.0 encodingUTF-8?
services-providerservice idtestService interfacecom.hjzgg.simulation.api.ITestService/
/services-provider 自定义xml配置将要注册的服务id及对应的接口类。 # 内置tomcat服务器配置
server.port8088
server.context-path/provider-server#打印彩色日志
spring.output.ansi.enabledalways# 日志打印级别
logging.level.rootdebug# service
service.xml.pathclasspath:service-provider.xml 自定义服务提供者配置文件 位置
service.provider.pathhttp://localhost:8088/provider-server/index/provider 服务提供者执行相应服务接口
service.register.pathhttp://localhost:8090/register-server/index/register 调用注册中心 接口 import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.hjzgg.simulation.common.node.InterfaceMessage;
import com.hjzgg.simulation.common.node.RegisterMessage;
import com.hjzgg.simulation.common.parsexml.BeanNode;
import com.hjzgg.simulation.common.parsexml.ParseServiceXML;
import com.hjzgg.simulation.common.response.ReturnCode;
import com.hjzgg.simulation.common.utils.RestTemplateUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.env.Environment;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.http.MediaType;
import org.springframework.util.CollectionUtils;import java.util.ArrayList;
import java.util.List;public class Registrar implements ImportBeanDefinitionRegistrar, EnvironmentAware {private static Logger logger LoggerFactory.getLogger(Registrar.class);private String servicesXmlPath;private String serviceProviderPath;private String serviceRegisterPath;Overridepublic void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {ListBeanNode beanNodes ParseServiceXML.getProviderServices(servicesXmlPath); 解析自定义服务提供配置文件ListInterfaceMessage list new ArrayList();for(BeanNode beanNode : beanNodes) { 根据服务对应id去 寻找实现的 beanif(!registry.containsBeanDefinition(beanNode.getBeanName())) {logger.error(接口 beanNode.getBeanName() beanNode.getInterfaceCls().getTypeName() 没有对应的实现类);} else {InterfaceMessage interfaceMessage new InterfaceMessage();interfaceMessage.setBeanName(beanNode.getBeanName());interfaceMessage.setInterfacType(beanNode.getInterfaceCls().getTypeName());list.add(interfaceMessage);}}if(!CollectionUtils.isEmpty(list)) { 将配置的服务信息发送的注册中心RegisterMessage registerMessage new RegisterMessage();registerMessage.setProviderUrl(this.serviceProviderPath);registerMessage.setInterfaceMessageList(list);try {String result RestTemplateUtils.post(this.serviceRegisterPath, (JSONObject) JSON.toJSON(registerMessage), MediaType.APPLICATION_JSON_UTF8);JSONObject retJson JSONObject.parseObject(result);if(retJson.getInteger(code) ReturnCode.SUCCESS.getValue()) {logger.debug(服务注册成功...);} else {logger.error(服务注册失败... retJson.getString(msg));}} catch (Exception e) {e.printStackTrace();logger.error(服务注册失败... e.getMessage());}}}Overridepublic void setEnvironment(Environment environment) { 获取环境变量this.servicesXmlPath environment.getProperty(service.xml.path);this.serviceProviderPath environment.getProperty(service.provider.path);this.serviceRegisterPath environment.getProperty(service.register.path);assert(StringUtils.isNotEmpty(this.serviceProviderPath) StringUtils.isNotEmpty(serviceRegisterPath) StringUtils.isNotEmpty(this.servicesXmlPath));}
} import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;/*** Created by hujunzheng on 2017/7/7.*/Configuration
Import(Registrar.class)
public class Config { 注册服务配置启动
} import com.hjzgg.simulation.common.node.ServiceMessage;
import com.hjzgg.simulation.common.response.SimpleResponse;
import com.hjzgg.simulation.common.utils.ContextUtils;
import com.hjzgg.simulation.common.utils.SerializeUtil;
import org.apache.commons.codec.binary.Hex;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.springframework.util.ReflectionUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;/*** Created by hujunzheng on 2017/7/8.*/
RestController
RequestMapping(index)
public class IndexController {服务提供者执行相应服务接口RequestMapping(value invoke, method RequestMethod.POST)public Object invoke(RequestParam String serviceMessageBody) {try { 根据消费者传递的服务信息 找到对应的服务bean以及方法并利用反射执行方法最后返回结果ServiceMessage serviceMessage (ServiceMessage) SerializeUtil.unserialize(Hex.decodeHex(serviceMessageBody.toCharArray()));Object bean null;if((bean ContextUtils.getBean(serviceMessage.getBeanName(), serviceMessage.getRequireType())) ! null) {ListClass? classList new ArrayList();if(serviceMessage.getArgs() ! null) {for (Object obj : serviceMessage.getArgs()) {classList.add(obj.getClass());}}Method method ReflectionUtils.findMethod(bean.getClass(), serviceMessage.getMethodName(), classList.toArray(new Class?[0]));if(method ! null) {return method.invoke(bean, serviceMessage.getArgs());} else {return SimpleResponse.error(服务 serviceMessage.getRequireType().getTypeName() 中没有对应参数 ToStringBuilder.reflectionToString(classList) 的 serviceMessage.getMethodName() 方法);}} else {return SimpleResponse.error(没有名称为 serviceMessage.getBeanName() 且类型为 serviceMessage.getRequireType().getTypeName() 对应的bean);}} catch (Exception e) {e.printStackTrace();return SimpleResponse.error(e.getMessage());}}} 服务消费者 ?xml version1.0 encodingUTF-8?
services-consumerservice reftestService interfacecom.hjzgg.simulation.api.ITestService urlhttp://localhost:8088/provider-server/index/provider/
/services-consumer 自定义服务消费者配置服务引用名称接口类型调用服务提供者URL # 内置tomcat服务器配置
server.port8089
server.context-path/consumer-server#打印彩色日志
spring.output.ansi.enabledalways# 日志打印级别
logging.level.rootdebug# service xml
service.xml.pathclasspath:service-consumer.xml 自定义服务消费配置文件位置
service.contains.urlhttp://localhost:8090/register-server/index/contains 注册中心服务查询接口
service.invoke.urlhttp://localhost:8088/provider-server/index/invoke 服务提供者执行相应服务接口 import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.hjzgg.simulation.common.dynamic.JdkDynamicProxy;
import com.hjzgg.simulation.common.node.InterfaceMessage;
import com.hjzgg.simulation.common.parsexml.BeanNode;
import com.hjzgg.simulation.common.parsexml.ParseServiceXML;
import com.hjzgg.simulation.common.register.SpringBeanRegister;
import com.hjzgg.simulation.common.response.ReturnCode;
import com.hjzgg.simulation.common.utils.RestTemplateUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.env.Environment;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.http.MediaType;import java.util.Iterator;
import java.util.List;public class Registrar implements ImportBeanDefinitionRegistrar, EnvironmentAware{private Logger logger LoggerFactory.getLogger(Registrar.class);private String servicesXmlPath;private String serviceContainsPath;Overridepublic void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { 解析自定义服务消费配置文件ListBeanNode beanNodes ParseServiceXML.getConsumerServices(servicesXmlPath);判断注册中心 是否注册了这个服务了for(IteratorBeanNode it beanNodes.iterator(); it.hasNext(); ) {BeanNode beanNode it.next();InterfaceMessage interfaceMessage new InterfaceMessage();interfaceMessage.setProviderUrl(beanNode.getUrl());interfaceMessage.setInterfacType(beanNode.getInterfaceCls().getTypeName());interfaceMessage.setBeanName(beanNode.getBeanName());try {String result RestTemplateUtils.post(this.serviceContainsPath, (JSONObject) JSON.toJSON(interfaceMessage), MediaType.APPLICATION_JSON_UTF8);JSONObject retJson JSON.parseObject(result);if (retJson.getInteger(code) ReturnCode.FAILURE.getValue()) {it.remove();logger.error(interfaceMessage.getBeanName() 对应类型 interfaceMessage.getInterfacType() 的服务在 interfaceMessage.getProviderUrl() 上没有注册);}} catch (Exception e) {e.printStackTrace();logger.error(服务 interfaceMessage.getBeanName() 对应类型 interfaceMessage.getInterfacType() 查找失败... e.getMessage());}} 将与注册中心一直的服务 以 动态代理的方式 注册到spring中SpringBeanRegister.registerBean(importingClassMetadata, registry, beanNodes);}Overridepublic void setEnvironment(Environment environment) { 设置环境变量this.servicesXmlPath environment.getProperty(service.xml.path);this.serviceContainsPath environment.getProperty(service.contains.url);String serviceInvokePath environment.getProperty(service.invoke.url);assert(StringUtils.isNotEmpty(serviceContainsPath) StringUtils.isNotEmpty(this.servicesXmlPath) StringUtils.isNotEmpty(serviceInvokePath));JdkDynamicProxy.setServerProviderInvokeUrl(serviceInvokePath);}
} import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;/*** Created by hujunzheng on 2017/7/7.*/Configuration
Import(Registrar.class)
public class Config {
} 测试一下 api接口 import com.alibaba.fastjson.JSONObject;/*** Created by hujunzheng on 2017/7/7.*/
public interface ITestService {JSONObject testService();
} 服务提供者对应的实例 import com.alibaba.fastjson.JSONObject;
import com.hjzgg.simulation.api.ITestService;
import org.springframework.stereotype.Service;/*** Created by hujunzheng on 2017/7/8.*/
Service(testService)
public class TestServiceImpl implements ITestService {Overridepublic JSONObject testService() {JSONObject result new JSONObject();result.put(name, hujunzheng);result.put(age, 25);return result;}
} 消费者对应的测试 import com.hjzgg.simulation.api.ITestService;
import com.hjzgg.simulation.common.response.SimpleResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;/*** Created by hujunzheng on 2017/7/9.*/
RestController
RequestMapping(index)
public class ConsumerController {Autowiredprivate ITestService testService;RequestMapping(test)public SimpleResponse test() {try {return SimpleResponse.success(testService.testService());} catch (Exception e) {e.printStackTrace();return SimpleResponse.error(e.getMessage());}}
} 这就是我的实现方式就说到这里了。最后我想说思路很重要掌握的知识很重要多积累多思考任重而道远。最后附上我从中积累的知识和经验。 知识和经验 执行顺序及ProxyFactoryBean实现 Public class ProxyFactoryBean implements FactoryBean, InitializingBean; 方法执行顺序 getObjectType-afterPropertiesSet-getObject bean 的属性设置的 先于 getObjectType Springboot 工程自定义jar包中获取上下文工具类 要加上 Component注解 实体类型例如下面网络传输方法避免字符串编码格式问题 发送请求 ServiceMessage serviceMessage new ServiceMessage();。。。。。JSONObject params new JSONObject();params.put(serviceMessageBody, Hex.encodeHexString(SerializeUtil.serialize(serviceMessage)));Class? returnType method.getReturnType();return RestTemplateUtils.post(SERVER_PROVIDER_INVOKE_URL, params, MediaType.APPLICATION_FORM_URLENCODED, returnType); 接收请求 RequestMapping(value invoke, method RequestMethod.POST) public Object invoke(RequestParam String serviceMessageBody) { try { ServiceMessage serviceMessage (ServiceMessage) SerializeUtil.unserialize(Hex.decodeHex(serviceMessageBody.toCharArray())); 。。。。。 } 参考工具类 dependency groupIdcommons-codec/groupId artifactIdcommons-codec/artifactId/dependency Hex实现十六进制字符串和byte[]之间的转换另附RestTemplateUtils工具链接 完整项目下载请点这里! 转载于:https://www.cnblogs.com/hujunzheng/p/7131212.html