Fork me on GitHub

SpringBoot2踩坑之SpringWebContext方法过时

SpringWebContext方法过时

今天在做项目的时候,为了优化访问速度,应对高并发,想把页面信息全部获取出来存到redis缓存中,这样每次访问就不用客户端进行渲染了,速度能快不少。

想用thymeleafViewResolver.getTemplateEngine().process("goodslist.html",ctx);函数实现,里面有一个ctx参数,这个参数就是WebContext

然后定义这个变量 SpringWebContext ctx = new SpringWebContext(......)

哎,这个方法在SpringBoot1.X的时候还能有,在org.thymeleaf.spring4.context这个package下,在、SpringBoot2.X +thymeleaf3.0.9 中没有,想去找一下用什么来代替,直接去org.thymeleaf.spring4下面去找,没找到相同类型的,然后取找thymeleaf.spring5的API,还找不到,只能找到thymeleaf.spring4的API,。想想还要用,怎么办啊,总不能把版本切换了吧,那有些别的说不定也得改,自己写吧,自力更生艰苦奋斗。

找了之前的一个项目,然后找到了那里面的SpringWebContext是怎么写的,超过来就完了,

但是不行SpringWebContext继承的是org.thymeleaf.context下的WebContext方法,在SpringBoot2.0+thymeleaf3.0.9中定义成final类型的,不能继承,想想要不把库的代码改了,还是算了,再往上找,找到这个WebContext extends AbstractContext implements IWebContext,没有final,所以一层一层的找到之后,按照他的源码改了一下,自己重写了SpringWebContext方法,如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
package com.springboot.SecKill.util;

import org.springframework.context.ApplicationContext;
import org.thymeleaf.context.AbstractContext;
import org.thymeleaf.context.IWebContext;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.Locale;
import java.util.Map;
import java.util.HashMap;
import java.util.concurrent.ConcurrentHashMap;

/**
* @author WilsonSong
* @date 2018/8/5
*/
public class SpringWebContextUtil extends AbstractContext implements IWebContext {

private final HttpServletRequest request;
private final HttpServletResponse response;
private final ServletContext servletContext;

public static final String BEANS_VARIABLE_NAME = "beans";
private static final ConcurrentHashMap<ApplicationContext, HashMap<String, Object>> variableMapPrototypes = new ConcurrentHashMap();
private final ApplicationContext applicationContext;

public SpringWebContextUtil(final HttpServletRequest request,
final HttpServletResponse response,
final ServletContext servletContext,
final Locale locale,
final Map<String, Object> variables,
final ApplicationContext appctx){
super(locale,addSpringSpecificVariables(variables, appctx));
this.request = request;
this.response = response;
this.servletContext = servletContext;
this.applicationContext = appctx;

}

private static Map<String, Object> addSpringSpecificVariables(Map<String, ?> variables, ApplicationContext appctx) {
HashMap<String, Object> variableMapPrototype = (HashMap)variableMapPrototypes.get(appctx);
if (variableMapPrototype == null) {
variableMapPrototype = new HashMap(20, 1.0F);
ContexBeans beans = new ContexBeans(appctx);
variableMapPrototype.put("beans", beans);
variableMapPrototypes.put(appctx, variableMapPrototype);
}

Map newVariables;
synchronized(variableMapPrototype) {
newVariables = (Map)variableMapPrototype.clone();
}

if (variables != null) {
newVariables.putAll(variables);
}

return newVariables;
}

public ApplicationContext getApplicationContext() {
return this.applicationContext;
}

public HttpServletRequest getRequest() {
return this.request;
}

public HttpSession getSession() {
return this.request.getSession(false);
}

public HttpServletResponse getResponse() {
return this.response;
}

public ServletContext getServletContext() {
return this.servletContext;
}
}

其中的ContexBeans是自己定义的,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
package com.springboot.SecKill.util;

/**
* @author WilsonSong
* @date 2018/8/5
*/

import java.util.Arrays;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;
import org.springframework.context.ApplicationContext;
import org.thymeleaf.util.Validate;
public class ContexBeans implements Map<String, Object> {
private final ApplicationContext ctx;

public ContexBeans(ApplicationContext ctx) {
Validate.notNull(ctx, "Application Context cannot be null");
this.ctx = ctx;
}

public boolean containsKey(Object key) {
Validate.notNull(key, "Key cannot be null");
return this.ctx.containsBean(key.toString());
}

public Object get(Object key) {
Validate.notNull(key, "Key cannot be null");
return this.ctx.getBean(key.toString());
}

public Set<String> keySet() {
return new LinkedHashSet(Arrays.asList(this.ctx.getBeanDefinitionNames()));
}

public int size() {
return this.ctx.getBeanDefinitionCount();
}

public boolean isEmpty() {
return this.ctx.getBeanDefinitionCount() <= 0;
}

public boolean containsValue(Object value) {
throw new UnsupportedOperationException("Method \"containsValue\" not supported in Beans object");
}

public Object put(String key, Object value) {
throw new UnsupportedOperationException("Method \"put\" not supported in Beans object");
}

public void putAll(Map<? extends String, ?> m) {
throw new UnsupportedOperationException("Method \"putAll\" not supported in Beans object");
}

public Object remove(Object key) {
throw new UnsupportedOperationException("Method \"remove\" not supported in Beans object");
}

public void clear() {
throw new UnsupportedOperationException("Method \"clear\" not supported in Beans object");
}

public Collection<Object> values() {
throw new UnsupportedOperationException("Method \"values\" not supported in Beans object");
}

public Set<Entry<String, Object>> entrySet() {
throw new UnsupportedOperationException("Method \"entrySet\" not supported in Beans object");
}

}

这样就能用了。

本文标题:SpringBoot2踩坑之SpringWebContext方法过时

文章作者:WilsonSong

发布时间:2018年08月05日 - 08:08

最后更新:2018年08月16日 - 20:08

原始链接:https://songwell1024.github.io/2018/08/05/SpringWebContext/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

-------------本文结束感谢您的阅读-------------