发布网友 发布时间:2022-04-22 06:17
共3个回答
懂视网 时间:2022-04-22 10:38
opentoken的字面意思为“打开的令牌”,是服务端生成的一串字符串,也是客户端进行请求时的一个标识。
opentoken代表的是调用OpenAPI访问和修改用户数据过程中必须传入的参数,由每次用户登录时生成,过期时间默认为三个月,用户再次登录时自动刷新。当用户第一次登录后,服务器生成一个token并将此token返回给客户端,以后客户端只需带上这个token前来请求数据即可,无需再次带上用户名和密码。
用户在登录APP时,APP端会发送加密的用户名和密码到服务器,服务器验证用户名和密码,如果验证成功,就会生成相应位数的字符产作为token存储到服务器中,并且将该token返回给APP端。
热心网友 时间:2022-04-22 07:46
简单的说#{}和${}的区别:$是String 拼接插入的#则是占位符来做处理的,写法比如字符串类型,$需要自己添加''#就不需要添加,对于日志的差别就是$会打印在日志里面,#则显示?
大多数我们都是用#{} 因为可以防止sql注入,但是有时候${}还是很必要的,比如传入tableName,或者fieldName比如Order By id||time 就需要${}传入 #{}就无法搞定
typeHandler就无法对${}起作用
---只有明白工具是如何玩耍的,我们才能更好的使用工具
先介绍一个解析#{}和${}的类,这里${}就替换成对对应的值了,而#{}替换成?,并且在这里解析了这个属性的字段,包括判断了类型等等
public class GenericTokenParser {
private final String openToken;//这个比如#{ 或者${
private final String closeToken;//这里基本上就是}
private final TokenHandler handler;//根据#{key}或者${key}得到key的值
public GenericTokenParser(String openToken, String closeToken, TokenHandler handler) {
this.openToken = openToken;
this.closeToken = closeToken;
this.handler = handler;
}
/**
*这个就是替换的了${key} 然后通过hanlder获取value 拼接进去
**/
public String parse(String text) {
StringBuilder builder = new StringBuilder();
if (text != null && text.length() > 0) {
char[] src = text.toCharArray();
int offset = 0;
int start = text.indexOf(openToken, offset);
while (start > -1) {
if (start > 0 && src[start - 1] == '\\') {
// the variable is escaped. remove the backslash.
builder.append(src, offset, start - 1).append(openToken);
offset = start + openToken.length();
} else {
int end = text.indexOf(closeToken, start);
if (end == -1) {
builder.append(src, offset, src.length - offset);
offset = src.length;
} else {
builder.append(src, offset, start - offset);
offset = start + openToken.length();
String content = new String(src, offset, end - offset);//拿到#{key}||${key}中的key
builder.append(handler.handleToken(content));//根据key获取对应的"value"
offset = end + closeToken.length();
}
}
start = text.indexOf(openToken, offset);
}
if (offset < src.length) {
builder.append(src, offset, src.length - offset);
}
}
return builder.toString();
}
}
其实最大的区别也就是下面的两个不同的实现类
1.${} 的解析实现类
判断一下参数的类型,然后就把value给搞定了,没有添加其他的东西,万能的Ognl
private static class BindingTokenParser implements TokenHandler {
private DynamicContext context;
public BindingTokenParser(DynamicContext context) {
this.context = context;
}
public String handleToken(String content) {
Object parameter = context.getBindings().get("_parameter");
if (parameter == null) {
context.getBindings().put("value", null);
} else if (SimpleTypeRegistry.isSimpleType(parameter.getClass())) {
context.getBindings().put("value", parameter);
}
Object value = OgnlCache.getValue(content, context.getBindings());
return (value == null ? "" : String.valueOf(value)); // issue #274 return "" instead of "null"
}
}
2.#{} 的解析实现类
这里就比较复杂了,判断了javaType,typeHandler,数字精度,通过hanlder,我们就可以处理一些列复杂的数据
private static class ParameterMappingTokenHandler extends BaseBuilder implements TokenHandler {
private List<ParameterMapping> parameterMappings = new ArrayList<ParameterMapping>();
private Class<?> parameterType;
private MetaObject metaParameters;
public ParameterMappingTokenHandler(Configuration configuration, Class<?> parameterType, Map<String, Object> additionalParameters) {
super(configuration);
this.parameterType = parameterType;
this.metaParameters = configuration.newMetaObject(additionalParameters);
}
public List<ParameterMapping> getParameterMappings() {
return parameterMappings;
}
public String handleToken(String content) {
parameterMappings.add(buildParameterMapping(content));
return "?";
}
//这里就是把#{key}内容进行解析成一个带有一些列属性的类然后再由一些列typehanlder来setValue
private ParameterMapping buildParameterMapping(String content) {
Map<String, String> propertiesMap = parseParameterMapping(content);
String property = propertiesMap.get("property");
Class<?> propertyType;
if (metaParameters.hasGetter(property)) { // issue #448 get type from additional params
propertyType = metaParameters.getGetterType(property);
} else if (typeHandlerRegistry.hasTypeHandler(parameterType)) {
propertyType = parameterType;
} else if (JdbcType.CURSOR.name().equals(propertiesMap.get("jdbcType"))) {
propertyType = java.sql.ResultSet.class;
} else if (property != null) {
MetaClass metaClass = MetaClass.forClass(parameterType);
if (metaClass.hasGetter(property)) {
propertyType = metaClass.getGetterType(property);
} else {
propertyType = Object.class;
}
} else {
propertyType = Object.class;
}
ParameterMapping.Builder builder = new ParameterMapping.Builder(configuration, property, propertyType);
Class<?> javaType = propertyType;
String typeHandlerAlias = null;
for (Map.Entry<String, String> entry : propertiesMap.entrySet()) {
String name = entry.getKey();
String value = entry.getValue();
if ("javaType".equals(name)) {
javaType = resolveClass(value);
builder.javaType(javaType);
} else if ("jdbcType".equals(name)) {
builder.jdbcType(resolveJdbcType(value));
} else if ("mode".equals(name)) {
builder.mode(resolveParameterMode(value));
} else if ("numericScale".equals(name)) {
builder.numericScale(Integer.valueOf(value));
} else if ("resultMap".equals(name)) {
builder.resultMapId(value);
} else if ("typeHandler".equals(name)) {
typeHandlerAlias = value;
} else if ("jdbcTypeName".equals(name)) {
builder.jdbcTypeName(value);
} else if ("property".equals(name)) {
// Do Nothing
} else if ("expression".equals(name)) {
throw new BuilderException("Expression based parameters are not supported yet");
} else {
throw new BuilderException("An invalid property '" + name + "' was found in mapping #{" + content + "}. Valid properties are " + parameterProperties);
}
}
if (typeHandlerAlias != null) {
builder.typeHandler(resolveTypeHandler(javaType, typeHandlerAlias));
}
return builder.build();
}
private Map<String, String> parseParameterMapping(String content) {
try {
return new ParameterExpression(content);
} catch (BuilderException ex) {
throw ex;
} catch (Exception ex) {
throw new BuilderException("Parsing error was found in mapping #{" + content + "}. Check syntax #{property|(expression), var1=value1, var2=value2, ...} ", ex);
}
}
}
热心网友 时间:2022-04-22 09:04
mybatis中拼接SQL参数用#{}
拼接可执行的函数的参数需要使用${}输出参数.