001/*
002 * Copyright 2002-2014 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.mvc;
018
019import javax.servlet.http.HttpServletRequest;
020import javax.servlet.http.HttpServletResponse;
021
022import org.springframework.http.HttpMethod;
023import org.springframework.http.HttpStatus;
024import org.springframework.web.servlet.ModelAndView;
025import org.springframework.web.servlet.View;
026import org.springframework.web.servlet.support.RequestContextUtils;
027
028/**
029 * Trivial controller that always returns a pre-configured view and optionally
030 * sets the response status code. The view and status can be configured using
031 * the provided configuration properties.
032 *
033 * @author Rod Johnson
034 * @author Juergen Hoeller
035 * @author Keith Donald
036 * @author Rossen Stoyanchev
037 */
038public class ParameterizableViewController extends AbstractController {
039
040        private Object view;
041
042        private HttpStatus statusCode;
043
044        private boolean statusOnly;
045
046
047        public ParameterizableViewController() {
048                super(false);
049                setSupportedMethods(HttpMethod.GET.name(), HttpMethod.HEAD.name());
050        }
051
052        /**
053         * Set a view name for the ModelAndView to return, to be resolved by the
054         * DispatcherServlet via a ViewResolver. Will override any pre-existing
055         * view name or View.
056         */
057        public void setViewName(String viewName) {
058                this.view = viewName;
059        }
060
061        /**
062         * Return the name of the view to delegate to, or {@code null} if using a
063         * View instance.
064         */
065        public String getViewName() {
066                return (this.view instanceof String ? (String) this.view : null);
067        }
068
069        /**
070         * Set a View object for the ModelAndView to return.
071         * Will override any pre-existing view name or View.
072         * @since 4.1
073         */
074        public void setView(View view) {
075                this.view = view;
076        }
077
078        /**
079         * Return the View object, or {@code null} if we are using a view name
080         * to be resolved by the DispatcherServlet via a ViewResolver.
081         * @since 4.1
082         */
083        public View getView() {
084                return (this.view instanceof View ? (View) this.view : null);
085        }
086
087        /**
088         * Configure the HTTP status code that this controller should set on the
089         * response.
090         * <p>When a "redirect:" prefixed view name is configured, there is no need
091         * to set this property since RedirectView will do that. However this property
092         * may still be used to override the 3xx status code of {@code RedirectView}.
093         * For full control over redirecting provide a {@code RedirectView} instance.
094         * <p>If the status code is 204 and no view is configured, the request is
095         * fully handled within the controller.
096         * @since 4.1
097         */
098        public void setStatusCode(HttpStatus statusCode) {
099                this.statusCode = statusCode;
100        }
101
102        /**
103         * Return the configured HTTP status code or {@code null}.
104         * @since 4.1
105         */
106        public HttpStatus getStatusCode() {
107                return this.statusCode;
108        }
109
110
111        /**
112         * The property can be used to indicate the request is considered fully
113         * handled within the controller and that no view should be used for rendering.
114         * Useful in combination with {@link #setStatusCode}.
115         * <p>By default this is set to {@code false}.
116         * @since 4.1
117         */
118        public void setStatusOnly(boolean statusOnly) {
119                this.statusOnly = statusOnly;
120        }
121
122        /**
123         * Whether the request is fully handled within the controller.
124         */
125        public boolean isStatusOnly() {
126                return this.statusOnly;
127        }
128
129
130        /**
131         * Return a ModelAndView object with the specified view name.
132         * <p>The content of the {@link RequestContextUtils#getInputFlashMap
133         * "input" FlashMap} is also added to the model.
134         * @see #getViewName()
135         */
136        @Override
137        protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response)
138                        throws Exception {
139
140                String viewName = getViewName();
141
142                if (getStatusCode() != null) {
143                        if (getStatusCode().is3xxRedirection()) {
144                                request.setAttribute(View.RESPONSE_STATUS_ATTRIBUTE, getStatusCode());
145                                viewName = (viewName != null && !viewName.startsWith("redirect:") ? "redirect:" + viewName : viewName);
146                        }
147                        else {
148                                response.setStatus(getStatusCode().value());
149                                if (isStatusOnly() || (getStatusCode().equals(HttpStatus.NO_CONTENT) && getViewName() == null)) {
150                                        return null;
151                                }
152                        }
153                }
154
155                ModelAndView modelAndView = new ModelAndView();
156                modelAndView.addAllObjects(RequestContextUtils.getInputFlashMap(request));
157
158                if (getViewName() != null) {
159                        modelAndView.setViewName(viewName);
160                }
161                else {
162                        modelAndView.setView(getView());
163                }
164
165                return (isStatusOnly() ? null : modelAndView);
166        }
167
168}