spring AbstractBeanDefinition創建bean類型是動態代理類的方式

1.接口?Class<?> resourceClass

2.獲取builder

BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(resourceClass);

3.獲取接口對應的動態代理class

Class<?> targetProxyClass = Proxy.getProxyClass(XXX.class.getClassLoader(), new Class[]{resourceClass});

4.targetProxyClass構造參數類型?InvocationHandler,通過builder設置

? ?builder.addConstructorArgValue(Proxy.getInvocationHandler(xxxProxyBean) 或者 new?InvocationHandler(){...});

 AbstractBeanDefinition beanDefinition = builder.getBeanDefinition();

? ?beanDefinition.setBeanClass(targetProxyClass);

? ?registry.registerBeanDefinition("beanName", beanDefinition);

?

5.記錄一下自己曾經寫的一個例子

5.1 抽象類ProxyFactoryBean

package com.hjzgg.apigateway.soa.proxy;import com.hjzgg.apigateway.soa.exceptions.SoaException;
import com.hjzgg.apigateway.soa.proxy.consumer.ConsumerProxyFactoryBean;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.util.ClassUtils;import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Objects;
import java.util.stream.Collectors;
import java.util.stream.Stream;/*** Created by hujunzheng on 2017/7/7.*/
public abstract class ProxyFactoryBean implements FactoryBean {protected Class<?> selfDynamicProxyClass;//代理類protected Class<?> resourceClass;//接口類protected String version;//dubbo 版本protected String group;//dubbo 分組protected Object proxy;//代理對象protected Method createProxyMethod;public ProxyFactoryBean(Class<?> selfDynamicProxyClass, Class<?> resourceClass, String version, String group) throws SoaException {if (Objects.isNull(selfDynamicProxyClass)) {throw new SoaException("selfDynamicProxyClass 動態代理類不能為null");}try {this.createProxyMethod = Stream.of(selfDynamicProxyClass.getMethods()).filter(method -> Modifier.isStatic(method.getModifiers())&& Modifier.isPublic(method.getModifiers())&& !Modifier.isAbstract(method.getModifiers())&& method.getParameters().length == 2&& method.getParameters()[0].getType().equals(ProxyFactoryBean.class)&& method.getParameters()[1].getType().equals(Class.class)&& !method.getReturnType().equals(void.class)).collect(Collectors.toList()).get(0);} catch (Exception e) {throw new SoaException("500", String.format("%s %s %s和%s %s, %s %s", ClassUtils.getQualifiedName(selfDynamicProxyClass), " 沒有參數類型是 ", ClassUtils.getQualifiedName(ConsumerProxyFactoryBean.class), ClassUtils.getQualifiedName(Class.class), " 的、公共的、非抽象的、返回值非void的方法", "請將你的動態代理類繼承", ClassUtils.getQualifiedName(DynamicProxyAdapter.class)), e);}this.selfDynamicProxyClass = selfDynamicProxyClass;this.resourceClass = resourceClass;this.version = version;this.group = group;}protected Object newInstance() throws SoaException {if(this.isSingleton() && this.proxy != null) {return proxy;}synchronized (this) {Object target;try {target = this.createProxyMethod.invoke(null,this, selfDynamicProxyClass);} catch (Exception e) {throw new SoaException("500", String.format("%s %s %s", ClassUtils.getQualifiedName(selfDynamicProxyClass), createProxyMethod.getName(), "創建代理類異常"), e);}if(proxy == null) {proxy = target;}return target;}}public Class<?> getSelfDynamicProxyClass() {return selfDynamicProxyClass;}public void setSelfDynamicProxyClass(Class<?> selfDynamicProxyClass) {this.selfDynamicProxyClass = selfDynamicProxyClass;}public Class<?> getResourceClass() {return resourceClass;}public void setResourceClass(Class<?> resourceClass) {this.resourceClass = resourceClass;}public String getVersion() {return version;}public void setVersion(String version) {this.version = version;}public String getGroup() {return group;}public void setGroup(String group) {this.group = group;}
}

5.2?ProxyFactoryBean具體實現類ProviderProxyFactoryBean

package com.hjzgg.apigateway.soa.proxy.provider;import com.hjzgg.apigateway.soa.exceptions.SoaException;
import com.hjzgg.apigateway.soa.proxy.ProxyFactoryBean;
import org.springframework.aop.SpringProxy;
import org.springframework.aop.TargetClassAware;import java.lang.reflect.Method;
import java.lang.reflect.Proxy;/*** @author hujunzheng* @create 2018-02-18 下午3:01**/
public class ProviderProxyFactoryBean extends ProxyFactoryBean {public ProviderProxyFactoryBean(Class<?> selfDynamicProxyClass, Class<?> resourceClass, String version, String group) throws SoaException {super(selfDynamicProxyClass, resourceClass, version, group);}@Overridepublic Object getObject() throws Exception {return this.newInstance();}@Overridepublic Class<?> getObjectType() {return resourceClass;}@Overridepublic boolean isSingleton() {return true;}public static Class<?> getProxyClass(Class<?> resourceClass) {/*** @see com.hjzgg.apigateway.dubbo.configure.SelfDubboAnnotationBean#postProcessAfterInitialization(Object, String)* @see org.springframework.aop.support.AopUtils#isAopProxy(Object)* @see org.springframework.aop.support.AopUtils#getTargetClass(Object)* @see com.hjzgg.apigateway.soa.proxy.provider.ProviderDynamicProxy#invoke(Object, Method, Object[])* */return Proxy.getProxyClass(ProviderProxyFactoryBean.class.getClassLoader(), new Class[]{resourceClass, SpringProxy.class, TargetClassAware.class});}
}

5.3 動態代理適配器DynamicProxyAdapter

package com.hjzgg.apigateway.soa.proxy;import com.hjzgg.apigateway.soa.exceptions.SoaException;
import org.springframework.util.ClassUtils;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;/*** @author hujunzheng* @create 2018-02-04 上午12:00**/
public class DynamicProxyAdapter implements InvocationHandler {public DynamicProxyAdapter(ProxyFactoryBean factoryBean) {this.bean = factoryBean;}protected ProxyFactoryBean bean;@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {throw new SoaException(String.format("%s %s %s", "你應當重寫", ClassUtils.getQualifiedName(DynamicProxyAdapter.class), "invoke方法"));}public static Object createJDKProxy(ProxyFactoryBean factoryBean, Class<?> selfDynamicProxyClass) throws SoaException {if (!DynamicProxyAdapter.class.equals(selfDynamicProxyClass.getSuperclass())) {throw new SoaException(String.format("%s %s %s", ClassUtils.getQualifiedName(selfDynamicProxyClass), "需要繼承", ClassUtils.getQualifiedName(DynamicProxyAdapter.class)));}Object selfDynamicProxyInstance;try {selfDynamicProxyInstance = selfDynamicProxyClass.getConstructor(factoryBean.getClass()).newInstance(factoryBean);} catch (Exception e) {throw new SoaException("500", "動態代理類創建失敗", e);}Object proxy = Proxy.newProxyInstance(selfDynamicProxyClass.getClassLoader(),new Class[]{factoryBean.getResourceClass()}, (InvocationHandler) selfDynamicProxyInstance);return proxy;}
}

5.4 繼承DynamicProxyAdapter 實現invoke接口?ProviderDynamicProxy

package com.hjzgg.apigateway.soa.proxy.provider;import com.hjzgg.apigateway.commons.utils.ContextUtils;
import com.hjzgg.apigateway.soa.annotation.SOAImplements;
import com.hjzgg.apigateway.soa.exceptions.SoaException;
import com.hjzgg.apigateway.soa.proxy.DynamicProxyAdapter;
import com.hjzgg.apigateway.soa.proxy.consumer.ConsumerProxyFactoryBean;
import org.springframework.aop.TargetClassAware;
import org.springframework.util.ClassUtils;import java.lang.reflect.Method;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Stream;public class ProviderDynamicProxy extends DynamicProxyAdapter {private static final ConcurrentHashMap<Class<?>, Object> map = new ConcurrentHashMap<>();public ProviderDynamicProxy(ProviderProxyFactoryBean factoryBean) {super(factoryBean);}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {try {if (method.equals(TargetClassAware.class.getMethod("getTargetClass", new Class[]{}))) {return bean.getResourceClass();}return method.invoke(this.findRelevantServiceProvider(), args);} catch (Exception e) {throw new SoaException("500", String.format("%s %s %s", "invoke service proxy object error!", ClassUtils.getQualifiedName(this.bean.getResourceClass()), method.getName()), e);}}private Object findRelevantServiceProvider() throws SoaException {Class<?> resourceClass = super.bean.getResourceClass();if (!map.contains(resourceClass)) {Stream<?> stream = ContextUtils.getBeans(SOAImplements.class).stream().filter(serviceProvider -> resourceClass.isAssignableFrom(serviceProvider.getClass()));if (stream.count() > 1) {throw new SoaException(String.format("multiple relevant service provider found with annotation %s and interface is %s", ClassUtils.getQualifiedName(SOAImplements.class), ClassUtils.getQualifiedName(resourceClass)));}if (stream.count() == 1) {map.put(resourceClass, stream.findFirst().get());} else {List<?> objects = ContextUtils.getBeans(SOAImplements.class);if (objects.size() > 1) {throw new SoaException(String.format("multiple relevant service provider found with annotation %s", ClassUtils.getQualifiedName(SOAImplements.class)));}if (objects.size() == 1) {map.put(resourceClass, objects.get(0));} else {try {Object object = ContextUtils.getBean(resourceClass);map.put(resourceClass, object);} catch (Exception e) {throw new SoaException("500", String.format("find relevant service provider with interface %s error", ClassUtils.getQualifiedName(resourceClass)), e);}}}}return map.get(resourceClass);}
}

5.5 注冊類型是jdk proxy類型的bean

//參數dynamicProxyClass 是 ProviderDynamicProxy
public static boolean registerProvider(BeanDefinitionRegistry registry, Class<?> dynamicProxyClass, Class<?> resourceClass) {String apiClassInfo = ClassUtils.getQualifiedName(resourceClass);try {/*** 通過代理bean的方式創建創建 服務bean* @see com.hjzgg.apigateway.dubbo.configure.SelfDubboAnnotationBean#postProcessAfterInitialization(Object, String)* if (AopUtils.isAopProxy(bean)), 判斷bean的類型如果是代理類型,進行dubbo注解解析處理* */BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(resourceClass);String dubboVersion = resourceClass.getAnnotation(Service.class).version();String dubboGroup = resourceClass.getAnnotation(Service.class).group();ProviderProxyFactoryBean providerProxyFactoryBean = new ProviderProxyFactoryBean(dynamicProxyClass, resourceClass, dubboVersion, dubboGroup);/*** providerProxyFactoryBean.getObject() 得到的是通過 Proxy.newInstance方法獲取到的代理類* @see com.hjzgg.apigateway.soa.proxy.DynamicProxyAdapter#createJDKProxy(ProxyFactoryBean, Class)* 可通過 Proxy.getInvocationHandler方法拿到 InvocationHandler實例*/Class<?> targetProxyClass = ProviderProxyFactoryBean.getProxyClass(resourceClass);builder.addConstructorArgValue(Proxy.getInvocationHandler(providerProxyFactoryBean.getObject()));AbstractBeanDefinition beanDefinition = builder.getBeanDefinition();beanDefinition.setBeanClass(targetProxyClass);beanDefinition.setAttribute(Constants.API_CLASS_INFO, resourceClass);String beanName = beanNameGenerator.generateBeanName(beanDefinition, registry);if (registry.containsBeanDefinition(beanName)) {log.debug(beanName + " already exists! Class is " + apiClassInfo + " .");return false;}registry.registerBeanDefinition(beanName, beanDefinition);return true;} catch (Exception e) {log.error("registerProvider proxy bean error! Class is " + apiClassInfo + " .");return false;}
}

5.6 附加SelfDubboAnnotationBean

package com.hjzgg.apigateway.dubbo.configure;import com.alibaba.dubbo.common.Constants;
import com.alibaba.dubbo.common.logger.Logger;
import com.alibaba.dubbo.common.logger.LoggerFactory;
import com.alibaba.dubbo.common.utils.ConcurrentHashSet;
import com.alibaba.dubbo.config.*;
import com.alibaba.dubbo.config.annotation.Service;
import com.alibaba.dubbo.config.spring.ReferenceBean;
import com.alibaba.dubbo.config.spring.ServiceBean;
import org.springframework.aop.support.AopUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.util.ClassUtils;import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.stream.Collectors;
import java.util.stream.Stream;/*** @see com.alibaba.dubbo.config.spring.AnnotationBean*/
public class SelfDubboAnnotationBean extends AbstractConfig implements DisposableBean, BeanPostProcessor, ApplicationContextAware, Serializable {private static final Logger logger = LoggerFactory.getLogger(Logger.class);private String annotationPackage;private String[] annotationPackages;private final Set<ServiceConfig<?>> serviceConfigs = new ConcurrentHashSet<>();private final ConcurrentMap<String, ReferenceBean<?>> referenceConfigs = new ConcurrentHashMap<>();public String getPackage() {return annotationPackage;}public void setPackage(String annotationPackage) {this.annotationPackage = annotationPackage;this.annotationPackages = (annotationPackage == null || annotationPackage.length() == 0) ? null: Constants.COMMA_SPLIT_PATTERN.split(annotationPackage);}private ApplicationContext applicationContext;public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {this.applicationContext = applicationContext;}public void destroy() throws Exception {for (ServiceConfig<?> serviceConfig : serviceConfigs) {try {serviceConfig.unexport();} catch (Throwable e) {logger.error(e.getMessage(), e);}}for (ReferenceConfig<?> referenceConfig : referenceConfigs.values()) {try {referenceConfig.destroy();} catch (Throwable e) {logger.error(e.getMessage(), e);}}}public Object postProcessAfterInitialization(Object bean, String beanName)throws BeansException {if (! isMatchPackage(bean)) {return bean;}if (AopUtils.isAopProxy(bean)) {/*** @see com.hjzgg.apigateway.soa.executor.RegisterBeanUtils#registerProvider* @see com.hjzgg.apigateway.soa.proxy.provider.ProviderDynamicProxy#invoke* *///獲取被代理的真實類或者接口類Class<?> targetClass = AopUtils.getTargetClass(bean);Service service = targetClass.getAnnotation(Service.class);if (service != null) {ServiceBean<Object> serviceConfig = new ServiceBean<Object>(service);if (void.class.equals(service.interfaceClass())&& "".equals(service.interfaceName())) {if (!(targetClass.isInterface() || targetClass.getInterfaces().length > 0)) {throw new IllegalStateException("Failed to export remote service class " + bean.getClass().getName() + ", cause: The @Service undefined interfaceClass or interfaceName, and the service class unimplemented any interfaces.");} else {if (targetClass.isInterface()) {serviceConfig.setInterface(targetClass);}if (targetClass.getInterfaces().length > 0) {serviceConfig.setInterface(targetClass.getInterfaces()[0]);}}}if (applicationContext != null) {serviceConfig.setApplicationContext(applicationContext);if (service.registry() != null && service.registry().length > 0) {List<RegistryConfig> registryConfigs = new ArrayList<RegistryConfig>();for (String registryId : service.registry()) {if (registryId != null && registryId.length() > 0) {registryConfigs.add(applicationContext.getBean(registryId, RegistryConfig.class));}}serviceConfig.setRegistries(registryConfigs);}if (service.provider() != null && service.provider().length() > 0) {serviceConfig.setProvider(applicationContext.getBean(service.provider(),ProviderConfig.class));}if (service.monitor() != null && service.monitor().length() > 0) {serviceConfig.setMonitor(applicationContext.getBean(service.monitor(), MonitorConfig.class));}if (service.application() != null && service.application().length() > 0) {serviceConfig.setApplication(applicationContext.getBean(service.application(), ApplicationConfig.class));}if (service.module() != null && service.module().length() > 0) {serviceConfig.setModule(applicationContext.getBean(service.module(), ModuleConfig.class));}if (service.provider() != null && service.provider().length() > 0) {serviceConfig.setProvider(applicationContext.getBean(service.provider(), ProviderConfig.class));}if (service.protocol() != null && service.protocol().length > 0) {List<ProtocolConfig> protocolConfigs = new ArrayList<ProtocolConfig>();for (String protocolId : service.registry()) {if (protocolId != null && protocolId.length() > 0) {protocolConfigs.add(applicationContext.getBean(protocolId, ProtocolConfig.class));}}serviceConfig.setProtocols(protocolConfigs);}try {serviceConfig.afterPropertiesSet();} catch (RuntimeException e) {throw e;} catch (Exception e) {throw new IllegalStateException(e.getMessage(), e);}}serviceConfig.setRef(bean);serviceConfigs.add(serviceConfig);serviceConfig.export();}}return bean;}public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {Service service = (AopUtils.isAopProxy(bean) && !Objects.isNull(AopUtils.getTargetClass(bean).getAnnotation(Service.class)))? AopUtils.getTargetClass(bean).getAnnotation(Service.class): bean.getClass().getAnnotation(Service.class);if (Objects.isNull(service)) {return bean;}try {InvocationHandler h = Proxy.getInvocationHandler(service);// 獲取 AnnotationInvocationHandler 的 memberValues 字段Field memberValuesField = h.getClass().getDeclaredField("memberValues");// 因為這個字段事 private final 修飾,所以要打開權限memberValuesField.setAccessible(true);// 獲取 memberValuesMap memberValues = (Map) memberValuesField.get(h);Service serviceInstance = Stream.of(bean.getClass().getInterfaces()).filter(iface -> iface.getAnnotation(Service.class) != null).collect(Collectors.toList()).get(0).getAnnotation(Service.class);memberValues.put("version", serviceInstance.version());memberValues.put("group", serviceInstance.group());} catch (Exception e) {throw new BeanCreationException(String.format("%s %s %s %s %s", "修改", ClassUtils.getQualifiedName(bean.getClass()), "的注解", ClassUtils.getQualifiedName(Service.class), "的 group值和version值出錯"), e);}return bean;}private boolean isMatchPackage(Object bean) {if (annotationPackages == null || annotationPackages.length == 0) {return true;}String beanClassName = bean.getClass().getName();for (String pkg : annotationPackages) {if (beanClassName.startsWith(pkg)) {return true;}}return false;}}
View Code

?5.7 附加AopUtils相關方法

/*** Check whether the given object is a JDK dynamic proxy or a CGLIB proxy.* <p>This method additionally checks if the given object is an instance* of {@link SpringProxy}.* @param object the object to check* @see #isJdkDynamicProxy* @see #isCglibProxy*/
public static boolean isAopProxy(Object object) {return (object instanceof SpringProxy &&(Proxy.isProxyClass(object.getClass()) || ClassUtils.isCglibProxyClass(object.getClass())));
}/*** Determine the target class of the given bean instance which might be an AOP proxy.* <p>Returns the target class for an AOP proxy or the plain class otherwise.* @param candidate the instance to check (might be an AOP proxy)* @return the target class (or the plain class of the given object as fallback;* never {@code null})* @see org.springframework.aop.TargetClassAware#getTargetClass()* @see org.springframework.aop.framework.AopProxyUtils#ultimateTargetClass(Object)*/
public static Class<?> getTargetClass(Object candidate) {Assert.notNull(candidate, "Candidate object must not be null");Class<?> result = null;if (candidate instanceof TargetClassAware) {result = ((TargetClassAware) candidate).getTargetClass();}if (result == null) {result = (isCglibProxy(candidate) ? candidate.getClass().getSuperclass() : candidate.getClass());}return result;
}
View Code

?

轉載于:https://www.cnblogs.com/hujunzheng/p/8527338.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/531230.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/531230.shtml
英文地址,請注明出處:http://en.pswp.cn/news/531230.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

TypeReference -- 讓Jackson Json在List/Map中識別自己的Object

private Map<String, Object> buildHeaders(Object params) {ObjectMapper objectMapper JacksonHelper.getMapper();return objectMapper.convertValue(params, new TypeReference<Map<String, Object>>(){}); } 參考How to use Jackson to deserialis…

微信小程序:一起玩連線,一個算法來搞定

微信小程序&#xff1a;一起玩連線 游戲玩法 將相同顏色的結點連接在一起&#xff0c;連線之間不能交叉。 算法思想 轉換為多個源點到達對應終點的路徑問題&#xff0c;且路徑之間不相交。按照dfs方式尋找兩個結點路徑&#xff0c;一條路徑探索完之后&#xff0c;標記地圖并記錄…

IntelliJ IDEA關于logger的live template配置

1.安裝 log support2插件 2.配置log support2 由于項目中的日志框架是公司自己封裝的&#xff0c;所以還需要自己手動改一下 log support2插件生成的live template 當然也可以修改 Log support global的配置 包括 Logger Field、Logger class、Logger Factory class都可以修改。…

springboot項目接入配置中心,實現@ConfigurationProperties的bean屬性刷新方案

前言 配置中心&#xff0c;通過keyvalue的形式存儲環境變量。配置中心的屬性做了修改&#xff0c;項目中可以通過配置中心的依賴&#xff08;sdk&#xff09;立即感知到。需要做的就是如何在屬性發生變化時&#xff0c;改變帶有ConfigurationProperties的bean的相關屬性。 配置…

jackson實現java對象轉支付寶/微信模板消息

一、支付寶消息模板大致長這樣 {"to_user_id": "","telephone": "xxxxx","template": {"template_id": "xxxxxx","context": {"head_color": "#85be53","url"…

簡單封裝kafka相關的api

一、針對于kafka版本 <dependency><groupId>org.apache.kafka</groupId><artifactId>kafka-clients</artifactId><version>0.8.2.2</version></dependency><dependency><groupId>org.apache.kafka</groupId>…

springmvc controller動態設置content-type

springmvc RequestMappingHandlerAdapter#invokeHandlerMethod 通過ServletInvocableHandlerMethod#invokeAndHandle調用目標方法&#xff0c;并處理返回值。 如果return value &#xff01; null&#xff0c;則通過returnvalueHandlers處理&#xff0c;內部會調用MessageConv…

springboot2.0 redis EnableCaching的配置和使用

一、前言 關于EnableCaching最簡單使用&#xff0c;個人感覺只需提供一個CacheManager的一個實例就好了。springboot為我們提供了cache相關的自動配置。引入cache模塊&#xff0c;如下。 二、maven依賴 <dependency><groupId>org.springframework.boot</groupId…

依賴配置中心實現注有@ConfigurationProperties的bean相關屬性刷新

配置中心是什么 配置中心&#xff0c;通過keyvalue的形式存儲環境變量。配置中心的屬性做了修改&#xff0c;項目中可以通過配置中心的依賴&#xff08;sdk&#xff09;立即感知到。需要做的就是如何在屬性發生變化時&#xff0c;改變帶有ConfigurationProperties的bean的相關屬…

java接口簽名(Signature)實現方案

預祝大家國慶節快樂&#xff0c;趕快迎接美麗而快樂的假期吧&#xff01;&#xff01;&#xff01; 前言 在為第三方系統提供接口的時候&#xff0c;肯定要考慮接口數據的安全問題&#xff0c;比如數據是否被篡改&#xff0c;數據是否已經過時&#xff0c;數據是否可以重復提交…

Git rebase命令實戰

一、前言 一句話&#xff0c;git rebase 可以幫助項目中的提交歷史干凈整潔&#xff01;&#xff01;&#xff01; 二、避免合并出現分叉現象 git merge操作 1、新建一個 develop 分支 2、在develop分支上新建兩個文件 3、然后分別執行 add、commit、push 4、接著切換到master分…

HttpServletRequestWrapper使用技巧(自定義session和緩存InputStream)

一、前言 javax.servlet.http.HttpServletRequestWrapper 是一個開發者可以繼承的類&#xff0c;我們可以重寫相應的方法來實現session的自定義以及緩存InputStream&#xff0c;在程序中可以多次獲取request body的內容。 二、自定義seesion import javax.servlet.http.*;publi…

spring注解工具類AnnotatedElementUtils和AnnotationUtils

一、前言 spring為開發人員提供了兩個搜索注解的工具類&#xff0c;分別是AnnotatedElementUtils和AnnotationUtils。在使用的時候&#xff0c;總是傻傻分不清&#xff0c;什么情況下使用哪一個。于是我做了如下的整理和總結。 二、AnnotationUtils官方解釋 功能 用于處理注解&…

windows系統nexus3安裝和配置

一、前言 為什么要在本地開發機器上安裝nexus&#xff1f;首先聲明公司內部是有自己的nexus倉庫&#xff0c;但是對上傳jar包做了限制&#xff0c;不能暢快的上傳自己測試包依賴。于是就自己在本地搭建了一個nexus私服&#xff0c;即可以使用公司nexus私服倉庫中的依賴&#xf…

Springmvc借助SimpleUrlHandlerMapping實現接口開關功能

一、接口開關功能 1、可配置化&#xff0c;依賴配置中心 2、接口訪問權限可控 3、springmvc不會掃描到&#xff0c;即不會直接的將接口暴露出去 二、接口開關使用場景 和業務沒什么關系&#xff0c;主要方便查詢系統中的一些狀態信息。比如系統的配置信息&#xff0c;中間件的狀…

log4j平穩升級到log4j2

一、前言 公司中的項目雖然已經用了很多的新技術了&#xff0c;但是日志的底層框架還是log4j&#xff0c;個人還是不喜歡用這個的。最近項目再生產環境上由于log4j引起了一場血案&#xff0c;于是決定升級到log4j2。 二、現象 雖然生產環境有多個結點分散高并發帶來的壓力&…

Springboot集成ES啟動報錯

報錯內容 None of the configured nodes are available elasticsearch.yml配置 cluster.name: ftest node.name: node-72 node.master: true node.data: true network.host: 112.122.245.212 http.port: 39200 transport.tcp.port: 39300 discovery.zen.ping.unicast.hosts: [&…

高效使用hibernate-validator校驗框架

一、前言 高效、合理的使用hibernate-validator校驗框架可以提高程序的可讀性&#xff0c;以及減少不必要的代碼邏輯。接下來會介紹一下常用一些使用方式。 二、常用注解說明 限制說明Null限制只能為nullNotNull限制必須不為nullAssertFalse限制必須為falseAssertTrue限制必須為…

kafka-manager配置和使用

kafka-manager配置 最主要配置就是用于kafka管理器狀態的zookeeper主機。這可以在conf目錄中的application.conf文件中找到。 kafka-manager.zkhosts"my.zookeeper.host.com:2181" 當然也可以聲明為zookeeper集群。 kafka-manager.zkhosts"my.zookeeper.host.co…

kafka告警簡單方案

一、前言 為什么要設計kafka告警方案&#xff1f;現成的監控項目百度一下一大堆&#xff0c;KafkaOffsetMonitor、KafkaManager、 Burrow等&#xff0c;具體參考&#xff1a;kafka的消息擠壓監控。由于本小組的項目使用的kafka集群并沒有被公司的kafka-manager管理&#xff0c;…