Cannot expose request attribute 'userName' because of an existing model object of the same name

一、背景说明

     在预发布环境中进行功能验证时,点击“我的反馈”菜单时出现Cannot expose request attribute 'userName' because of an existing model object of the same name 错误,在测试环境正常显示。

二、认识异常

11-Jun-2019 16:43:57.429 SEVERE    org.apache.catalina.core.StandardWrapperValve.invoke Servlet.service() for servlet [springServlet] in context with path [] threw exception [Cannot expose request attribute 'userName' because of an existing model object of the same name] with root cause
javax.servlet.ServletException: Cannot expose request attribute 'userName' because of an existing model object of the same name
at org.springframework.web.servlet.view.AbstractTemplateView.renderMergedOutputModel(AbstractTemplateView.java:123)
at org.springframework.web.servlet.view.AbstractView.render(AbstractView.java:303)
at org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1257)
at org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1037)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:980)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:897)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:622)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:291)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:212)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:141)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:521)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1096)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:674)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1500)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1456)
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)

错误异常说明:request中存在同名的userName属性,获取失败
注:该错误会在Tomcat的server/logs/localhost.log日志中展示

三、排查问题

1、在LoginInteceptor中通过 request.setAttribute 方式添加了userName属性

public class LoginInteceptor implements HandlerInterceptor{
    @Override
    boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
	    throws Exception{
        /**......**/
	request.setAttribute("userName",'test');
	/**......**/
    }
}

2、同时在Controller中通过modelAndView.addObject 方式添加了userName属性

@RequestMapping("/myCall")
public ModelAndView myCall(ModelAndView modelAndView){
	modelAndView.setViewName("my/call");
	modelAndView.addObject("userName","test");
	return modelAndView ;
}

3、同时在Spring MVC的viewResolver解析器中配置了exposeRequestAttributes和exposeSessionAttributes值为ture

<bean id="viewResolver" class="org.springframework.web.servlet.view.velocity.VelocityLayoutViewResolver">
	/**......**/
	<property name="exposeRequestAttributes" value="true"/>
	<property name="exposeSessionAttributes" value="true"/>
	/**......**/
</bean>

exposeRequestAttributes 和 exposeSessionAttributes 设置为true的话会将request和session中的键值和值合并到modelAndView的Map参数中。

通过以上三项最终导致问题的产生

四、解决问题

方案一:修改Controller中参数名称userName,改为modelAndView.addObject("myUserName","test"),简单粗暴

方案二:在Spring MVC的viewResolver解析器配置中添加allowRequestOverride=true和allowSessionOverride=true配置,允许request和session设置的键值被覆盖,具体配置如下所示:

<bean id="viewResolver" class="org.springframework.web.servlet.view.velocity.VelocityLayoutViewResolver">
	/**......**/
	<property name="exposeRequestAttributes" value="true"/>
	<property name="allowRequestOverride" value="true"/>
	<property name="exposeSessionAttributes" value="true"/>
	<property name="allowSessionOverride" value="true"/>
	/**......**/
</bean>

注:两种方案都可以解决Cannot expose request attribute 'userName' because of an existing model object of the same name 问题

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值