链接:https://www.jianshu.com/p/7bed8cb98144
序言上篇文章先容了maven WEB 项目的搭建,基本的配置文件也都贴出来了,本日就来先容下SpringMVC的事情事理以及事情中常用的表明。为往后开拓打下坚实的根本。
正文
SpringMVC框架先容
SpringMVC便是通过DispatcherServlet将一堆组件串联起来的Web框架。
Spring MVC属于SpringFrameWork的后续产品,已经领悟在Spring Web Flow里面。Spring 框架供应了构建 Web 运用程序的全功能 MVC 模块。利用 Spring 可插入的 MVC 架构,可以选择是利用内置的 Spring Web 框架还是 Struts 这样的 Web 框架。通过策略接口,Spring 框架是高度可配置的,而且包含多种视图技能,例如 JavaServer Pages(JSP)技能、Velocity、Tiles、iText 和 POI。Spring MVC 框架并不知道利用的视图,以是不会强制您只利用 JSP 技能。
Spring MVC 分离了掌握器、模型工具、分派器以及处理程序工具的角色,这种分离让它们更随意马虎进行定制
Spring的MVC框架紧张由DispatcherServlet、处理器映射、处理器(掌握器)、视图解析器、视图组成。SpringMVC事理图
SpringMVC接口阐明
DispatcherServlet接口:
Spring供应的前端掌握器,所有的要求都有经由它来统一分发。在DispatcherServlet将要求分发给Spring Controller之前,须要借助于Spring供应的HandlerMapping定位到详细的Controller。
HandlerMapping接口:
能够完成客户要求到Controller映射。
Controller接口:
须要为并发用户处理上述要求,因此实现Controller接口时,必须担保线程安全并且可重用。
Controller将处理用户要求,这和Struts Action扮演的角色是同等的。一旦Controller处理完用户要求,则返回ModelAndView工具给DispatcherServlet前端掌握器,ModelAndView中包含了模型(Model)和视图(View)。
从宏不雅观角度考虑,DispatcherServlet是全体Web运用的掌握器;从微不雅观考虑,Controller是单个Http要求处理过程中的掌握器,而ModelAndView是Http要求过程中返回的模型(Model)和视图(View)。
ViewResolver接口:
Spring供应的视图解析器(ViewResolver)在Web运用中查找View工具,从而将相应结果渲染给客户。
SpringMVC运行事理
客户端要求提交到DispatcherServlet由DispatcherServlet掌握器查询一个或多个HandlerMapping,找到处理要求的ControllerDispatcherServlet将要求提交到ControllerController调用业务逻辑处理后,返回ModelAndViewDispatcherServlet查询一个或多个ViewResoler视图解析器,找到ModelAndView指定的视图视图卖力将结果显示到客户端DispatcherServlet是全体Spring MVC的核心。它卖力吸收HTTP要求组织折衷Spring MVC的各个组成部分。其紧张事情有以下三项:
截获符合特定格式的URL要求。初始化DispatcherServlet高下文对应的WebApplicationContext,并将其与业务层、持久化层的WebApplicationContext建立关联。初始化Spring MVC的各个组成组件,并装置到DispatcherServlet中。结合项目理解:
1.大家由上面事理也看明白了,DispatcherServlet是全体Spring MVC的核心,SpringMVC所有的要求都会通过这个前端掌握器。它配置的地方是在web.xml里面,配置如下:
<servlet> <servlet-name>springmvctouchbaidu</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring/applicationContext.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet>
配置的时候还指明了contextConfigLocation,这样就会去加载这个applicationContext.xml了。
2.事理第2点中由DispatcherServlet掌握器查询一个或多个HandlerMapping,找到处理要求的Controller。这里实在是通过在applicationContext-mvc.xml配置了扫描路径以及开启了表明驱动来实现的。
applicationContext-mvc.xml中的配置:
<context:component-scan base-package=\"大众com.tengj.demo\"大众/>
context:component-scan解释了要扫描com.tengj.demo这个包下所有的类。这里要把稳一下,大家往后开拓中有用到表明的类一定都要在这个demo包下,不然就会抛非常的。
加载了扫描路径后,还要开启表明驱动,这样才能认到代码中利用到的表明,比如@Controller这个表明。
<mvc:annotation-driven />
3.ViewResoler视图解析器对应配置里面的
<bean class=\公众org.springframework.web.servlet.view.InternalResourceViewResolver\"大众> <property name=\"大众prefix\"大众 value=\公众/WEB-INF/pages/\"大众/> <property name=\"大众suffix\"大众 value=\"大众.jsp\"大众/> </bean>
这样,当controller中方法返回的是
return \"大众index\公众;
的时候,实际是指向了/WEB-INF/pages/index.jsp这个页面。
常用到的表明
当我们利用了自动扫描+表明的办法后,就不须要在applicationContext-mvc.xml里面配置类的bean了,要引用类直接在成员变量上面加行表明,set/get方法也省了。超级方便,下面就列出常规开拓中常用的表明。
@Component
@Component
是所有受Spring 管理组件的通用形式,@Component表明可以放在类的头上,@Component不推举利用。
利用@Controller定义一个Controller掌握器
@Controller对应表现层的Bean,也便是Action,例如:
@Controllerpublic class UserController { ……}
利用@Controller表明标识UserController之后,就表示要把UserController交给Spring容器管理,在Spring容器中会存在一个名字为\"大众userController\公众的action,这个名字是根据UserController类名来取的。把稳:如果@Controller不指定其value【@Controller】,则默认的bean名字为这个类的类名首字母小写,如果指定value【@Controller(value=\"大众UserController\公众)】或者【@Controller(\公众UserController\"大众)】,则利用value作为bean的名字。
利用@Service定义一个业务层Bean
@Service对应的是业务层Bean,例如:
@Service(\"大众userService\"大众)public class UserServiceImpl implements UserService{………}
@Service(\公众userService\公众)表明是见告Spring,当Spring要创建UserServiceImpl的的实例时,bean的名字必须叫做\公众userService\"大众,这样当Action须要利用UserServiceImpl的的实例时,就可以由Spring创建好的\"大众userService\"大众,然后注入给Action:在Action只须要声明一个名字叫“userService”的变量来吸收由Spring注入的\"大众userService\公众即可,详细代码如下:
//注入userService@Resource(name=\公众userService\"大众)UserService userService;
把稳:在UserController声明的“userService”变量的类型必须是“UserServiceImpl”或者是其父类“UserService”,否则由于类型不一致而无法注入,由于UserController中的声明的“userService”变量利用了@Resource表明去标注,并且指明了其name = \"大众userService\公众,这就即是见告Spring,说我UserController要实例化一个“userService”,你Spring快点帮我实例化好,然后给我,当Spring看到userService变量上的@Resource的表明时,根据其指明的name属性可以知道,UserController中须要用到一个UserServiceImpl的实例,此时Spring就会把自己创建好的名字叫做\"大众userService\公众的UserServiceImpl的实例注入给UserController中的“userService”变量,帮助UserController完成userService的实例化,这样在UserController中就不用通过“UserService userService = new UserServiceImpl();”这种最原始的办法去实例化userService了。
如果没有Spring,那么当UserController须要利用UserServiceImpl时,必须通过“UserService userService = new UserServiceImpl();”主动去创建实例工具,但利用了Spring之后,UserController要利用UserServiceImpl时,就不用主动去创建UserServiceImpl的实例了,创建UserServiceImpl实例已经交给Spring来做了,Spring把创建好的UserServiceImpl实例给UserController,UserController拿到就可以直接用了。
UserController由原来的主动创建UserServiceImpl实例后就可以立时利用,变成了被动等待由Spring创建好UserServiceImpl实例之后再注入给UserController,UserController才能够利用。这解释UserController对“UserServiceImpl”类的“掌握权”已经被“反转”了,原来主动权在自己手上,自己要利用“UserServiceImpl”类的实例,自己主动去new一个出来立时就可以利用了,但现在自己不能主动去new“UserServiceImpl”类的实例,new“UserServiceImpl”类的实例的权力已经被Spring拿走了,只有Spring才能够new“UserServiceImpl”类的实例,而UserController只能等Spring创建好“UserServiceImpl”类的实例后,再“哀求”Spring把创建好的“UserServiceImpl”类的实例给他,这样他才能够利用“UserServiceImpl”,这便是Spring核心思想“掌握反转”,也叫“依赖注入”。
“依赖注入”也很好理解,UserController须要利用UserServiceImpl干活,那么便是对UserServiceImpl产生了依赖,Spring把Acion须要依赖的UserServiceImpl注入(也便是“给”)给UserController,这便是所谓的“依赖注入”。对UserController而言,UserController依赖什么东西,就要求Spring注入给他,对Spring而言,UserController须要什么,Spring就主动注入给他。
利用@Repository定义一个数据访问层Bean
@Repository对应数据访问层Bean ,例如:
@Repository(value=\"大众userDao\"大众) public class UserDao { ……… }
@Repository(value=\"大众userDao\公众)表明是见告Spring,让Spring创建一个名字叫“userDao”的UserDao实例。
当Service须要利用Spring创建的名字叫“userDao”的UserDao实例时,就可以利用@Resource(name = \公众userDao\"大众)表明见告Spring,Spring把创建好的userDao注入给Service即可。
// 注入userDao@Resource(name = \"大众userDao\"大众)private UserDao userDao;
@Resource跟@Autowired比较
上面先容中Controller中注入userService或者 Service层里面注入dao都是用@Resource标签,实在也可以利用@Autowired来替代,但是建议利用@Resource。下面说说这2者的差异:
@Autowired和@Resource都可以用来装置bean,都可以写在字段上,或者方法上。@Autowired属于Spring的;@Resource为JSR-250标准的注释,属于J2EE的。@Autowired默认按类型装置,默认情形下必须哀求依赖工具必须存在,如果要许可null值,可以设置它的required属性为false,例如:@Autowired(required=false) ,如果我们想利用名称装置可以结合@Qualifier表明进行利用 例如:@Autowired@Qualifier(\"大众baseDao\"大众)private BaseDao baseDao;@Resource,默认按照名称进行装置,名称可以通过name属性进行指定,如果没有指定name属性,当表明写在字段上时,默认取字段名进行安装名称查找,如果表明写在setter方法上默认取属性名进行装置。当找不到与名称匹配的bean时才按照类型进行装置。但是须要把稳的是,如果name属性一旦指定,就只会按照名称进行装置。 例如:
@Resource(name=\"大众baseDao\"大众)private BaseDao baseDao;
5.之以是推举利用@Resource,由于这个表明是属于J2EE的,减少了与spring的耦合。这样代码看起就比较优雅。
利用@RequestMapping来映射Request要求与处理器
SpringMVC利用@RequestMapping表明为掌握器制订可以处理哪些URL要求
在掌握器的类定义及方法定义处都可以标注
类定义处:供应初步的要求映射信息。相对付WEB运用的根目录方法处:供应进一步的细分映射信息。相对付类定义处的URL,若类定义处未标注@RequestMapping,则方法处标记的URL相对付WEB运用的根目录。 举个列子:@Controller@RequestMapping(value=\"大众/test\"大众)public class UserController{ @RequestMapping(value=\"大众/view\公众,method = RequestMethod.GET) public String index(){ System.out.println(\"大众进来了\"大众); return \"大众index\"大众; }}
上面这样,只要地址访问 就能进入这个index方法了,个中利用method属性来指定要求是get还是post。
(一)利用带占位符URI@PathVariable
带占位符的URL是Spring3.0新增的功能,该功能在SpringMVC向REST目标挺进发展过程中具有里程碑的意义
通过@PathVariable可以将URL中占位符参数绑定到掌握器处理方法的入参中:URL中的{xxx}占位符可以通过@PathVariable(\"大众xxx\"大众)绑定到操作方法入参中。
例子:
/ @RequestMapping 可以来映射URL中的占位符到目标方法的参数中 @param id @return /@RequestMapping(\公众/testPathVariable/{id}\"大众)public String testPathVariable(@PathVariable(\公众id\公众) String id){ System.out.println(\"大众testPathVariable id=\"大众+id); return \公众index\"大众;}
(二)利用@RequestParam绑定HttpServletRequest要求参数到掌握器方法参数
@RequestMapping ( \公众requestParam\公众 ) public String testRequestParam( @RequestParam(required=false) String name, @RequestParam ( \"大众age\"大众 ) int age) { return \公众requestParam\"大众 ;}
在上面代码中利用@RequestParam 从HttpServletRequest 中绑定了参数name 到掌握器方法参数name ,绑定了参数age 到掌握器方法参数age 。值得把稳的是和@PathVariable 一样,当你没有明确指定从request 中取哪个参数时,Spring 在代码是debug 编译的情形下会默认取更方法参数同名的参数,如果不是debug 编译的就会报错。此外,当须要从request 中绑定的参数和方法的参数名不相同的时候,也须要在@RequestParam 中明确指出是要绑定哪个参数。在上面的代码中如果我访问/requestParam.do?name=hello&age=1 则Spring 将会把request要求参数name 的值hello 赋给对应的处理方法参数name ,把参数age 的值1 赋给对应的处理方法参数age 。
在@RequestParam 中除了指定绑定哪个参数的属性value 之外,还有一个属性required ,它表示所指定的参数是否必须在request 属性中存在,默认是true ,表示必须存在,当不存在时就会报错。在上面代码中我们指定了参数name 的required 的属性为false ,而没有指定age 的required 属性,这时候如果我们访问/requestParam.do而没有通报参数的时候,系统就会抛出非常,由于age 参数是必须存在的,而我们没有指定。而如果我们访问/requestParam.do?age=1 的时候就可以正常访问,由于我们通报了必须的参数age ,而参数name 是非必须的,不通报也可以。
(三)利用@CookieValue绑定cookie的值到Controller方法参数
@RequestMapping ( \公众cookieValue\"大众 ) public String testCookieValue( @CookieValue ( \公众hello\"大众 ) String cookieValue, @CookieValue String hello) { System. out .println(cookieValue + \"大众-----------\"大众 + hello); return \"大众cookieValue\"大众 ; }
在上面的代码中我们利用@CookieValue 绑定了cookie 的值到方法参数上。上面一共绑定了两个参数,一个是明确指定要绑定的是名称为hello 的cookie 的值,一个是没有指定。利用没有指定的形式的规则和@PathVariable、@RequestParam 的规则是一样的,即在debug 编译模式下将自动获取跟方法参数名同名的cookie 值。
(四)利用@RequestHeader表明绑定 HttpServletRequest头信息到Controller方法参数
@RequestMapping ( \公众testRequestHeader\"大众 )public String testRequestHeader( @RequestHeader ( \公众Host\"大众 ) String hostAddr, @RequestHeader String Host, @RequestHeader String host ) { System. out .println(hostAddr + \"大众-----\公众 + Host + \"大众-----\公众 + host ); return \"大众requestHeader\公众 ;}
在上面的代码中我们利用了 @RequestHeader 绑定了 HttpServletRequest 要求头 host 到Controller 的方法参数。上面方法的三个参数都将会授予同一个值,由此我们可以知道在绑定要求头参数到方法参数的时候规则和 @PathVariable 、 @RequestParam 以及 @CookieValue 是一样的,即没有指定绑定哪个参数到方法参数的时候,在 debug 编译模式下将利用方法参数名作为须要绑定的参数。但是有一点 @RequestHeader 跟其余三种绑定办法是不一样的,那便是在利用 @RequestHeader 的时候是大小写不敏感的,即 @RequestHeader(“Host”) 和 @RequestHeader(“host”) 绑定的都是 Host 头信息。记住在 @PathVariable 、 @RequestParam 和 @CookieValue 中都是大小写敏感的。
(五)@RequestMapping的一些高等运用
在RequestMapping 中除了指定要求路径value 属性外,还有其他的属性可以指定,如params 、method 和headers 。这样属性都可以用于缩小要求的映射范围。
1.params属性
@RequestMapping (value= \"大众testParams\公众 , params={ \"大众param1=value1\"大众 , \"大众param2\公众 , \"大众!param3\"大众 }) public String testParams() { System. out .println( \"大众test Params...........\"大众 ); return \"大众testParams\公众 ; }
在上面的代码中我们用@RequestMapping 的params 属性指定了三个参数,这些参数都是针对要求参数而言的,它们分别表示参数param1 的值必须即是value1 ,参数param2 必须存在,值无所谓,参数param3 必须不存在,只有当要求/ 并且知足指定的三个参数条件的时候才能访问到该方法。以是当要求/ 的时候能够精确访问到该testParams 方法,当要求/ 的时候就不能够正常的访问到该方法,由于在@RequestMapping 的params 参数里面指定了参数param3 是不能存在的。
2.method属性
@RequestMapping (value= \公众testMethod\"大众 , method={RequestMethod. GET , RequestMethod. DELETE }) public String testMethod() { return \"大众method\"大众 ; }
在上面的代码中就利用method 参数限定了以GET 或DELETE 方法要求/testMethod.do 的时候才能访问到该Controller 的testMethod 方法。
3.headers属性
@RequestMapping (value= \"大众testHeaders\"大众 , headers={ \"大众host=localhost\"大众 , \"大众Accept\"大众 }) public String testHeaders() { return \"大众headers\"大众 ; }
headers 属性的用法和功能与params 属性相似。在上面的代码中当要求/testHeaders.do 的时候只有当要求头包含Accept 信息,且要求的host 为localhost 的时候才能精确的访问到testHeaders 方法。
(六)以@RequestMapping标记的处理器方法支持的方法参数和返回类型
1. 支持的方法参数类型
HttpServlet 工具,紧张包括HttpServletRequest 、HttpServletResponse 和HttpSession 工具。 这些参数Spring 在调用处理器方法的时候会自动给它们赋值,以是当在处理器方法中须要利用到这些工具的时候,可以直接在方法上给定一个方法参数的申明,然后在方法体里面直接用就可以了。但是有一点须要把稳的是在利用HttpSession 工具的时候,如果此时HttpSession 工具还没有建立起来的话就会有问题。Spring 自己的WebRequest 工具。 利用该工具可以访问到存放在HttpServletRequest 和HttpSession 中的属性值。InputStream 、OutputStream 、Reader 和Writer 。 InputStream 和Reader 是针对HttpServletRequest 而言的,可以从里面取数据;OutputStream 和Writer 是针对HttpServletResponse 而言的,可以往里面写数据。利用@PathVariable 、@RequestParam 、@CookieValue 和@RequestHeader 标记的参数。利用@ModelAttribute 标记的参数。java.util.Map 、Spring 封装的Model 和ModelMap 。 这些都可以用来封装模型数据,用来给视图做展示。实体类。 可以用来吸收上传的参数。Spring 封装的MultipartFile 。 用来吸收上传文件的。Spring 封装的Errors 和BindingResult 工具。 这两个工具参数必须紧接在须要验证的实体工具参数之后,它里面包含了实体工具的验证结果。2. 支持的返回类型
一个包含模型和视图的ModelAndView 工具。一个模型工具,这紧张包括Spring 封装好的Model 和ModelMap ,以及java.util.Map ,当没有视图返回的时候视图名称将由RequestToViewNameTranslator 来决定。一个View 工具。这个时候如果在渲染视图的过程中模型的话就可以给处理器方法定义一个模型参数,然后在方法体里面往模型中添加值。一个String 字符串。这每每代表的是一个视图名称。这个时候如果须要在渲染视图的过程中须要模型的话就可以给处理器方法一个模型参数,然后在方法体里面往模型中添加值就可以了。返回值是void 。这种情形一样平常是我们直接把返回结果写到HttpServletResponse 中了,如果没有写的话,那么Spring 将会利用RequestToViewNameTranslator 来返回一个对应的视图名称。如果视图中须要模型的话,处理方法与返回字符串的情形相同。如果处理器方法被表明@ResponseBody 标记的话,那么处理器方法的任何返回类型都会通过HttpMessageConverters 转换之后写到HttpServletResponse 中,而不会像上面的那些情形一样当做视图或者模型来处理。除以上几种情形之外的其他任何返回类型都会被当做模型中的一个属性来处理,而返回的视图还是由RequestToViewNameTranslator 来决定,添加到模型中的属性名称可以在该方法上用@ModelAttribute(“attributeName”) 来定义,否则将利用返回类型的类名称的首字母小写形式来表示。利用@ModelAttribute 标记的方法会在@RequestMapping 标记的方法实行之前实行。(七)利用 @ModelAttribute 和 @SessionAttributes 通报和保存数据
SpringMVC 支持利用 @ModelAttribute 和 @SessionAttributes 在不同的模型和掌握器之间共享数据。 @ModelAttribute 紧张有两种利用办法,一种是标注在方法上,一种是标注在 Controller 方法参数上。
当 @ModelAttribute 标记在方法上的时候,该方法将在处理器方法实行之前实行,然后把返回的工具存放在 session 或模型属性中,属性名称可以利用 @ModelAttribute(“attributeName”) 在标记方法的时候指定,若未指定,则利用返回类型的类名称(首字母小写)作为属性名称。关于 @ModelAttribute 标记在方法上时对应的属性是存放在 session 中还是存放在模型中,我们来做一个实验,看下面一段代码。
@Controller@RequestMapping ( \公众/myTest\"大众 )public class MyController { @ModelAttribute ( \公众hello\"大众 ) public String getModel() { System. out .println( \"大众-------------Hello---------\"大众 ); return \"大众world\"大众 ; } @ModelAttribute ( \公众intValue\公众 ) public int getInteger() { System. out .println( \"大众-------------intValue---------------\"大众 ); return 10; } @RequestMapping ( \"大众sayHello\"大众 ) public void sayHello( @ModelAttribute ( \公众hello\"大众 ) String hello, @ModelAttribute ( \公众intValue\"大众 ) int num, @ModelAttribute ( \"大众user2\"大众 ) User user, Writer writer, HttpSession session) throws IOException { writer.write( \"大众Hello \公众 + hello + \公众 , Hello \"大众 + user.getUsername() + num); writer.write( \公众\r\"大众 ); Enumeration enume = session.getAttributeNames(); while (enume.hasMoreElements()) writer.write(enume.nextElement() + \公众\r\"大众 ); } @ModelAttribute ( \"大众user2\"大众 ) public User getUser() { System. out .println( \公众---------getUser-------------\公众 ); return new User(3, \公众user2\"大众 ); }}
当我们要求 /myTest/ 的时候利用 @ModelAttribute 标记的方法会先实行,然后把它们返回的工具存放到模型中。终极访问到 sayHello 方法的时候,利用 @ModelAttribute 标记的方法参数都能被精确的注入值。实行结果如下所示:
Hello world,Hello user210
由实行结果我们可以看出来,此时 session 中没有包含任何属性,也便是说上面的那些工具都是存放在模型属性中,而不是存放在 session 属性中。那要如何才能存放在 session 属性中呢?这个时候我们先引入一个新的观点 @SessionAttributes ,它的用法会在讲完 @ModelAttribute 之后先容,这里我们就先拿来用一下。我们在 MyController 类上加上 @SessionAttributes 属性标记哪些是须要存放到 session 中的。看下面的代码:
@Controller@RequestMapping ( \"大众/myTest\"大众 )@SessionAttributes (value={ \"大众intValue\"大众 , \公众stringValue\公众 }, types={User. class })public class MyController { @ModelAttribute ( \"大众hello\"大众 ) public String getModel() { System. out .println( \"大众-------------Hello---------\公众 ); return \"大众world\公众 ; } @ModelAttribute ( \公众intValue\"大众 ) public int getInteger() { System. out .println( \"大众-------------intValue---------------\"大众 ); return 10; } @RequestMapping ( \公众sayHello\"大众 ) public void sayHello(Map<String, Object> map, @ModelAttribute ( \公众hello\公众 ) String hello, @ModelAttribute ( \"大众intValue\"大众 ) int num, @ModelAttribute ( \"大众user2\"大众 ) User user, Writer writer, HttpServletRequest request) throws IOException { map.put( \"大众stringValue\公众 , \"大众String\公众 ); writer.write( \公众Hello \公众 + hello + \公众 , Hello \"大众 + user.getUsername() + num); writer.write( \公众\r\"大众 ); HttpSession session = request.getSession(); Enumeration enume = session.getAttributeNames(); while (enume.hasMoreElements()) writer.write(enume.nextElement() + \"大众\r\"大众 ); System. out .println(session); } @ModelAttribute ( \"大众user2\"大众 ) public User getUser() { System. out .println( \"大众---------getUser-------------\"大众 ); return new User(3, \"大众user2\"大众 ); }}
在上面代码中我们指定了属性为 intValue 或 stringValue 或者类型为 User 的都会放到 Session中,利用上面的代码当我们访问 /myTest/sayHello.do 的时候,结果如下:
Hello world,Hello user210
仍旧没有打印出任何 session 属性,这是怎么回事呢?怎么定义了把模型中属性名为 intValue 的工具和类型为 User 的工具存到 session 中,而实际上没有加进去呢?难道我们错啦?我们当然没有错,只是在第一次访问 /myTest/ 的时候 @SessionAttributes 定义了须要存放到 session 中的属性,而且这个模型中也有对应的属性,但是这个时候还没有加到 session 中,以是 session 中不会有任何属性,等处理器方法实行完成后 Spring 才会把模型中对应的属性添加到 session 中。以是当要求第二次的时候就会涌现如下结果:
Hello world,Hello user210user2intValuestringValue
当 @ModelAttribute 标记在处理器方法参数上的时候,表示该参数的值将从模型或者 Session 中取对应名称的属性值,该名称可以通过 @ModelAttribute(“attributeName”) 来指定,若未指定,则利用参数类型的类名称(首字母小写)作为属性名称。
总结到此,SpringMVC的事理以及常用表明就先容的差不多了,平时开拓这些就够用了,如果你还想深入学习SpringMVC知识点,可以关注我个人"大众年夜众号,里面资源贴有全套的视频教程。
参考