Spring4MVC之SessionAttributes注解引发的异常

 

异常消息

 

HTTP Status 500 - Session attribute 'employee' required - not found in session

type Exception report

message Session attribute 'employee' required - not found in session

description The server encountered an internal error that prevented it from fulfilling this request.

exception

org.springframework.web.HttpSessionRequiredException: Session attribute 'employee' required - not found in session
	org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter$ServletHandlerMethodInvoker.raiseSessionRequiredException(AnnotationMethodHandlerAdapter.java:791)
	org.springframework.web.bind.annotation.support.HandlerMethodInvoker.resolveModelAttribute(HandlerMethodInvoker.java:766)
	org.springframework.web.bind.annotation.support.HandlerMethodInvoker.resolveHandlerArguments(HandlerMethodInvoker.java:363)
	org.springframework.web.bind.annotation.support.HandlerMethodInvoker.invokeHandlerMethod(HandlerMethodInvoker.java:170)
	org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:446)
	org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.java:434)
	org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:945)
	org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:876)
	org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:931)
	org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:833)
	javax.servlet.http.HttpServlet.service(HttpServlet.java:646)
	org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:807)
	javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
	org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
	org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77)
	org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:108)

 

note The full stack trace of the root cause is available in the Apache Tomcat/7.0.55 logs.

 

 

异常原因

 

当使用SessionAttributes注解缓存对象时,handler处理类的处理方法中存在对应的入参时,SpringMVC在implicitModel中找不到对应的对象时,SpringMVC会去判断是否使用SessionAttributes注解缓存了对应的类。如果缓存了,就会去查找对应的对象,如果找不到,就会抛出此异常。

 

源码:

 

private WebDataBinder resolveModelAttribute(String attrName, MethodParameter methodParam,
			ExtendedModelMap implicitModel, NativeWebRequest webRequest, Object handler) throws Exception {

		// Bind request parameter onto object...
		String name = attrName;
		if ("".equals(name)) {
			name = Conventions.getVariableNameForParameter(methodParam);
		}
		Class<?> paramType = methodParam.getParameterType();
		Object bindObject;
		if (implicitModel.containsKey(name)) {
			bindObject = implicitModel.get(name);
		}
		else if (this.methodResolver.isSessionAttribute(name, paramType)) {
			bindObject = this.sessionAttributeStore.retrieveAttribute(webRequest, name);
			if (bindObject == null) {
				raiseSessionRequiredException("Session attribute '" + name + "' required - not found in session");
			}
		}
		else {
			bindObject = BeanUtils.instantiateClass(paramType);
		}
		WebDataBinder binder = createBinder(webRequest, bindObject, name);
		initBinder(handler, name, binder, webRequest);
		return binder;
	}

 

 

解决方法

 

1. 方法入参的@ModelAttribute注解的value值不要与@SessionAttributes注解的value值一致。

 

@SessionAttributes(value={"employee"})
@Controller
@RequestMapping("/emp")
public class EmployeeController {

@RequestMapping("/save")
	public ModelAndView save(@ModelAttribute(value="abc") Employee emp) throws Exception
	{
		
		System.out.println(emp);
    
		if(emp.getId() == null)
		{
			Date date = new Date();
			SimpleDateFormat format = new SimpleDateFormat("yyyy-mm-dd");
			emp.setHiredate(format.format(date));
			employeeDao.addEmployee(emp);
		}
		else
		{
			//更新数据,实际上丢失表单中没有的数据:no,hiredate
			employeeDao.updateEmployeeById(emp);
		}
		
		ModelAndView modelAndView = new ModelAndView();
		
		List<Employee> emps = employeeDao.getAllEmployees();
		
		modelAndView.addObject("emps", emps);
		modelAndView.setViewName(VIEW_NAME_LIST);
		return modelAndView;
	}	
}

 

2. 如果方法中不使用注解@ModelAttribute改变value值的默认值(类名首字母小写),而且@SessionAttributes注解的value值又习惯性使用类名首字母小写,则只能添加@ModelAttribute标注的方法,且在map中添加对应的对象。

 

	@ModelAttribute
	public void getEmployee(@RequestParam(value="id",required=false) Integer id,Map<String,Object> map) throws Exception
	{
		System.out.println("从数据库中获取一个对象: " + id);
		System.out.println("-----------getEmployee-------------");
		//从数据库中获取对象
		if(id != null)
		{
			Employee emp = employeeDao.getById(id);
			map.put("employee", emp);
		}
	}

 

 

 

你可能感兴趣的:(Spring4MVC之SessionAttributes注解引发的异常)