001/* 002 * Copyright 2002-2017 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.web.servlet.view; 018 019import javax.servlet.ServletContext; 020import javax.servlet.http.HttpServletRequest; 021 022import org.springframework.context.MessageSource; 023import org.springframework.lang.Nullable; 024import org.springframework.web.servlet.support.JstlUtils; 025import org.springframework.web.servlet.support.RequestContext; 026 027/** 028 * Specialization of {@link InternalResourceView} for JSTL pages, 029 * i.e. JSP pages that use the JSP Standard Tag Library. 030 * 031 * <p>Exposes JSTL-specific request attributes specifying locale 032 * and resource bundle for JSTL's formatting and message tags, 033 * using Spring's locale and {@link org.springframework.context.MessageSource}. 034 * 035 * <p>Typical usage with {@link InternalResourceViewResolver} would look as follows, 036 * from the perspective of the DispatcherServlet context definition: 037 * 038 * <pre class="code"> 039 * <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> 040 * <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/> 041 * <property name="prefix" value="/WEB-INF/jsp/"/> 042 * <property name="suffix" value=".jsp"/> 043 * </bean> 044 * 045 * <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource"> 046 * <property name="basename" value="messages"/> 047 * </bean></pre> 048 * 049 * Every view name returned from a handler will be translated to a JSP 050 * resource (for example: "myView" -> "/WEB-INF/jsp/myView.jsp"), using 051 * this view class to enable explicit JSTL support. 052 * 053 * <p>The specified MessageSource loads messages from "messages.properties" etc 054 * files in the class path. This will automatically be exposed to views as 055 * JSTL localization context, which the JSTL fmt tags (message etc) will use. 056 * Consider using Spring's ReloadableResourceBundleMessageSource instead of 057 * the standard ResourceBundleMessageSource for more sophistication. 058 * Of course, any other Spring components can share the same MessageSource. 059 * 060 * <p>This is a separate class mainly to avoid JSTL dependencies in 061 * {@link InternalResourceView} itself. JSTL has not been part of standard 062 * J2EE up until J2EE 1.4, so we can't assume the JSTL API jar to be 063 * available on the class path. 064 * 065 * <p>Hint: Set the {@link #setExposeContextBeansAsAttributes} flag to "true" 066 * in order to make all Spring beans in the application context accessible 067 * within JSTL expressions (e.g. in a {@code c:out} value expression). 068 * This will also make all such beans accessible in plain {@code ${...}} 069 * expressions in a JSP 2.0 page. 070 * 071 * @author Juergen Hoeller 072 * @since 27.02.2003 073 * @see org.springframework.web.servlet.support.JstlUtils#exposeLocalizationContext 074 * @see InternalResourceViewResolver 075 * @see org.springframework.context.support.ResourceBundleMessageSource 076 * @see org.springframework.context.support.ReloadableResourceBundleMessageSource 077 */ 078public class JstlView extends InternalResourceView { 079 080 @Nullable 081 private MessageSource messageSource; 082 083 084 /** 085 * Constructor for use as a bean. 086 * @see #setUrl 087 */ 088 public JstlView() { 089 } 090 091 /** 092 * Create a new JstlView with the given URL. 093 * @param url the URL to forward to 094 */ 095 public JstlView(String url) { 096 super(url); 097 } 098 099 /** 100 * Create a new JstlView with the given URL. 101 * @param url the URL to forward to 102 * @param messageSource the MessageSource to expose to JSTL tags 103 * (will be wrapped with a JSTL-aware MessageSource that is aware of JSTL's 104 * {@code javax.servlet.jsp.jstl.fmt.localizationContext} context-param) 105 * @see JstlUtils#getJstlAwareMessageSource 106 */ 107 public JstlView(String url, MessageSource messageSource) { 108 this(url); 109 this.messageSource = messageSource; 110 } 111 112 113 /** 114 * Wraps the MessageSource with a JSTL-aware MessageSource that is aware 115 * of JSTL's {@code javax.servlet.jsp.jstl.fmt.localizationContext} 116 * context-param. 117 * @see JstlUtils#getJstlAwareMessageSource 118 */ 119 @Override 120 protected void initServletContext(ServletContext servletContext) { 121 if (this.messageSource != null) { 122 this.messageSource = JstlUtils.getJstlAwareMessageSource(servletContext, this.messageSource); 123 } 124 super.initServletContext(servletContext); 125 } 126 127 /** 128 * Exposes a JSTL LocalizationContext for Spring's locale and MessageSource. 129 * @see JstlUtils#exposeLocalizationContext 130 */ 131 @Override 132 protected void exposeHelpers(HttpServletRequest request) throws Exception { 133 if (this.messageSource != null) { 134 JstlUtils.exposeLocalizationContext(request, this.messageSource); 135 } 136 else { 137 JstlUtils.exposeLocalizationContext(new RequestContext(request, getServletContext())); 138 } 139 } 140 141}