记录一次源码扩展案列——FastJson自定义反序列化ValueMutator

背景:曾经遇到一个很麻烦的事情,就是一个json串中有很多占位符,需要替换成特定文案。如果将json转换成对象后,在一个一个属性去转换的话就出出现很多冗余代码,不美观也不是很实用。
而且也不能提前在json串中替换,因为替换的文案会因为某些变量发生改变。就比如国际化,在中文的时候应该是"你好",而在英文的时候要出现"Hello"。
所以我想到一个方法,为什么不能再json反序列化的时候,把这些都做好呢?
以下的代码介绍的是,我自己扩展的一点点fastjson代码,增加了在反序列化的时候可以对所有的值进行修改的方案。
注意:这个方案会对fastjson反序列化的速度有一定的影响,我只是用来做配置的反序列化,完成后将反序列化的东西缓存起来使用。
使用方式有两种
一种是直接通过 @JsonDeserializer 注解的valueMutators属性注入这种方式有个缺陷,你的修改器必须有无参构造函数的
@JsonDeserializer(valueMutators = {CoustomizeValueMutator.class})
@Getter
@Setter
public class User {
private String name;
...
}
第二种方式是通过直接创建的方式,使用反序列化工具,这种方式支持有参构造函数。
CoustomizeValueMutator zhCoustomizeValueMutator = new CoustomizeValueMutator(zh);
User user = CustomizeJSON.parseObject(userStr, User.class, zhCoustomizeValueMutator);
下面先展示一下使用效果,测试代码如下:
import com.alibaba.fastjson.parser.deserializer.CustomizeJSON;
import com.raiden.model.*;
import org.junit.jupiter.api.Test; import java.util.*; /**
* @创建人:Raiden
* @Descriotion:
* @Date:Created in 22:39 2020/1/28
* @Modified By:
*/
public class AppTest { @Test
public void testFastJosn() throws Throwable {
String userStr = "{\n" +
"\t\"id\":\"I18nKey:20200411001\",\n" +
"\t\"a\":\"I18nKey:张三\",\n" +
"\t\"student\":\"I18nKey:高三三班\",\n" +
"\t\"contents\":[\"I18nKey:1\",\"I18nKey:2\"]\n" +
"}";
Map<String, String> en = new HashMap<>();
en.put("3", "zhangsan");
en.put("4", "20200411001");
en.put("5", "Class three in grade three");
en.put("1", "Hello");
en.put("2", "Welcome home");
Map<String, String> zh = new HashMap<>();
zh.put("3", "张三");
zh.put("4", "20200411001");
zh.put("5", "高三三班");
zh.put("1", "你好");
zh.put("2", "欢迎回家");
CoustomizeValueMutator zhCoustomizeValueMutator = new CoustomizeValueMutator(zh); User user = CustomizeJSON.parseObject(userStr, User.class, zhCoustomizeValueMutator);
System.err.println(user);
String string = "{\n" +
"\t\"users\": [{\n" +
"\t\t\"id\": \"I18nKey:4\",\n" +
"\t\t\"a\": \"I18nKey:3\",\n" +
"\t\t\"student\": \"I18nKey:5\",\n" +
"\t\t\"url\": \"www.baidu.com\",\n" +
"\t\t\"contents\": [\"I18nKey:1\", \"I18nKey:2\"]\n" +
"\t}],\n" +
"\t\"memberId\":\"2020\"\n" +
"}";
CoustomizeValueMutator enCoustomizeValueMutator = new CoustomizeValueMutator(en);
Administration administration = CustomizeJSON.parseObject(string, Administration.class, enCoustomizeValueMutator);
System.err.println(administration);
}
}
运行效果:

下面是测试模型代码:
import com.alibaba.fastjson.parser.deserializer.JsonDeserializer;
import com.raiden.CoustomizeValueMutator;
import lombok.Getter;
import lombok.Setter; import java.util.List; /**
* @创建人:Raiden
* @Descriotion:
* @Date:Created in 23:56 2020/4/17
* @Modified By:
*/
@JsonDeserializer
@Getter
@Setter
public class Administration { private List<User> users;
private String memberId; @Override
public String toString() {
return "Administration{" +
"users=" + users +
", memberId='" + memberId + '\'' +
'}';
}
}
import com.alibaba.fastjson.parser.deserializer.JsonDeserializer;
import lombok.Getter;
import lombok.Setter; import java.util.List; /**
* @创建人:Raiden
* @Descriotion:
* @Date:Created in 15:53 2020/3/21
* @Modified By:
*/
@JsonDeserializer
@Getter
@Setter
public class User { private String name;
private String id;
private String student;
private List<String> contents;
private String url; @Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", id='" + id + '\'' +
", student='" + student + '\'' +
", contents='" + contents.toString() + '\'' +
", url='" + url + '\'' +
'}';
}
}
自定义的反序列化值修改器:
import com.alibaba.fastjson.parser.deserializer.DeserializerValueMutator; import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.List;
import java.util.Map; /**
* @创建人:Raiden
* @Descriotion:
* @Date:Created in 22:15 2020/5/1
* @Modified By:
*/
public class CoustomizeValueMutator implements DeserializerValueMutator { private Map<String, String> dataSource; public CoustomizeValueMutator(Map<String, String> dataSource){
this.dataSource = dataSource;
}
@Override
public Object process(Object object, Annotation[] annotations, String name, Object value) {
if (value instanceof List){
List list = new ArrayList();
for (Object o : (List) value){
if (!(o instanceof String)){
return value;
}
list.add(DeserializerUtils.deserializer(o, dataSource));
}
return list;
}
return DeserializerUtils.deserializer(value, dataSource);
}
}
一些工具类和静态资源类:
/**
* @创建人:Raiden
* @Descriotion:
* @Date:Created in 23:00 2020/4/17
* @Modified By:
*/
public class CustomizeStaticConfig {
public static final String I18N_KEY = "I18nKey:";
}
import org.apache.commons.lang3.StringUtils; import java.util.Map; /**
* @创建人:Raiden
* @Descriotion:
* @Date:Created in 0:15 2020/4/18
* @Modified By:
*/
public final class DeserializerUtils { public static final Object deserializer(Object value, Map<String, String> languageConfig){
String result = null;
if (value.getClass() == String.class && StringUtils.contains((result = ((String) value).trim()), CustomizeStaticConfig.I18N_KEY)){
int indexOf = result.indexOf(CustomizeStaticConfig.I18N_KEY) + CustomizeStaticConfig.I18N_KEY.length();
String key = StringUtils.substring(result, indexOf);
return languageConfig.getOrDefault(key, result);
}
return value;
}
}
下面给出的是扩展的关键代码。
首先是自定义解析配置类,这个类是核心。这个类继承了 com.alibaba.fastjson.parser.ParserConfig 类。覆写了其两个核心方法。
方法一:
createFieldDeserializer(ParserConfig mapping, JavaBeanInfo beanInfo, FieldInfo fieldInfo) 创建一个属性反序列化处理类
该方法的修改,是将源码中的 ArrayListTypeFieldDeserializer 替换成 我们自定义的 CustomizeArrayListTypeFieldDeserializer 处理器。
将源码中的 DefaultFieldDeserializer 替换成 我们自定义的 CustomizeDefaultFieldDeserializer 处理器
方法二:
createJavaBeanDeserializer(Class<?> clazz, Type type) 创建一个 JavaBean 反序列化处理器
新增判断逻辑,如果要反序列化的类上存在 @JsonDeserializer 标识注解,返回包含自定义配置类的 JavaBeanDeserializer。
import com.alibaba.fastjson.annotation.JSONField;
import com.alibaba.fastjson.parser.ParserConfig;
import com.alibaba.fastjson.util.FieldInfo;
import com.alibaba.fastjson.util.JavaBeanInfo; import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
/**
* @创建人:Raiden
* @Descriotion:
* @Date:Created in 21:52 2020/4/17
* @Modified By: 自定义fastjson 解析配置类 这个类是核心
*/
public class CustomizeParserConfig extends ParserConfig { /**
* 值修改器数组 可以将类修改器放入其中使用
*/
private DeserializerValueMutator[] valueMutators; public CustomizeParserConfig(){
} /**
* 有参构造方法 可以通过该方法 将类修改器放入其中
* @param valueMutators
*/
public CustomizeParserConfig(DeserializerValueMutator... valueMutators){
super();
this.valueMutators = valueMutators;
} /**
* 创建一个属性反序列化处理类
* @param mapping
* @param beanInfo
* @param fieldInfo
* @return
*/
@Override
public FieldDeserializer createFieldDeserializer(ParserConfig mapping, //
JavaBeanInfo beanInfo, //
FieldInfo fieldInfo) {
//获取要反序列化的model 的class
Class<?> clazz = beanInfo.clazz;
//获取要反序列化属性的 class
Class<?> fieldClass = fieldInfo.fieldClass; Class<?> deserializeUsing = null;
JSONField annotation = fieldInfo.getAnnotation();
if (annotation != null) {
deserializeUsing = annotation.deserializeUsing();
if (deserializeUsing == Void.class) {
deserializeUsing = null;
}
} if (deserializeUsing == null && (fieldClass == List.class || fieldClass == ArrayList.class)) {
//将源码中的 ArrayListTypeFieldDeserializer 替换成 我们自定义的 CustomizeArrayListTypeFieldDeserializer 处理器
return new CustomizeArrayListTypeFieldDeserializer(clazz, fieldInfo, valueMutators);
}
//将源码中的 DefaultFieldDeserializer 替换成 我们自定义的 CustomizeDefaultFieldDeserializer 处理器
return new CustomizeDefaultFieldDeserializer(mapping, clazz, fieldInfo, valueMutators);
} /**
* 创建一个 javaBean 反序列化处理器
* @param clazz
* @param type
* @return
*/
@Override
public ObjectDeserializer createJavaBeanDeserializer(Class<?> clazz, Type type) {
//获取要反序列化类上的标识注解
JsonDeserializer jsonDeserializer = clazz.getAnnotation(JsonDeserializer.class);
//如果不存在就走原逻辑
if (jsonDeserializer != null){
//获取注解中的反序列化值处理器
Class<? extends DeserializerValueMutator>[] classes = jsonDeserializer.valueMutators();
if (classes != null && classes.length > 0){
DeserializerValueMutator[] mutators = new DeserializerValueMutator[classes.length];
int size = 0;
for (Class<? extends DeserializerValueMutator> c : classes) {
try {
DeserializerValueMutator mutator = c.newInstance();
mutators[size] = mutator;
size++;
} catch (Exception e) {
//如果创建失败了就忽略掉这次错误
}
}
if (size > 0){
//判断原来是否有值 如果有 就合并成一组
if (valueMutators != null){
DeserializerValueMutator[] newValueMutators = new DeserializerValueMutator[size + valueMutators.length];
System.arraycopy(valueMutators, 0, newValueMutators, 0, valueMutators.length);
System.arraycopy(mutators, 0, newValueMutators, valueMutators.length, size);
this.valueMutators = newValueMutators;
}else {
this.valueMutators = new DeserializerValueMutator[size];
System.arraycopy(mutators, 0, valueMutators, 0, size);
}
}
}
if (valueMutators != null){
return new JavaBeanDeserializer(this, clazz);
}
}
return super.createJavaBeanDeserializer(clazz, type);
}
}
CustomizeDefaultFieldDeserializer 类继承了 DefaultFieldDeserializer 类在构造方法中新增了参数 valueMutators(值修改器数组)
并在 public void setValue(Object object, Object value) 方法中新增了逻辑如果值修改器数组中存在值修改器,就遍历所有的修改器,
依次调用修改器的 process方法修改值。
import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.parser.ParserConfig;
import com.alibaba.fastjson.util.FieldInfo; import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong; /**
* @创建人:Raiden
* @Descriotion:
* @Date:Created in 0:13 2020/4/18
* @Modified By: 替代fastjson中 对象反序列化处理类
*/
public class CustomizeDefaultFieldDeserializer extends DefaultFieldDeserializer { private DeserializerValueMutator[] valueMutators; public CustomizeDefaultFieldDeserializer(ParserConfig config, Class<?> clazz, FieldInfo fieldInfo,DeserializerValueMutator[] valueMutators) {
super(config, clazz, fieldInfo);
this.valueMutators = valueMutators;
} public void setValue(Object object, Object value) {
if (value == null //
&& fieldInfo.fieldClass.isPrimitive()) {
return;
} else if (fieldInfo.fieldClass == String.class
&& fieldInfo.format != null
&& fieldInfo.format.equals("trim")){
value = ((String) value).trim();
}
try {
/**
* 如果值修改器数组中存在值修改器实例,就遍历该数组,依次调用所有的修改器的 process方法
*/
if (valueMutators != null && valueMutators.length > 0){
for (DeserializerValueMutator mutator : valueMutators){
value = mutator.process(object,fieldInfo.field.getAnnotations(), fieldInfo.name, value);
}
}
Method method = fieldInfo.method;
if (method != null) {
if (fieldInfo.getOnly) {
if (fieldInfo.fieldClass == AtomicInteger.class) {
AtomicInteger atomic = (AtomicInteger) method.invoke(object);
if (atomic != null) {
atomic.set(((AtomicInteger) value).get());
}
} else if (fieldInfo.fieldClass == AtomicLong.class) {
AtomicLong atomic = (AtomicLong) method.invoke(object);
if (atomic != null) {
atomic.set(((AtomicLong) value).get());
}
} else if (fieldInfo.fieldClass == AtomicBoolean.class) {
AtomicBoolean atomic = (AtomicBoolean) method.invoke(object);
if (atomic != null) {
atomic.set(((AtomicBoolean) value).get());
}
} else if (Map.class.isAssignableFrom(method.getReturnType())) {
Map map = (Map) method.invoke(object);
if (map != null) {
if (map == Collections.emptyMap()
|| map.getClass().getName().startsWith("java.util.Collections$Unmodifiable")) {
// skip
return;
} map.putAll((Map) value);
}
} else {
Collection collection = (Collection) method.invoke(object);
if (collection != null && value != null) {
if (collection == Collections.emptySet()
|| collection == Collections.emptyList()
|| collection.getClass().getName().startsWith("java.util.Collections$Unmodifiable")) {
// skip
return;
} collection.clear();
collection.addAll((Collection) value);
}
}
} else {
method.invoke(object, value);
}
} else {
final Field field = fieldInfo.field; if (fieldInfo.getOnly) {
if (fieldInfo.fieldClass == AtomicInteger.class) {
AtomicInteger atomic = (AtomicInteger) field.get(object);
if (atomic != null) {
atomic.set(((AtomicInteger) value).get());
}
} else if (fieldInfo.fieldClass == AtomicLong.class) {
AtomicLong atomic = (AtomicLong) field.get(object);
if (atomic != null) {
atomic.set(((AtomicLong) value).get());
}
} else if (fieldInfo.fieldClass == AtomicBoolean.class) {
AtomicBoolean atomic = (AtomicBoolean) field.get(object);
if (atomic != null) {
atomic.set(((AtomicBoolean) value).get());
}
} else if (Map.class.isAssignableFrom(fieldInfo.fieldClass)) {
Map map = (Map) field.get(object);
if (map != null) {
if (map == Collections.emptyMap()
|| map.getClass().getName().startsWith("java.util.Collections$Unmodifiable")) {
// skip
return;
}
map.putAll((Map) value);
}
} else {
Collection collection = (Collection) field.get(object);
if (collection != null && value != null) {
if (collection == Collections.emptySet()
|| collection == Collections.emptyList()
|| collection.getClass().getName().startsWith("java.util.Collections$Unmodifiable")) {
// skip
return;
} collection.clear();
collection.addAll((Collection) value);
}
}
} else {
if (field != null) {
field.set(object, value);
}
}
}
} catch (Exception e) {
throw new JSONException("set property error, " + clazz.getName() + "#" + fieldInfo.name, e);
}
}
}
类CustomizeArrayListTypeFieldDeserializer 和 类CustomizeDefaultFieldDeserializer 改动类似。
import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.parser.ParserConfig;
import com.alibaba.fastjson.util.FieldInfo; import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong; /**
* @创建人:Raiden
* @Descriotion:
* @Date:Created in 0:13 2020/4/18
* @Modified By: 替代fastjson中 对象反序列化处理类
*/
public class CustomizeDefaultFieldDeserializer extends DefaultFieldDeserializer { private DeserializerValueMutator[] valueMutators; public CustomizeDefaultFieldDeserializer(ParserConfig config, Class<?> clazz, FieldInfo fieldInfo,DeserializerValueMutator[] valueMutators) {
super(config, clazz, fieldInfo);
this.valueMutators = valueMutators;
} public void setValue(Object object, Object value) {
if (value == null //
&& fieldInfo.fieldClass.isPrimitive()) {
return;
} else if (fieldInfo.fieldClass == String.class
&& fieldInfo.format != null
&& fieldInfo.format.equals("trim")){
value = ((String) value).trim();
}
try {
/**
* 如果值修改器数组中存在值修改器实例,就遍历该数组,依次调用所有的修改器的 process方法
*/
if (valueMutators != null && valueMutators.length > 0){
for (DeserializerValueMutator mutator : valueMutators){
value = mutator.process(object,fieldInfo.field.getAnnotations(), fieldInfo.name, value);
}
}
Method method = fieldInfo.method;
if (method != null) {
if (fieldInfo.getOnly) {
if (fieldInfo.fieldClass == AtomicInteger.class) {
AtomicInteger atomic = (AtomicInteger) method.invoke(object);
if (atomic != null) {
atomic.set(((AtomicInteger) value).get());
}
} else if (fieldInfo.fieldClass == AtomicLong.class) {
AtomicLong atomic = (AtomicLong) method.invoke(object);
if (atomic != null) {
atomic.set(((AtomicLong) value).get());
}
} else if (fieldInfo.fieldClass == AtomicBoolean.class) {
AtomicBoolean atomic = (AtomicBoolean) method.invoke(object);
if (atomic != null) {
atomic.set(((AtomicBoolean) value).get());
}
} else if (Map.class.isAssignableFrom(method.getReturnType())) {
Map map = (Map) method.invoke(object);
if (map != null) {
if (map == Collections.emptyMap()
|| map.getClass().getName().startsWith("java.util.Collections$Unmodifiable")) {
// skip
return;
} map.putAll((Map) value);
}
} else {
Collection collection = (Collection) method.invoke(object);
if (collection != null && value != null) {
if (collection == Collections.emptySet()
|| collection == Collections.emptyList()
|| collection.getClass().getName().startsWith("java.util.Collections$Unmodifiable")) {
// skip
return;
} collection.clear();
collection.addAll((Collection) value);
}
}
} else {
method.invoke(object, value);
}
} else {
final Field field = fieldInfo.field; if (fieldInfo.getOnly) {
if (fieldInfo.fieldClass == AtomicInteger.class) {
AtomicInteger atomic = (AtomicInteger) field.get(object);
if (atomic != null) {
atomic.set(((AtomicInteger) value).get());
}
} else if (fieldInfo.fieldClass == AtomicLong.class) {
AtomicLong atomic = (AtomicLong) field.get(object);
if (atomic != null) {
atomic.set(((AtomicLong) value).get());
}
} else if (fieldInfo.fieldClass == AtomicBoolean.class) {
AtomicBoolean atomic = (AtomicBoolean) field.get(object);
if (atomic != null) {
atomic.set(((AtomicBoolean) value).get());
}
} else if (Map.class.isAssignableFrom(fieldInfo.fieldClass)) {
Map map = (Map) field.get(object);
if (map != null) {
if (map == Collections.emptyMap()
|| map.getClass().getName().startsWith("java.util.Collections$Unmodifiable")) {
// skip
return;
}
map.putAll((Map) value);
}
} else {
Collection collection = (Collection) field.get(object);
if (collection != null && value != null) {
if (collection == Collections.emptySet()
|| collection == Collections.emptyList()
|| collection.getClass().getName().startsWith("java.util.Collections$Unmodifiable")) {
// skip
return;
} collection.clear();
collection.addAll((Collection) value);
}
}
} else {
if (field != null) {
field.set(object, value);
}
}
}
} catch (Exception e) {
throw new JSONException("set property error, " + clazz.getName() + "#" + fieldInfo.name, e);
}
}
}
下面是值修改器接口定义:
import java.lang.annotation.Annotation; /**
* @创建人:Raiden
* @Descriotion:
* @Date:Created in 22:01 2020/5/1
* @Modified By: 反序列化值修改器接口
*/
public interface DeserializerValueMutator { Object process(Object object, Annotation[] annotations, String name, Object value);
}
反序列化标识注解,只有用这个注解注释的类才会执行拓展的方法。
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; /**
* @创建人:Raiden
* @Descriotion:
* @Date:Created in 22:25 2020/4/17
* @Modified By: 反序列化值修改标识注解
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE })
public @interface JsonDeserializer {
/**
* 注意这里只能放无参构造函数的修改器 否则会创建失败
* @return
*/
Class<? extends DeserializerValueMutator>[] valueMutators() default {};
}
强化的JSON序列化工具类:
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.parser.Feature; import java.lang.reflect.Type; /**
* @创建人:Raiden
* @Descriotion:
* @Date:Created in 22:12 2020/5/1
* @Modified By: 反序列化工具类
*/
public final class CustomizeJSON { public static <T> T parseObject(String input,Type clazz,DeserializerValueMutator... valueMutators) {
return JSON.parseObject(input, clazz, new CustomizeParserConfig(valueMutators));
} public static <T> T parseObject(String json, Type type,DeserializerValueMutator[] valueMutators, Feature... features) {
return JSON.parseObject(json, type, new CustomizeParserConfig(valueMutators), features);
} public static <T> T parseObject(String json, Type type,Feature... features) {
return JSON.parseObject(json, type, new CustomizeParserConfig(), features);
} public static <T> T parseObject(String json, Type type) {
return JSON.parseObject(json, type, new CustomizeParserConfig());
}
}
以上代码都可以在我的git中下载:https://github.com/RaidenXin/fastjson-deserializer.git
创作不易,如果转载请注明出处,小编在此感谢各位看官。
如果觉得有用,请看官们点个赞,谢谢。
如果有想学Redis的可以关注我的Redis文章系列:
小白也能看懂的REDIS教学基础篇——REDIS基础数据结构
小白也能看懂的REDIS教学基础篇——朋友面试被SKIPLIST跳跃表拦住了
记录一次源码扩展案列——FastJson自定义反序列化ValueMutator的更多相关文章
- storm源码之巧用java反射反序列化clojure的defrecord获取属性值
[原创]storm源码之巧用java反射反序列化clojure的defrecord获取属性值 [原创]storm源码之巧用java反射反序列化clojure的defrecord获取属性值 storm源 ...
- springboot aop 自定义注解方式实现一套完善的日志记录(完整源码)
https://www.cnblogs.com/wenjunwei/p/9639909.html https://blog.csdn.net/tyrant_800/article/details/78 ...
- Linux下利用phpize安装memcashe的php源码扩展包
phpize是php的一种构建工具,为PHP扩展准备构建环境,通过phpize可以编译php的扩展源码文件为php扩展模块. 一.安装 phpize工具可以通过安装php-dev包自动集成安装.安装完 ...
- 记录编译JDK11源码时遇到的两个问题
执行make all报错信息: 错误一 /src/hotspot/share/runtime/arguments.cpp:1461:35: error: result of comparison ag ...
- 四:WEB源码扩展
前言:WEB源码在安全测试中是非常重要的信息来源,可以用来进行代码审计漏洞也可以用来做信息突破口,其中WEB源码有很多技术需要简明分析,获取某ASP源码后就可以采用默认数据库下载为突破,获取某其他脚本 ...
- [Abp vNext 源码分析] - 11. 用户的自定义参数与配置
一.简要说明 文章信息: 基于的 ABP vNext 版本:1.0.0 创作日期:2019 年 10 月 23 日晚 更新日期:暂无 ABP vNext 针对用户可编辑的配置,提供了单独的 Volo. ...
- Spring源码阅读笔记05:自定义xml标签解析
在上篇文章中,提到了在Spring中存在默认标签与自定义标签两种,并且详细分析了默认标签的解析,本文就来分析自定义标签的解析,像Spring中的AOP就是通过自定义标签来进行配置的,这里也是为后面学习 ...
- HTML5游戏源码 飞翔的字母 可自定义内容
相信大家都玩过飞翔的小鸟吧,当然,可能已经有很多人因为这个游戏砸了不少手机.吼吼. 废话不多说,回到主题,源码如下. 博客园上传空间大小有限制,没法上传了,需要打包源码的朋友们请留言邮箱地址.当然还有 ...
- Dubbo源码-Dubbo是如何随心所欲自定义XML标签的
叨叨 今天考虑了很久要不要写这篇文章. 距离<Dubbo源码>系列的开篇到现在已经快两个月时间了.当时是想着工作上的RPC框架使用存在一些让人头疼的问题,就来看看Dubbo给出了一套什么样 ...
随机推荐
- 汽车芯片如何高效符合ISO 26262功能安全标准
汽车芯片和集成电路(IC)是高级驾驶员辅助系统(advanced driver assistance systems-ADAS)和联网自动驾驶汽车(connected autonomous veh ...
- 用Nginx将web请求引导到本机两个tomcat
如何在本机启动两个tomcat请参考:https://www.cnblogs.com/xiandedanteng/p/12100461.html 而Nginx这边,将\conf\nginx.conf ...
- String源码浅析
如果问你,开发过程中用的最多的类是哪个?你可能回答是HashMap,一个原因就是HashMap的使用量的确很多,还有就是HashMap的内容在面试中经常被问起. 但是在开发过程中使用最多的类其实并不是 ...
- django之admin配置
要在admin内显示的表,在admin中进行注册,然后在登录admin后台,才可以对表进行操作例如:from django.contrib import adminfrom app01 import ...
- SpringBoot中使用切面的每次传的参数,进行解析,验签,并返回解码后的参数
目的,在每次请求的时候,对每次传的参数,进行解析,验签,并返回解码后的参数, 以json传递: 例子背景: IOT平台提供对外可访问的接口, 需要对所有参数的传递做到 不泄露.认证的目的:所以需要在每 ...
- 记录openssl和openssh升级中遇到的问题以及解决方法
本文档讲述的升级操作是基于操作系统centos6.5,使用的openssl版本是openssl-1.0.2l.tar.gz,openssh版本是openssh-7.6p1.tar.gz. 1. 依赖检 ...
- Git+Gitlab+Ansible的roles实现一键部署Nginx静态网站(4)
前言 截止目前已经写了<Ansible基础认识及安装使用详解(一)–技术流ken>,<Ansible常用模块介绍及使用(二)–技术流ken><Ansible剧本介绍及使用 ...
- 简单说说Restful API
前言: 最近一段时间,一直在低头敲代码,开发平台对外交互的API接口,功能已经大体完成了,回过头来看看自己的接口设计文档,不胜感慨,想当初自己也是为"接口名称"想破了脑袋,各种百度 ...
- 面试可能遇到的关联式容器(map、set等)相关问题
>>>. map与set的区别是什么,各有哪些优势? map中存储的数据是以键值对(key - value)形式并且通过排序(比较key,默认以 '<' 方式排序)存在的( ...
- python3-day5
模块,用一砣代码实现了某个功能的代码集合. 类似于函数式编程和面向过程编程,函数式编程则完成一个功能,其他代码用来调用即可,提供了代码的重用性和代码间的耦合.而对于一个复杂的功能来,可能需要多个函数才 ...