## 关于SpringMVC Model数据不允许覆盖
报错
Cannot expose session attribute 'projectId' because of an existing model object of the same name
代码:
@RequestMapping("turnToDocs.do")
public ModelAndView turnToDocs(String projectId){
Map<String, String> map = new HashMap<String, String>();
map.put("projectId", projectId);
return new ModelAndView("ftl/file_manage/approve_docs",map);
}
异常:
二月 24, 2017 11:53:54 上午 org.apache.catalina.core.StandardWrapperValve invoke
严重: Servlet.service() for servlet [spring] in context with path [/STObject] threw exception [Cannot expose session attribute 'projectId' because of an existing model object of the same name] with root cause
javax.servlet.ServletException: Cannot expose session attribute 'projectId' because of an existing model object of the same name
at org.springframework.web.servlet.view.AbstractTemplateView.renderMergedOutputModel(AbstractTemplateView.java:141)
at org.springframework.web.servlet.view.AbstractView.render(AbstractView.java:266)
at org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1225)
at org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1012)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:959)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:876)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:931)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:822)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:622)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:807)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:230)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
at com.cxcm.crm.filter.AuthorityFilter.doFilter(AuthorityFilter.java:60)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:108)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:199)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:108)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:522)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:620)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:349)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:1110)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:785)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1419)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:44)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)
异常原因:
查看spring源码发现,spring mvc会把session中的数据放到model中去,默认情况下不允许model中的数据被重写。而我的代码中,之前已经在session中设置了name为projectId的数据值,所以,不允许在new ModelAndView中继续放名为projectId的数据。
**if** (**this**.exposeSessionAttributes) {
HttpSession session = request.getSession(**false**);
**if** (session != **null**) {
**for** (Enumeration<String> en = session.getAttributeNames(); en.hasMoreElements();) {
String attribute = en.nextElement();
**if** (model.containsKey(attribute) && !**this**.allowSessionOverride) {
**throw** **new** ServletException("Cannot expose session attribute '" + attribute +
"' because of an existing model object of the same name");
}
Object attributeValue = session.getAttribute(attribute);
**if** (logger.isDebugEnabled()) {
logger.debug("Exposing session attribute '" + attribute +
"' with value [" + attributeValue + "] to model");
}
model.put(attribute, attributeValue);
}
}
}
其它测试:
- 既然session中的值都复制到model中了,那是否在ftl中可以获取呢?回答:对的
测试方法:在controller中修改model中key为pId,session中key依然为projectId,在ftl用 input value=${projectId!}依然可以获取到值
- 在其它controller中采用projectId传值,那么这个projectId中的值到底是session中的,还是request中的呢?回答:request中的
测试方法:修改request中projectId的值,从ftl中获取的数值和request中的数值一致
正文到此结束