16
16
17
17
package org .springframework .boot .autoconfigure .web ;
18
18
19
+ import java .util .Collections ;
19
20
import java .util .HashMap ;
20
21
import java .util .List ;
21
22
import java .util .Map ;
51
52
import org .springframework .core .Ordered ;
52
53
import org .springframework .core .io .support .SpringFactoriesLoader ;
53
54
import org .springframework .core .type .AnnotatedTypeMetadata ;
55
+ import org .springframework .expression .EvaluationContext ;
54
56
import org .springframework .expression .Expression ;
55
57
import org .springframework .expression .spel .standard .SpelExpressionParser ;
56
58
import org .springframework .expression .spel .support .StandardEvaluationContext ;
57
- import org .springframework .util .PropertyPlaceholderHelper ;
58
59
import org .springframework .util .PropertyPlaceholderHelper .PlaceholderResolver ;
59
60
import org .springframework .web .servlet .DispatcherServlet ;
60
61
import org .springframework .web .servlet .View ;
@@ -172,19 +173,18 @@ public ConditionOutcome getMatchOutcome(ConditionContext context,
172
173
*/
173
174
private static class SpelView implements View {
174
175
175
- private final String template ;
176
-
177
- private final StandardEvaluationContext context = new StandardEvaluationContext ();
176
+ private final NonRecursivePropertyPlaceholderHelper helper ;
178
177
179
- private PropertyPlaceholderHelper helper ;
178
+ private final String template ;
180
179
181
- private PlaceholderResolver resolver ;
180
+ private final Map < String , Expression > expressions ;
182
181
183
182
public SpelView (String template ) {
183
+ this .helper = new NonRecursivePropertyPlaceholderHelper ("${" , "}" );
184
184
this .template = template ;
185
- this . context . addPropertyAccessor ( new MapAccessor () );
186
- this .helper = new PropertyPlaceholderHelper ( "${" , "}" );
187
- this .resolver = new SpelPlaceholderResolver ( this . context );
185
+ ExpressionCollector expressionCollector = new ExpressionCollector ( );
186
+ this .helper . replacePlaceholders ( this . template , expressionCollector );
187
+ this .expressions = expressionCollector . getExpressions ( );
188
188
}
189
189
190
190
@ Override
@@ -200,36 +200,63 @@ public void render(Map<String, ?> model, HttpServletRequest request,
200
200
}
201
201
Map <String , Object > map = new HashMap <String , Object >(model );
202
202
map .put ("path" , request .getContextPath ());
203
- this .context . setRootObject ( map );
204
- String result = this .helper .replacePlaceholders (this .template , this . resolver );
203
+ PlaceholderResolver resolver = new ExpressionResolver ( this .expressions , map );
204
+ String result = this .helper .replacePlaceholders (this .template , resolver );
205
205
response .getWriter ().append (result );
206
206
}
207
207
208
208
}
209
209
210
210
/**
211
- * SpEL based {@link PlaceholderResolver}.
211
+ * {@link PlaceholderResolver} to collect placeholder expressions .
212
212
*/
213
- private static class SpelPlaceholderResolver implements PlaceholderResolver {
213
+ private static class ExpressionCollector implements PlaceholderResolver {
214
214
215
215
private final SpelExpressionParser parser = new SpelExpressionParser ();
216
216
217
- private final StandardEvaluationContext context ;
217
+ private final Map < String , Expression > expressions = new HashMap < String , Expression >() ;
218
218
219
- public SpelPlaceholderResolver (StandardEvaluationContext context ) {
220
- this .context = context ;
219
+ @ Override
220
+ public String resolvePlaceholder (String name ) {
221
+ this .expressions .put (name , this .parser .parseExpression (name ));
222
+ return null ;
223
+ }
224
+
225
+ public Map <String , Expression > getExpressions () {
226
+ return Collections .unmodifiableMap (this .expressions );
227
+ }
228
+
229
+ }
230
+
231
+ /**
232
+ * SpEL based {@link PlaceholderResolver}.
233
+ */
234
+ private static class ExpressionResolver implements PlaceholderResolver {
235
+
236
+ private final Map <String , Expression > expressions ;
237
+
238
+ private final EvaluationContext context ;
239
+
240
+ ExpressionResolver (Map <String , Expression > expressions , Map <String , ?> map ) {
241
+ this .expressions = expressions ;
242
+ this .context = getContext (map );
243
+ }
244
+
245
+ private EvaluationContext getContext (Map <String , ?> map ) {
246
+ StandardEvaluationContext context = new StandardEvaluationContext ();
247
+ context .addPropertyAccessor (new MapAccessor ());
248
+ context .setRootObject (map );
249
+ return context ;
221
250
}
222
251
223
252
@ Override
224
- public String resolvePlaceholder (String name ) {
225
- Expression expression = this .parser .parseExpression (name );
226
- try {
227
- Object value = expression .getValue (this .context );
228
- return HtmlUtils .htmlEscape (value == null ? null : value .toString ());
229
- }
230
- catch (Exception ex ) {
231
- return null ;
232
- }
253
+ public String resolvePlaceholder (String placeholderName ) {
254
+ Expression expression = this .expressions .get (placeholderName );
255
+ return escape (expression == null ? null : expression .getValue (this .context ));
256
+ }
257
+
258
+ private String escape (Object value ) {
259
+ return HtmlUtils .htmlEscape (value == null ? null : value .toString ());
233
260
}
234
261
235
262
}
0 commit comments