> NULL_TYPE_HANDLER_MAP = Collections.emptyMap();
/**
* 默认的枚举类型转换器
*/
private Class defaultEnumTypeHandler = EnumTypeHandler.class;
仔细看前两个属性的定义,JDBC_TYPE_HANDLER_MAP
用于存放JdbcType
和TypeHandler
的对应关系。
TYPE_HANDLER_MAP
的key
值是一个java
类型,value
是Map>
集合。
这两个属性的定义很容易让人误认为 :TYPE_HANDLER_MAP
的value
存放是的指定java
类型对应的JDBC_TYPE_HANDLER_MAP
集合。
但是,事实上,在梳理源码后,我们会发现二者毫无关系 。
JDBC_TYPE_HANDLER_MAP
的作用是:维护一个JdbcType
和其默认 的TypeHandler
之间的对应关系。
TYPE_HANDLER_MAP
的作用是:维护java
类型和其所有可转换的JdbcType
的关系,并保留负责进行转换操作的TypeHandler
实例。
换句话,TYPE_HANDLER_MAP
集合中的value
虽然类型也是Map>
,但是他存储的JdbcType
和TypeHandler
的对应关系可能会因为所属的java
类型的不同而不同。
比如:
var TYPE_HANDLER_MAP={
'Integer':{
"JdbcType.INTEGER":"IntegerTypeHandler"
},
'Double':{
"JdbcType.INTEGER":"DoubleTypeHandler"
}
}
在上面这个通过JS
描述的伪对象TYPE_HANDLER_MAP
中,我们可以看到随着java
类型由Integer
变成Double
,JdbcType.INTEGER
对应的TypeHandler
实例也由IntegerTypeHandler
变成了DoubleTypeHandler
。
除了这个容易让人混淆的问题之外,还有一个问题困扰了我很久,按照前面的理解,一个jdbc
类型应该是可以对应多个TypeHandler
对象的,毕竟,一个jdbc
类型可能会转换成不同的JAVA
对象,可是按照JDBC_TYPE_HANDLER_MAP
的定义,一个jdbc
类型只能对应一个TypeHandler
,这是为什么呢?
这是因为JDBC_TYPE_HANDLER_MAP
负责存储的是JdbcType
和其默认 的TypeHandler
之间的对应关系,JDBC_TYPE_HANDLER_MAP
是TYPE_HANDLER_MAP
的一个补充,当TYPE_HANDLER_MAP
中无法获取TypeHandler
时,就会考虑根据jdbc
类型从JDBC_TYPE_HANDLER_MAP
中获取一个默认的TypeHandler
来完成类型转换的处理操作。
TypeHandlerRegistry
还有其他几个属性,被final
修饰的UNKNOWN_TYPE_HANDLER
属性是一个UnknownTypeHandler
类型的类型转换器。
UnknownTypeHandler
虽然听起来像是用于处理未知类型,但是实际上在他的实现中,我们会发现他更偏向于一个代理对象,他会在运行期间,动态的去选择一个有效的TypeHandler
实例来完成类型转换的工作。
类型为Map>
的NULL_TYPE_HANDLER_MAP
属性和JDBC_TYPE_HANDLER_MAP
也没有任何关系,他是一个标志性的对象,用来表示一个空的类型转换器映射关系。
类型为Map, TypeHandler>
的ALL_TYPE_HANDLERS_MAP
属性,他的key
是TypeHandler
实例的具体类型,他的value
则是TypeHandler
实例本身,他的作用是维护所有有效的TypeHandler
。
最后一个类型为Class
的defaultEnumTypeHandler
属性,则定义了默认的枚举类型转换器。
枚举类型转换器实际上是一个比较特殊的处理器,他有别于普通的处理器只用于处理特定的类,枚举类型转换器会处理任意继承了Enum
的类。
注册类型转换器功能的实现
TypeHandlerRegistry
的几个集合类型的属性已经为我们提供了保存类型转换器的功能 ,现在我们看一下TypeHandlerRegistry
如何实现注册 类型转换器的功能。
现在已经知道一个类型转换器核心的数据有:被处理的Java类型
,被处理的JDBC类型
以及类型转换器TypeHandler
本身这三个核心要素,同时Java类型
和JDBC类型
之间是一个多对多 的关系。
那么就注册功能的实现来讲,最好的场景就是我们能够直接拿到Java类型
和JDBC类型
以及相应的类型转换器TypeHandler
实例这三个参数。
如果不能,那就退而求其次,获取类型转换器TypeHandler
加上Java类型
与JDBC类型
中的一个。
如果还不行,只有类型转换器TypeHandler
也可以。
对于那些缺失的参数,我们的实现通常是想办法推导出它们,然后转为完美场景进行处理。
TypeHandlerRegistry
在注册类型转换器的功能实现方面,提供了较多的register
方法重载方法。
其中有一个方法签名为private void register(Type javaType, JdbcType jdbcType,TypeHandler handler)
的重载方法,用于处理三要素齐全的场景,完成了事实上的类型转换器的注册工作:
/**
* 注册类型转换器
*
* @param javaType java类型
* @param jdbcType jdbc类型
* @param handler 类型转换器
*/
private void register(Type javaType, JdbcType jdbcType, TypeHandler handler) {
if (javaType != null) {
// 获取该java类型对应的jdbc类型转换器的集合
Map> map = TYPE_HANDLER_MAP.get(javaType);
if (map == null || map == NULL_TYPE_HANDLER_MAP) {
map = new HashMap<>();
// 注册java类型和【jdbc和处理器的映射关系】的映射关系
TYPE_HANDLER_MAP.put(javaType, map);
}
map.put(jdbcType, handler);
}
// 注册处理器类型和实例的关系
ALL_TYPE_HANDLERS_MAP.put(handler.getClass(), handler);
}
这是register
重载方法中最核心的方法,多数 register
重载方法的调用,最终会落在该方法上来完成最终的处理操作。
他的实现比较简单,唯一值得注意的就是NULL_TYPE_HANDLER_MAP
作为标识符的作用就体现在这里。
还有一些register
重载方法的入参会缺失Java类型
与JDBC类型
中的一个,甚至是二者全部缺失。
我们前面说过,当我们缺少某一参数时,会尽可能的去推导出缺少属性的参数类型,然后转为完美场景进行处理。
推导Java
类型参数
在缺失java
类型参数的场景下,TypeHandlerRegistry
给出的解决方案是提供MappedTypes
注解和TypeReference
抽象父类。
MappedTypes
注解可以直接提供TypeHandler
对象可转换的java
类型集合:
/**
* 该注解用于给类型处理器指定可处理的JAVA类型
*
* @author Eduardo Macarron
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface MappedTypes {
/**
* 可转换的JAVA类型集合
*/
Class[] value();
}
TypeReference
抽象父类则可以获取其实现类的泛型参数定义。
具体的解析方法可以参考register(TypeHandler typeHandler)
方法:
public void register(TypeHandler typeHandler) {
boolean mappedTypeFound = false;
// 获取MappedTypes注解
MappedTypes mappedTypes = typeHandler.getClass().getAnnotation(MappedTypes.class);
if (mappedTypes != null) {
for (Class handledType : mappedTypes.value()) {
// 根据注解,注册类型转换器
register(handledType, typeHandler);
mappedTypeFound = true;
}
}
// 解析泛型
// @since 3.1.0 - try to auto-discover the mapped type
if (!mappedTypeFound && typeHandler instanceof TypeReference) {
try {
TypeReference typeReference = (TypeReference) typeHandler;
register(typeReference.getRawType(), typeHandler);
mappedTypeFound = true;
} catch (Throwable t) {
// maybe users define the TypeReference with a different type and are not assignable, so just ignore it
}
}
// 特殊的null类型
if (!mappedTypeFound) {
register((Class) null, typeHandler);
}
}
优先解析MappedTypes
注解中指定的类型,其次是根据TypeReference
获取泛型类型,如果还没能获取java
类型,那就使用特殊的类型null
。
推导Jdbc
类型参数
推导jdbc
类型参数,TypeHandlerRegistry
给出的解决方案是提供MappedJdbcTypes
注解,和MappedTypes
相似。
MappedJdbcTypes
注解的作用是标注出指定TypeHandler
可转换的jdbc
类型集合:
/**
* 给TypeHandler指定处理的JdbcType
* @author Eduardo Macarron
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface MappedJdbcTypes {
// 可处理的jdbc类型集合
JdbcType[] value();
// 是否额外注册JDBC类型为null的处理器
boolean includeNullJdbcType() default false;
}
MappedJdbcTypes
除了可以指定jdbc
类型集合之外,可有一个includeNullJdbcType()
方法,用于指定是否额外注册Jdbc
类型为null
的处理器。
负责推导jdbc
类型参数的方法是private void register(Type javaType, TypeHandler typeHandler)
:
/**
* 注册java类型和类型转换出处理器的关系
*
* @param javaType java类型
* @param typeHandler 类型转换处理器实例
* @param java类型
*/
private void register(Type javaType, TypeHandler typeHandler) {
// 寻找mappedJdbcTypes注解,mappedJdbcTypes用于给TypeHandler指定处理的JdbcType
MappedJdbcTypes mappedJdbcTypes = typeHandler.getClass().getAnnotation(MappedJdbcTypes.class);
if (mappedJdbcTypes != null) {
for (JdbcType handledJdbcType : mappedJdbcTypes.value()) {
// 注册java类型处理和jdbc类型以及类型转换处理器的关系
register(javaType, handledJdbcType, typeHandler);
}
if (mappedJdbcTypes.includeNullJdbcType()) {
// 注册JDBC类型为null的处理器
register(javaType, null, typeHandler);
}
} else {
// 注册JDBC类型为null的处理器
register(javaType, null, typeHandler);
}
}
上面的两个方法的实现上,分别
上面提到的三个register()
方法,是TypeHandlerRegistry
中比较核心的三个注册方法,这三个方法相互配合使用基本可以完成绝大多数注册场景。
还有一些其他的register()
重载方法,这些重载方法中有一部分用于处理java
类型的变种表现:
比如,将String
类型描述的Java
类型转换为实际的Java
类型:
/**
* 注册指定java类型的指定类型转换器
*
* @param javaTypeClassName java类型名称
* @param typeHandlerClassName 类型转换处理器名称
*/
public void register(String javaTypeClassName, String typeHandlerClassName) throws ClassNotFoundException {
register(Resources.classForName(javaTypeClassName), Resources.classForName(typeHandlerClassName));
}
比如,获取TypeReference
对应的泛型类型,然后进行注册:
/**
* 根据泛型注册类型转换处理器
*
* @param javaTypeReference java泛型
* @param handler 处理器
* @param 泛型
*/
public void register(TypeReference javaTypeReference, TypeHandler handler) {
register(javaTypeReference.getRawType(), handler);
}
还有一部分register()
方法用于处理特殊的场景,比如:
/**
* 注册JDBC类型转换器
*
* @param jdbcType jdbc类型
* @param handler 处理器
*/
public void register(JdbcType jdbcType, TypeHandler handler) {
// 注册jdbc类型转换器
JDBC_TYPE_HANDLER_MAP.put(jdbcType, handler);
}
这个方法注册的是指定的Jdbc
类型与其对应的默认转换器,和前面提到那些register()
方法在实际意义上完全不同。
还有一个register()
方法用于批量注册类型转换器:
// 注册指定包下所有的java类
public void register(String packageName) {
ResolverUtil> resolverUtil = new ResolverUtil<>();
// 返回当前已经找到的所有TypeHandler的子类
resolverUtil.find(new ResolverUtil.IsA(TypeHandler.class), packageName);
Set>> handlerSet = resolverUtil.getClasses();
for (Class type : handlerSet) {
//Ignore inner classes and interfaces (including package-info.java) and abstract classes
if (!type.isAnonymousClass() && !type.isInterface() && !Modifier.isAbstract(type.getModifiers())) {
// 忽略匿名类、接口以及抽象类
// 注册类型转换处理器
register(type);
}
}
}
在这个方法中,他通过ResolverUtils
的find()
方法来获取初步符合预期的类集合,之后排除掉匿名类、成员类和接口,对剩下的类执行别名注册的操作。
有关于更多ResolverUtil
的信息,在解析TypeAliases
元素时,已经给出。
获取类型转换器功能的实现
在实现上TypeHandlerRegistry
获取类型转换器的方法大致可以分为两类,其中一类是用于判断指定的类型转换器是否存在的hasTypeHandler()
方法,一类是实际获取类型转换器对象的getTypeHandler()
方法。
这两类方法的实现逻辑大致是一致的,hasTypeHandler()
方法仅仅是对getTypeHandler()
方法的返回结果做了一层非空判断,并包装成Boolean
值而已。
getTypeHandler()
方法的核心重载实现是:
/**
* 获取指定类型的处理器
*
* @param type java类型
* @param jdbcType jdbc类型
* @param 处理器类型
*/
@SuppressWarnings("unchecked")
private TypeHandler getTypeHandler(Type type, JdbcType jdbcType) {
if (ParamMap.class.equals(type)) {
return null;
}
/*
* 获取所有指定类型的java处理器
*/
Map> jdbcHandlerMap = getJdbcHandlerMap(type);
TypeHandler handler = null;
if (jdbcHandlerMap != null) {
// 获取对应的jdbc处理器
handler = jdbcHandlerMap.get(jdbcType);
if (handler == null) {
handler = jdbcHandlerMap.get(null);
}
if (handler == null) {
// 选择一个适合的惟一的处理器
// #591
handler = pickSoleHandler(jdbcHandlerMap);
}
}
// 返回处理器
// type drives generics here
return (TypeHandler) handler;
}
可以看到,方法实现比较简单,先获取指定java
类型对应的已注册的jdbc
类型及其转换处理器,之后根据jdbc
类型参数获取转换器, 如果没有指定jdbc
类型,则调用pickSoleHandler(jdbcHandlerMap)
方法,尝试获取一个有效转换器:
/**
* 从一组类型转换处理器中选择唯一的一个转换器,如果超过一个类型转换处理器,返回null。
*
* @param jdbcHandlerMap jdbc类型对应的类型转换处理器集合
*/
private TypeHandler pickSoleHandler(Map> jdbcHandlerMap) {
TypeHandler soleHandler = null;
for (TypeHandler handler : jdbcHandlerMap.values()) {
if (soleHandler == null) {
soleHandler = handler;
} else if (!handler.getClass().equals(soleHandler.getClass())) {
// More than one type handlers registered.
return null;
}
}
return soleHandler;
}
pickSoleHandler(jdbcHandlerMap)
方法对于有效转换器的定义比较简单,那就是返回java
类型对应的唯一的 类型转换器,这个唯一的类型转换器可以当做是默认的类型转换器来使用。
负责获取指定java
类型对应的已注册jdbc
类型及其转换处理器的方法getJdbcHandlerMap()
在实现上兼容了枚举和子类的处理操作。
// 获取指定java类型对应所有类型转换处理器
private Map> getJdbcHandlerMap(Type type) {
// 获取当前java类型对应的类型转换器集合
Map> jdbcHandlerMap = TYPE_HANDLER_MAP.get(type);
if (NULL_TYPE_HANDLER_MAP.equals(jdbcHandlerMap)) {
return null;
}
if (jdbcHandlerMap == null && type instanceof Class) {
Class clazz = (Class) type;
if (clazz.isEnum()) {
// 根据枚举查找类型转换处理器
jdbcHandlerMap = getJdbcHandlerMapForEnumInterfaces(clazz, clazz);
if (jdbcHandlerMap == null) {
// 注册类型转换处理器
register(clazz, getInstance(clazz, defaultEnumTypeHandler));
// 返回类型转换处理器
return TYPE_HANDLER_MAP.get(clazz);
}
} else {
// 根据父类查找类型转换处理器
jdbcHandlerMap = getJdbcHandlerMapForSuperclass(clazz);
}
}
// 注册类型转换处理器
TYPE_HANDLER_MAP.put(type, jdbcHandlerMap == null ? NULL_TYPE_HANDLER_MAP : jdbcHandlerMap);
return jdbcHandlerMap;
}
枚举兼容
在处理枚举 类型时,如果该枚举 没有定义相关的类型转换器,将会递归调用getJdbcHandlerMapForEnumInterfaces()
方法,尝试从实现的接口定义中获取类型转换器。
如果其接口也没有对应的类型转换器,那么将会使用TypeHandlerRegistry
的defaultEnumTypeHandler
属性对应的类型转换器作为当前枚举的类型处理器。
/**
* 根据枚举接口获取类型转换器
*
* @param clazz java类型
* @param enumClazz 枚举类型
* @return 类型转换处理器
*/
private Map> getJdbcHandlerMapForEnumInterfaces(Class clazz, Class enumClazz) {
for (Class iface : clazz.getInterfaces()) {
// 从指定java类的接口上找类型转换处理器
Map> jdbcHandlerMap = TYPE_HANDLER_MAP.get(iface);
if (jdbcHandlerMap == null) {
// 没有对应的类型转换器,递归往上找
jdbcHandlerMap = getJdbcHandlerMapForEnumInterfaces(iface, enumClazz);
}
if (jdbcHandlerMap != null) {
// 如果找到了类型转换器
// Found a type handler regsiterd to a super interface
HashMap> newMap = new HashMap<>();
for (Entry> entry : jdbcHandlerMap.entrySet()) {
// Create a type handler instance with enum type as a constructor arg
// 创建一个对应该类的类型转换器
newMap.put(entry.getKey(), getInstance(enumClazz, entry.getValue().getClass()));
}
return newMap;
}
}
return null;
}
子类兼容
在处理普通类型时,如果该类型没有定义相关的类型转换器,将会递归调用getJdbcHandlerMapForSuperclass()
方法,尝试从继承的父类定义中获取类型转换器。
private Map> getJdbcHandlerMapForSuperclass(Class clazz) {
Class superclass = clazz.getSuperclass();
if (superclass == null || Object.class.equals(superclass)) {
return null;
}
Map> jdbcHandlerMap = TYPE_HANDLER_MAP.get(superclass);
if (jdbcHandlerMap != null) {
return jdbcHandlerMap;
} else {
return getJdbcHandlerMapForSuperclass(superclass);
}
}
无论是针对普通类还是枚举,在查找到新的 类型转换器关系之后,都会重新注册到TypeHandlerRegistry
中。
我思考了很久,为什么在做子类兼容时,只递归查找父类对应的类型转换器集合,而不是连父接口对应的类型转换器一并查找?
先说结论:因为没必要。
首先,我们要明确一点:接口,是抽象方法的集合,方法定义的是一个对象的行为,所以接口定义的是一类对象的行为,而不是特性。
被类型转换器处理的java
类型通常需要具有一定程度上的一致性和可预见性,比如,给定Jdbc
数值A
,可以获取java
对象a
,那么理论上可预见的是:通过java
对象a
可以获得Jdbc
数值A
。
这种特性意味着,被类型转换器处理的java
类型通常具有简单性,不会是一个复杂的业务对象,这时候强调的往往是该对象的某一特性,而不是行为,这时候,这种对象通常会被直接定义为类而不是接口。
那么枚举对象为什么适配的是接口而不是类呢?
枚举对象也具有简单性,但是枚举默认继承了Enum
父类,所以只能实现接口,没有办法直接定义属性,所以退而求其次,通过方法来间接的限制属性。
getTypeHandler()
方法还有一些其他重载实现,逻辑大致与register()
方法重载实现一致,这里就不做讨论了。
到这里,TypeHandlerRegistry
就完成了保存所有类型转换器 ,以及相应的注册 和获取 类型转换器的功能的实现。
其他
TypeHandlerRegistry
中还有一些其他方法定义,比如defaultEnumTypeHandler
属性的getter/setter
方法和UNKNOWN_TYPE_HANDLER
属性的getter
方法,以及通过反射获取TypeHandler
对象实例的getInstance
方法。
这些方法的实现比较简单,这里就不在赘述了。
解析typeHandlers
元素
现在我们回到typeHandlers
元素的解析工作中。
在Mybatis中关于typeHandlers
的DTD
是如此定义的:
在typeHandlers
下面可以出现零个或多个typeHandler
或者package
标签。
typeHandler
元素用于注册单个TypeHandler
实例,它有三个属性javaType
,jdbcType
以及handler
,其中javaType
和jdbcType
是可选的,他们分别表示java类型和jdbc类型,handler
属性是必填的,他表示类型转换器的类型,这三个属性都可以使用类型别名。
package
元素用于批量注册TypeHandler
实例,它只有一个必填的name
属性,他表示用户需要注册TypeHandler
的基础包名,Mybatis
将会递归处理该基础包及其子包下所有可用的TypeHandler
实例。
调用解析的入口(XmlConfigBuilder
):
private void parseConfiguration(XNode root) {
// ...
// 注册类型转换器
typeHandlerElement(root.evalNode("typeHandlers"));
// ...
}
解析并注册TypeHandler
实例:
// 解析typeHandlers元素
private void typeHandlerElement(XNode parent) {
if (parent != null) {
for (XNode child : parent.getChildren()) {
if ("package".equals(child.getName())) {
// 整包注册
String typeHandlerPackage = child.getStringAttribute("name");
typeHandlerRegistry.register(typeHandlerPackage);
} else {
// 单个注册
// 获取java类型的名称
String javaTypeName = child.getStringAttribute("javaType");
// 获取jdbc类型的名称
String jdbcTypeName = child.getStringAttribute("jdbcType");
// 获取类型转换处理器的名称
String handlerTypeName = child.getStringAttribute("handler");
// 解析出java类型
Class javaTypeClass = resolveClass(javaTypeName);
// 解析jdbc类型
JdbcType jdbcType = resolveJdbcType(jdbcTypeName);
// 解析出类型转换处理器的类型
Class typeHandlerClass = resolveClass(handlerTypeName);
// 注册类型处理器
if (javaTypeClass != null) {
if (jdbcType == null) {
typeHandlerRegistry.register(javaTypeClass, typeHandlerClass);
} else {
typeHandlerRegistry.register(javaTypeClass, jdbcType, typeHandlerClass);
}
} else {
typeHandlerRegistry.register(typeHandlerClass);
}
}
}
}
}
根据子元素的不同,TypeHandler
实例的解析注册也分为两种:
一类是解析typeHandler
元素,尝试获取注册TypeHandler
实例的三要素完成注册工作。
一类是解析package
元素,获取用于批量注册的包名,调用TypeHandlerRegistry
的register()
方法完成整包批量注册。
关于具体注册方法的实现,前面已经有了详细的阐述。
至此,整个typeHandlers
元素的解析也已经完成,Mybatis
的基础准备工作也准备的差不多了。
接下来就是解析Mybatis
的Mapper
配置文件。
关注我,一起学习更多知识
你可能感兴趣的:(Mybatis源码之美:2.14.解析Mybatis的typeHandlers元素,配置Mybatis的类型转换器)
十大软件供应链安全AI代表厂商,一文快速了解!
数字供应链安全产品选型
安全
中国网络安全行业专业媒体安全牛正式发布《软件供应链安全能力构建指南(2024版)》报告,悬镜安全(官网访问地址:悬镜安全-DevSecOps数字供应链安全开拓者)作为DevSecOps软件供应链安全领域领导者,牵头并主导参与了多项国家软件供应链安全行业标准的制定,并打造了全球首个数字供应链开源社区OpenSCA,发布国内首个软件物料清单(SBOM)格式“数字供应链数据交换格式-DSDX(Digit
Android 网络框架之okhttp源码解析
码中之牛
移动开发 Android 开源框架 android kotlin 开发语言 移动开发 网络框架
okhttp使用okhttp则分为Request请求与response响应。request请求体:每一个HTTP请求中都应该包含一个URL,一个GET或POST方法以及Header或其他参数,当然还可以含特定内容类型的数据流。response响应码:响应则包含一个回复代码(200代表成功,404代表未找到),Header和定制可选的body。封装的okhttp库与okhttp使用:blog.csd
stm32 can 简单分析
风中微笑的代码狗
stm32
1.发送过程寄存器总结TXRQ=1发送can报文,由软件对其置’1’,来请求发送邮箱的数据。当数据发送完成,邮箱为空时,硬件对其清’0’。CAN_MCR寄存器的TXFP位置’1’,can发送为fifo模式,先发送的先发出RQCPTXOK=1发送成功仲裁失败ALST置一发生错误TERR置一TME=1发送邮箱为空ABRQ=1中止如果CAN_IER寄存器TMEIE=1,当RQCPx位被置’1’时,产生中
GitLab配置ssh key
西北**孤狼
SHH git ssh 运维
简介:一、背景当前很多公司都选择git作为代码版本控制工具,然后自己公司搭建私有的gitlab来管理代码,我们在clone代码的时候可以选择http协议,当然我们亦可以选择ssh协议来拉取代码。但是网上很少找到如何用git客户端生成sshkey,然后配置在gitlab,我当时在做的时候苦于摸索,后来终于找到了解决方案,那么本文,我们就来聊一聊如何本地git客户端生成sshkey,然后配置在gitl
AI系统架构
flying robot
AI 系统架构
在AI系统架构中,通常可以分为基础设施层、模型层和应用层。它们分别对应不同的技术和应用场景,具体如下:1.基础设施层(InfrastructureLayer)这是AI系统的底层支持,主要涉及计算资源、存储、网络等基础设施。关键组成计算硬件GPU(如NVIDIAA100、H100)TPU(GoogleTensorProcessingUnit)NPU(如华为昇腾、寒武纪等)CPU(用于轻量级推理任务)
GitLab配置添加SSH Key
小羊绒
配置ssh reactjs
工具gitbash1.配置姓名,邮箱配置姓名$gitconfig--globaluser.name"rongyang"配置邮箱$gitconfig--globaluser.email"rong.yang@foxmial.com"2.客户端配置生成SSH密钥对$ssh-keygen-trsa-C"rong.yang@woqutech.com"完成后在~/.ssh/会生成2个文件。id_rsa和id_
`http_port_t
宜昌李国勇
android 前端
`http_port_t`是SELinux(Security-EnhancedLinux)中的一种端口类型标签,用于标识哪些端口可以被HTTP和HTTPS服务使用。SELinux是一种强制访问控制(MAC)安全模块,它通过定义安全策略来限制进程对系统资源的访问,从而增强系统的安全性。###`http_port_t`的作用在SELinux中,每个网络端口都有一个类型标签,这些标签决定了哪些进程可以绑
C++的引用 ‘&’
三贝勒文子
C/C++ c++ c语言 软件工程 开发语言
引用这个操作在C语言中就已经存在了,它表示了一个取地址符,取地址符经常被用来在定义指针p的时候,在变量前面加上这个取地址符号,表示指针p指向了该变量的地址:int*p=NULL;inta=0;p=&a;又或者是在函数的参数传递时候,形参定义的是指针,实参数变量的取地址,通过指针传递的形式来进行数据的交换操作:voidTest_PointerTransport(int*p,int*q){inttem
SQL 拼接字符串 使用IN查询方法
MY-备忘
SQL SQL
CREATEFUNCTION[dbo].[F_SUBSTRINGINTARRAY](@STRVARCHAR(1000),--字符串队列格式为:1,2,3,4@CHARVARCHAR(10)--截取字符串的符号:,)RETURNS@RESULTTABLE(IDINT)ASBEGINDECLARE@INDEXINT--声明截取符号的位置DECLARE@ORDERIDINT--声明获取的INT编号--判
用友U9二次开发-问题记录
MY-备忘
U9 用友 C#
学习资料:链接:https://pan.baidu.com/s/13JbKSSRkSn2V6-dYX5zKFQ提取码:p9at页面&__dm=true客开插件&Admin=true开发者使用查看代码插件UI插件配置项1.关闭热插拔2.在configuration节点下加配置,多个在WebPartExtend节点下可以继续加ExtendedPart --对
[网络安全自学篇] 一.入门笔记之看雪Web安全学习及异或解密示例
鱼馬
网络 网络安全 web安全 笔记 测试工具 职场和发展
最近开始学习网络安全相关知识,接触了好多新术语,感觉自己要学习的东西太多,真是学无止境,也发现了好几个默默无闻写着博客、做着开源的大神。准备好好学习下新知识,并分享些博客与博友们一起进步,加油。非常基础的文章,大神请飘过,谢谢各位看官!文章目录一.工具&术语1.网安术语2.常用工具3.推荐文章二.常见攻击1.SQL注入2.XSS跨站3.越权漏洞4.CSRF跨站请求伪造5.支付漏洞三.音乐异或解密示
iOS开发 超详细Flutter开发环境搭建
weixin_40847622
flutter ios
1、安装Flutter此文章针对针对移动开发者,关于Flutter环境搭建,仅供参考,也可参考官网1.1、下载FlutterSDK进入Flutter官网此网站为中国网站,无需即可进入进入后,此处便为FlutterSDK下载地址了,根据自己的操作系统选择(本人为MacOS系统,下面以本人电脑为例操作)。
系统架构设计师-第6章 系统配置与性能评价
软考诸葛老师
系统架构设计师 系统架构 系统架构设计师 软考高级 软考
【本章学习建议】根据考试大纲,本章主要考查系统架构设计师单选题,预计考1分左右,对应第二版教材2.9节,内容较少,较为简单,容易拿分。6.1性能指标1.计算机的性能指标对计算机评价的主要性能指标有:时钟频率(主频);运算速度;运算精度;内存的存储容量;存储器的存取周期;数据处理速率(ProcessingDataRate,PDR);吞吐率;各种响应时间;各种利用率;RASIS特性(即:可靠性Reli
Laya前端开源框架深度解析与实践应用
徐子贡
本文还有配套的精品资源,点击获取简介:Laya前端开源框架是一个高效的跨平台JavaScript库,专注于2D/3D游戏及互动应用开发。它利用WebGL引擎提供原生级别的性能,同时兼容包括老旧IE在内的广泛浏览器环境。Laya框架具备强大的组件系统、资源管理、易用性,以及丰富的社区资源支持。实时编译和多平台发布能力让开发更加高效。通过LayaYKFramework-master项目,开发者可以深入
Laravel后台管理解决方案:admin-laravel实战
韦臻
本文还有配套的精品资源,点击获取简介:admin-laravel为Laravel框架提供了一个专门优化和封装的管理后台,支持认证授权、前端UI框架、表单构建、数据展示、API集成、错误日志处理、自定义命令、扩展性、安全防护等功能,旨在帮助开发者高效搭建后台管理系统。通过提供详细的文档和示例代码,它简化了安装、配置和操作流程,确保代码质量和可维护性。1.Laravel后台开发框架概述简介Larave
js 封装ajax方法吗,原生JS封装ajax方法
里小咸
js 封装ajax方法吗
jquery框架的ajax方法固然好用,但是假如某天我们的项目不能引入jquery或项目需求很简单,没有很多交互功能,只需要ajax,这时引入jquery库会造成资源浪费,也会显得页面臃肿。这时我们就需要用原生JS写一个ajax函数了。/*封装ajax函数*@param{string}opt.typehttp连接的方式,包括POST和GET两种方式*@param{string}opt.url发送请
【光流】——liteflownet论文与代码浅读
农夫山泉2号
光流 计算机视觉 深度学习 人工智能 光流 liteflownet
光流,liteflownetcode:mmflowCVPR20181.前言FlowNet2是最先进的光流估计卷积神经网络(CNN),需要超过160M的参数来实现精确的流量估计。在本文中,我们提出了一种替代网络,它在Sintel和KITTI基准测试上优于FlowNet2,同时在模型尺寸上要小30倍,在运行速度上要快1.36倍。这是通过深入研究当前框架中可能被遗漏的架构细节而实现的:(1)我们通过轻量
将自己的SSH密钥对导入YubiKey 5的PIV和智能卡模块,配合Putty和XShell使用
sbdx
Linux yubikey XShell PIV SSH Linux
前言YubiKey是什么东西我就不多说,简单的说是一种用来保存私钥的硬件设备,私钥一旦写入就无法读出,比起保存在硬盘里的私钥文件,更安全。前段时间入手一个YubiKey5NFC,最近一直在研究怎么用来登录SSH。需求我手上已经有了一个SSH密钥对用来管理着几十台Linux服务器,,在YubikeyMmanager->PIV中只能重新生成密钥对,并且无法导出私钥,然而我不想更换的我的私钥,与我的需求
【AI赋能】蓝耘赋能通义万相2.1:AI创作新时代的强力引擎
星落无尘
人工智能 AIGC
通义万相2.1的强大功能与特性通义万相2.1拥有多项突破性能力,使其在众多AI生成模型中脱颖而出。它支持文生视频、图生视频、视频编辑、文生图和视频生音频等多项任务,是真正意义上的多模态生成模型。在视频生成方面,通义万相2.1推出极速版和专业版两个版本,在权威的VBenchLeaderboard评测榜单上以84.7%的总分登顶。其首创的中文文字生成功能,为视频添加具有电影级效果的中英文文字特效变得轻
Python自定义鼠标指针工具(支持像素级编辑)
木木黄木木
python 计算机外设 开发语言
Python自定义鼠标指针工具(支持像素级编辑)项目简介这是一个基于Python的鼠标指针自定义工具,可以让用户自由创建、编辑和设置Windows系统的鼠标指针。该工具提供了像素级编辑功能,支持多种绘图工具,并且可以直接将设计好的指针应用到系统中。主要功能像素级编辑器支持16x16到64x64多种尺寸铅笔、橡皮擦工具直线、矩形、圆形等几何图形工具填充/空心图形选择取色器功能热点设置可视化热点标记精
LeetCode第78题_子集
@蓝莓果粒茶
算法 leetcode 算法 职场和发展 矩阵 数据结构 c# c++
LeetCode第78题:子集题目描述给你一个整数数组nums,数组中的元素互不相同。返回该数组所有可能的子集(幂集)。解集不能包含重复的子集。你可以按任意顺序返回解集。难度中等问题链接子集示例示例1:输入:nums=[1,2,3]输出:[[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]]示例2:输入:nums=[0]输出:[[],[0]]提示1>result=ne
JetBrains IDEs和Visual Studio Code的对比
ZhangJiQun&MXP
2021 论文 2021 AI python 教学 vscode ide 编辑器
JetBrainsIDEs和VisualStudioCode的对比JetBrainsIDEs是捷克JetBrains公司开发的一系列集成开发环境(IDE)。以下是具体介绍:IntelliJIDEA是JetBrains公司的一款产品主要产品IntelliJIDEA:一款功能强大且广泛应用的Java集成开发环境,有开源免费的社区版和商业收费的终极版。社区版可开发Java桌面和Android应用,终极版
ES6新增的变量
CspecialJ
es6 前端 javascript
ES6新增了两个变量,一个是let,另一个是const,接下来我们说一说他们的区别?let/const与var的区别?1.预解析var会进行预解析let/const没有预解析,必须先声明后使用2.重复变量名var定义的变量可以重名,let/const不允许定义重名变量3.块级作用域var没有块级作用域,只有函数能限制变量的使用范围let/const有块级作用域,任何一个可执行代码的{}都会限制该变
ES6新增语法
CspecialJ
es6 javascript 开发语言
一、定义变量1.1新增变量关键字let变量const常量1.2let/const与var的区别?1.2.1预解析var会进行与解析let/const没有与解析,必须先声明后使用1.2.2重复变量名var定义的变量可以崇明let/const不允许定义重名变量1.2.3块级作用域var没有块级作用域,只有函数能限制变量的使用范围let/const有块级作用域,任何一个可执行代码的{}都会限制该变量的适
EOS开发推荐VS Code和CLion做IDE工具
落叶无声9
以太坊 EOS CLion VS code IDE
每一个开发人员都需要一个良好的IDE,EOS开发也是一样,为项目开发过程构建一个良好的IDE环境是第一步。这就是为什么我们要写这个如何使用VSCode或者CLion进行EOS开发的快速教程的原因。我们还为VSCode创建了一些脚本,这些脚本将你在终端中使用的一些命令自动化。设置VisualStudioCode首先,如果你还没有这些VSCode扩展的话,安装一下。对于EOSDapp开发,它们将非常有
OkHttp源码解析(构建者模式、责任链模式、主线流程)
码农小风
开源框架 移动开发 Android 责任链模式 安卓 移动开发 OkHttp 开源框架
在分析OkHttp的核心流程已经核心类之前,我们先搞清楚两个概念,一个是OkHttpClient和Request在创建时所使用的构建者模式;另外一个则是负责响应处理的拦截器模式;OkHttpClient/Request的构建者模式解析基本概念构建者(又称建造者)模式允许我们使用多个简单的对象一步一步构建成一个复杂的对象。概念解释如果你要装修房子,你就会要考虑这个房子的整体设计怎么做,用地中海风格?
基于Nodejs的你划我猜词库管理系统+源码+高分项目
墨痕_777
python
你划我猜词库管理系统本博文提供了完整的代码和使用教程,适合新入门的朋友参考,完整代码资源文件请转至文末的下载链接。word-manage前端代码npmrunserve运行前端项目npmrunbuild打包生产环境代码npmruntest打包测试环境代码运行系统先打包前端代码npmrunbuild,放在static文件夹nodeapp.js项目运行在2900端口word表设计title词语hard难
数字信号处理之 快速傅里叶变换(FFT)
墨痕_777
信号处理 算法
文章目录快速傅里叶变换(FFT)一、直接计算DFT的问题和改善DFT运算效率的基本途径直接计算DFT的问题改善DFT运算效率的基本途径二、按时间抽取(DIT)的FFT算法(库利-图基算法)算法原理按时间抽取的FFT算法与直接计算DFT运算量的比较按时间抽取的FFT算法的特点按时间抽取的FFT算法的若干变体三、按频率抽取(DIF)的FFT算法(桑德-图基算法)算法原理时间抽取算法与频率抽取算法的比较
第一篇:CTF入门指南:了解CTF的基本概念与比赛形式
菜腿承希
零基础小白入门CTF python java 网络安全 前端
#零基础小白入门CTF解题到成为CTF大佬系列文章##引言CTF(CaptureTheFlag)是一种网络安全竞赛,参赛者需要通过解决各种安全相关的题目来获取“Flag”,从而得分。CTF题目通常涵盖密码学、逆向工程、漏洞利用、Web安全等多个领域。本系列文章将从零基础开始,逐步带你了解CTF的各个知识点,最终帮助你成为一名CTF大佬。##文章目录1.**CTF入门指南:了解CTF的基本概念与比赛
编程与脚本基础:网络安全的核心工具
菜腿承希
零基础网络安全 web安全 安全
###编程与脚本基础:网络安全的核心工具在上一篇教程中,我们探讨了操作系统和网络的基础知识。今天,我们将进入网络安全领域的另一个核心技能——编程与脚本。无论是自动化任务、开发安全工具,还是进行漏洞分析,编程和脚本都是网络安全从业者不可或缺的技能。本文将从编程基础入手,逐步引导你掌握网络安全中常用的编程语言和脚本技术。---####1.**为什么学习编程与脚本?**编程与脚本在网络安全中扮演着重要角
iOS http封装
374016526
ios 服务器交互 http 网络请求
程序开发避免不了与服务器的交互,这里打包了一个自己写的http交互库。希望可以帮到大家。
内置一个basehttp,当我们创建自己的service可以继承实现。
KuroAppBaseHttp *baseHttp = [[KuroAppBaseHttp alloc] init];
[baseHttp setDelegate:self];
[baseHttp
lolcat :一个在 Linux 终端中输出彩虹特效的命令行工具
brotherlamp
linux linux教程 linux视频 linux自学 linux资料
那些相信 Linux 命令行是单调无聊且没有任何乐趣的人们,你们错了,这里有一些有关 Linux 的文章,它们展示着 Linux 是如何的有趣和“淘气” 。
在本文中,我将讨论一个名为“lolcat”的小工具 – 它可以在终端中生成彩虹般的颜色。
何为 lolcat ?
Lolcat 是一个针对 Linux,BSD 和 OSX 平台的工具,它类似于 cat 命令,并为 cat
MongoDB索引管理(1)——[九]
eksliang
mongodb MongoDB管理索引
转载请出自出处:http://eksliang.iteye.com/blog/2178427 一、概述
数据库的索引与书籍的索引类似,有了索引就不需要翻转整本书。数据库的索引跟这个原理一样,首先在索引中找,在索引中找到条目以后,就可以直接跳转到目标文档的位置,从而使查询速度提高几个数据量级。
不使用索引的查询称
Informatica参数及变量
18289753290
Informatica 参数 变量
下面是本人通俗的理解,如有不对之处,希望指正 info参数的设置:在info中用到的参数都在server的专门的配置文件中(最好以parma)结尾 下面的GLOBAl就是全局的,$开头的是系统级变量,$$开头的变量是自定义变量。如果是在session中或者mapping中用到的变量就是局部变量,那就把global换成对应的session或者mapping名字。
[GLOBAL] $Par
python 解析unicode字符串为utf8编码字符串
酷的飞上天空
unicode
php返回的json字符串如果包含中文,则会被转换成\uxx格式的unicode编码字符串返回。
在浏览器中能正常识别这种编码,但是后台程序却不能识别,直接输出显示的是\uxx的字符,并未进行转码。
转换方式如下
>>> import json
>>> q = '{"text":"\u4
Hibernate的总结
永夜-极光
Hibernate
1.hibernate的作用,简化对数据库的编码,使开发人员不必再与复杂的sql语句打交道
做项目大部分都需要用JAVA来链接数据库,比如你要做一个会员注册的 页面,那么 获取到用户填写的 基本信后,你要把这些基本信息存入数据库对应的表中,不用hibernate还有mybatis之类的框架,都不用的话就得用JDBC,也就是JAVA自己的,用这个东西你要写很多的代码,比如保存注册信
SyntaxError: Non-UTF-8 code starting with '\xc4'
随便小屋
python
刚开始看一下Python语言,传说听强大的,但我感觉还是没Java强吧!
写Hello World的时候就遇到一个问题,在Eclipse中写的,代码如下
'''
Created on 2014年10月27日
@author: Logic
'''
print("Hello World!");
运行结果
SyntaxError: Non-UTF-8
学会敬酒礼仪 不做酒席菜鸟
aijuans
菜鸟
俗话说,酒是越喝越厚,但在酒桌上也有很多学问讲究,以下总结了一些酒桌上的你不得不注意的小细节。
细节一:领导相互喝完才轮到自己敬酒。敬酒一定要站起来,双手举杯。
细节二:可以多人敬一人,决不可一人敬多人,除非你是领导。
细节三:自己敬别人,如果不碰杯,自己喝多少可视乎情况而定,比如对方酒量,对方喝酒态度,切不可比对方喝得少,要知道是自己敬人。
细节四:自己敬别人,如果碰杯,一
《创新者的基因》读书笔记
aoyouzi
读书笔记 《创新者的基因》
创新者的基因
创新者的“基因”,即最具创意的企业家具备的五种“发现技能”:联想,观察,实验,发问,建立人脉。
第一部分破坏性创新,从你开始
第一章破坏性创新者的基因
如何获得启示:
发现以下的因素起到了催化剂的作用:(1) -个挑战现状的问题;(2)对某项技术、某个公司或顾客的观察;(3) -次尝试新鲜事物的经验或实验;(4)与某人进行了一次交谈,为他点醒
表单验证技术
百合不是茶
JavaScript DOM对象 String对象 事件
js最主要的功能就是验证表单,下面是我对表单验证的一些理解,贴出来与大家交流交流 ,数显我们要知道表单验证需要的技术点, String对象,事件,函数
一:String对象;通常是对字符串的操作;
1,String的属性;
字符串.length;表示该字符串的长度;
var str= "java"
web.xml配置详解之context-param
bijian1013
java servlet web.xml context-param
一.格式定义:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>contextConfigLocationValue></param-value>
</context-param>
作用:该元
Web系统常见编码漏洞(开发工程师知晓)
Bill_chen
sql PHP Web fckeditor 脚本
1.头号大敌:SQL Injection
原因:程序中对用户输入检查不严格,用户可以提交一段数据库查询代码,根据程序返回的结果,
获得某些他想得知的数据,这就是所谓的SQL Injection,即SQL注入。
本质:
对于输入检查不充分,导致SQL语句将用户提交的非法数据当作语句的一部分来执行。
示例:
String query = "SELECT id FROM users
【MongoDB学习笔记六】MongoDB修改器
bit1129
mongodb
本文首先介绍下MongoDB的基本的增删改查操作,然后,详细介绍MongoDB提供的修改器,以完成各种各样的文档更新操作 MongoDB的主要操作
show dbs 显示当前用户能看到哪些数据库
use foobar 将数据库切换到foobar
show collections 显示当前数据库有哪些集合
db.people.update,update不带参数,可
提高职业素养,做好人生规划
白糖_
人生
培训讲师是成都著名的企业培训讲师,他在讲课中提出的一些观点很新颖,在此我收录了一些分享一下。注:讲师的观点不代表本人的观点,这些东西大家自己揣摩。
1、什么是职业规划:职业规划并不完全代表你到什么阶段要当什么官要拿多少钱,这些都只是梦想。职业规划是清楚的认识自己现在缺什么,这个阶段该学习什么,下个阶段缺什么,又应该怎么去规划学习,这样才算是规划。
国外的网站你都到哪边看?
bozch
技术 网站 国外
学习软件开发技术,如果没有什么英文基础,最好还是看国内的一些技术网站,例如:开源OSchina,csdn,iteye,51cto等等。
个人感觉如果英语基础能力不错的话,可以浏览国外的网站来进行软件技术基础的学习,例如java开发中常用的到的网站有apache.org 里面有apache的很多Projects,springframework.org是spring相关的项目网站,还有几个感觉不错的
编程之美-光影切割问题
bylijinnan
编程之美
package a;
public class DisorderCount {
/**《编程之美》“光影切割问题”
* 主要是两个问题:
* 1.数学公式(设定没有三条以上的直线交于同一点):
* 两条直线最多一个交点,将平面分成了4个区域;
* 三条直线最多三个交点,将平面分成了7个区域;
* 可以推出:N条直线 M个交点,区域数为N+M+1。
关于Web跨站执行脚本概念
chenbowen00
Web 安全 跨站执行脚本
跨站脚本攻击(XSS)是web应用程序中最危险和最常见的安全漏洞之一。安全研究人员发现这个漏洞在最受欢迎的网站,包括谷歌、Facebook、亚马逊、PayPal,和许多其他网站。如果你看看bug赏金计划,大多数报告的问题属于 XSS。为了防止跨站脚本攻击,浏览器也有自己的过滤器,但安全研究人员总是想方设法绕过这些过滤器。这个漏洞是通常用于执行cookie窃取、恶意软件传播,会话劫持,恶意重定向。在
[开源项目与投资]投资开源项目之前需要统计该项目已有的用户数
comsci
开源项目
现在国内和国外,特别是美国那边,突然出现很多开源项目,但是这些项目的用户有多少,有多少忠诚的粉丝,对于投资者来讲,完全是一个未知数,那么要投资开源项目,我们投资者必须准确无误的知道该项目的全部情况,包括项目发起人的情况,项目的维持时间..项目的技术水平,项目的参与者的势力,项目投入产出的效益.....
oracle alert log file(告警日志文件)
daizj
oracle 告警日志文件 alert log file
The alert log is a chronological log of messages and errors, and includes the following items:
All internal errors (ORA-00600), block corruption errors (ORA-01578), and deadlock errors (ORA-00060)
关于 CAS SSO 文章声明
denger
SSO
由于几年前写了几篇 CAS 系列的文章,之后陆续有人参照文章去实现,可都遇到了各种问题,同时经常或多或少的收到不少人的求助。现在这时特此说明几点:
1. 那些文章发表于好几年前了,CAS 已经更新几个很多版本了,由于近年已经没有做该领域方面的事情,所有文章也没有持续更新。
2. 文章只是提供思路,尽管 CAS 版本已经发生变化,但原理和流程仍然一致。最重要的是明白原理,然后
初二上学期难记单词
dcj3sjt126com
english word
lesson 课
traffic 交通
matter 要紧;事物
happy 快乐的,幸福的
second 第二的
idea 主意;想法;意见
mean 意味着
important 重要的,重大的
never 从来,决不
afraid 害怕 的
fifth 第五的
hometown 故乡,家乡
discuss 讨论;议论
east 东方的
agree 同意;赞成
bo
uicollectionview 纯代码布局, 添加头部视图
dcj3sjt126com
Collection
#import <UIKit/UIKit.h>
@interface myHeadView : UICollectionReusableView
{
UILabel *TitleLable;
}
-(void)setTextTitle;
@end
#import "myHeadView.h"
@implementation m
N 位随机数字串的 JAVA 生成实现
FX夜归人
java Math 随机数 Random
/**
* 功能描述 随机数工具类<br />
* @author FengXueYeGuiRen
* 创建时间 2014-7-25<br />
*/
public class RandomUtil {
// 随机数生成器
private static java.util.Random random = new java.util.R
Ehcache(09)——缓存Web页面
234390216
ehcache 页面缓存
页面缓存
目录
1 SimplePageCachingFilter
1.1 calculateKey
1.2 可配置的初始化参数
1.2.1 cach
spring中少用的注解@primary解析
jackyrong
primary
这次看下spring中少见的注解@primary注解,例子
@Component
public class MetalSinger implements Singer{
@Override
public String sing(String lyrics) {
return "I am singing with DIO voice
Java几款性能分析工具的对比
lbwahoo
java
Java几款性能分析工具的对比
摘自:http://my.oschina.net/liux/blog/51800
在给客户的应用程序维护的过程中,我注意到在高负载下的一些性能问题。理论上,增加对应用程序的负载会使性能等比率的下降。然而,我认为性能下降的比率远远高于负载的增加。我也发现,性能可以通过改变应用程序的逻辑来提升,甚至达到极限。为了更详细的了解这一点,我们需要做一些性能
JVM参数配置大全
nickys
jvm 应用服务器
JVM参数配置大全
/usr/local/jdk/bin/java -Dresin.home=/usr/local/resin -server -Xms1800M -Xmx1800M -Xmn300M -Xss512K -XX:PermSize=300M -XX:MaxPermSize=300M -XX:SurvivorRatio=8 -XX:MaxTenuringThreshold=5 -
搭建 CentOS 6 服务器(14) - squid、Varnish
rensanning
varnish
(一)squid
安装
# yum install httpd-tools -y
# htpasswd -c -b /etc/squid/passwords squiduser 123456
# yum install squid -y
设置
# cp /etc/squid/squid.conf /etc/squid/squid.conf.bak
# vi /etc/
Spring缓存注解@Cache使用
tom_seed
spring
参考资料
http://www.ibm.com/developerworks/cn/opensource/os-cn-spring-cache/
http://swiftlet.net/archives/774
缓存注解有以下三个:
@Cacheable @CacheEvict @CachePut
dom4j解析XML时出现"java.lang.noclassdeffounderror: org/jaxen/jaxenexception"错误
xp9802
java.lang.NoClassDefFoundError: org/jaxen/JaxenExc
关键字: java.lang.noclassdeffounderror: org/jaxen/jaxenexception
使用dom4j解析XML时,要快速获取某个节点的数据,使用XPath是个不错的方法,dom4j的快速手册里也建议使用这种方式
执行时却抛出以下异常:
Exceptio