请求数据的保存是使用Template实现的。如下图所示,每个请求的部分都是一个Template。
父类Template
属性
// 用来区分查询参数的正则
private static final Pattern QUERY_STRING_PATTERN = Pattern.compile("(?<!\\{)(\\?)");
// 原始字符串
private final String template;
// 允许不解析,当没有合适的值时,可以不解析
private final boolean allowUnresolved;
// 编码
private final EncodingOptions encode;
// 是否编码斜杠 /
private final boolean encodeSlash;
private final Charset charset;
// 占位符将原始字符串分开,每个是一个TemplateChunk
// /provider/userinfo/{id}/test/{age} list包含了这四个分 {} 这种类型是需要解析的,替换为真正的值
// /provider/userinfo/
// {id}
// /test/
// {age}
private final List<TemplateChunk> templateChunks = new ArrayList<>();
构造函数
分别给属性赋值,有一步逻辑操作时解析模板,就是将原始字符串解析,之后给templateChunks 赋值。
Template(
String value, ExpansionOptions allowUnresolved, EncodingOptions encode, boolean encodeSlash,
Charset charset) {
if (value == null) {
throw new IllegalArgumentException("template is required.");
}
this.template = value;
this.allowUnresolved = ExpansionOptions.ALLOW_UNRESOLVED == allowUnresolved;
this.encode = encode;
this.encodeSlash = encodeSlash;
this.charset = charset;
this.parseTemplate();
}
可以看到解析的时候,{}这种占位符的解析成了Expression ,普通字符串只是Literal类型,只是保存字符串的对象。
private void parseFragment(String fragment, boolean query) {
ChunkTokenizer tokenizer = new ChunkTokenizer(fragment);
while (tokenizer.hasNext()) {
/* check to see if we have an expression or a literal */
String chunk = tokenizer.next();
if (chunk.startsWith("{")) {
/* it's an expression, defer encoding until resolution */
FragmentType type = (query) ? FragmentType.QUERY : FragmentType.PATH_SEGMENT;
Expression expression = Expressions.create(chunk, type);
if (expression == null) {
this.templateChunks.add(Literal.create(encode(chunk, query)));
} else {
this.templateChunks.add(expression);
}
} else {
/* it's a literal, pct-encode it */
this.templateChunks.add(Literal.create(encode(chunk, query)));
}
}
}
创建占位表达式
public static Expression create(final String value, final FragmentType type) {
// 得到严格的表达式{id}->返回值是id,相当于取{}中间的字符串
final String expression = stripBraces(value);
if (expression == null || expression.isEmpty()) {
throw new IllegalArgumentException("an expression is required.");
}
Optional<Entry<Pattern, Class<? extends Expression>>> matchedExpressionEntry =
expressions.entrySet