1616
1717package org .springframework .boot .autoconfigure .web ;
1818
19+ import java .util .Collections ;
1920import java .util .HashMap ;
2021import java .util .List ;
2122import java .util .Map ;
5152import org .springframework .core .Ordered ;
5253import org .springframework .core .io .support .SpringFactoriesLoader ;
5354import org .springframework .core .type .AnnotatedTypeMetadata ;
55+ import org .springframework .expression .EvaluationContext ;
5456import org .springframework .expression .Expression ;
5557import org .springframework .expression .spel .standard .SpelExpressionParser ;
5658import org .springframework .expression .spel .support .StandardEvaluationContext ;
57- import org .springframework .util .PropertyPlaceholderHelper ;
5859import org .springframework .util .PropertyPlaceholderHelper .PlaceholderResolver ;
5960import org .springframework .web .servlet .DispatcherServlet ;
6061import org .springframework .web .servlet .View ;
@@ -172,19 +173,18 @@ public ConditionOutcome getMatchOutcome(ConditionContext context,
172173 */
173174 private static class SpelView implements View {
174175
175- private final String template ;
176-
177- private final StandardEvaluationContext context = new StandardEvaluationContext ();
176+ private final NonRecursivePropertyPlaceholderHelper helper ;
178177
179- private PropertyPlaceholderHelper helper ;
178+ private final String template ;
180179
181- private PlaceholderResolver resolver ;
180+ private final Map < String , Expression > expressions ;
182181
183182 public SpelView (String template ) {
183+ this .helper = new NonRecursivePropertyPlaceholderHelper ("${" , "}" );
184184 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 ( );
188188 }
189189
190190 @ Override
@@ -200,36 +200,63 @@ public void render(Map<String, ?> model, HttpServletRequest request,
200200 }
201201 Map <String , Object > map = new HashMap <String , Object >(model );
202202 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 );
205205 response .getWriter ().append (result );
206206 }
207207
208208 }
209209
210210 /**
211- * SpEL based {@link PlaceholderResolver}.
211+ * {@link PlaceholderResolver} to collect placeholder expressions .
212212 */
213- private static class SpelPlaceholderResolver implements PlaceholderResolver {
213+ private static class ExpressionCollector implements PlaceholderResolver {
214214
215215 private final SpelExpressionParser parser = new SpelExpressionParser ();
216216
217- private final StandardEvaluationContext context ;
217+ private final Map < String , Expression > expressions = new HashMap < String , Expression >() ;
218218
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 ;
221250 }
222251
223252 @ 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 ());
233260 }
234261
235262 }
0 commit comments