@Controller用于标记一个类,使用它标记的类就是一个Spring MVC Controller对象,即一个控制器类。Spring使用扫描机制查找应用程序中所有基于注解的控制器类。分发处理器会扫描使用了该注解的类的方法,并检测该方法是否使用了@RequestMapping注解,而使用@RequestMapping注解的方法才是真正处理请求的处理器。为了保证Spring能找到控制器,需要完成两件事情:
配置文件如下所示:
示例:
springmvc-config.xml
/
.jsp
视图解析器中配置的prefix属性表示视图的前缀,suffix表示视图的前缀,返回的视图字符串是“helloWorld”,经过视图解析器之后,则视图的完整路径为“/helloWorld.jsp”(idea IDE环境下)。需要注意的是,此处没有配置之处理映射器和处理器适配器,当用户没有配置这两项时,Spring会使用默认的处理映射器和处理器适配器处理请求。
HelloWorldController.java
package org.fkit.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class HelloWorldController {
@RequestMapping("/helloWorld")
public String helloWorld(Model model){
model.addAttribute("message","Hello World!");
return "helloWorld";
}
}
web.xml
springmvc
org.springframework.web.servlet.DispatcherServlet
contextConfigLocation
/WEB-INF/springmvc-config.xml
1
springmvc
/
welcome.jsp
helloWorld.jsp
<%--
Created by IntelliJ IDEA.
User: Jeanne d'Arc
Date: 2018/7/29
Time: 18:14
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
测试@Controller注解
${requestScope.message}
Spring MVC中用于参数绑定的注解有很多,都在org.springframework.web.bind.annotation包中,根据他们处理的request的不同内容部分可以分为四类(主要讲解常用内容):
org.springframework.web.bind.annotation.RequestMapping注解类型指示Spring用那一个类或方法来处理请求动作,该注解可用于类或方法。
@RequestMapping可以用于注释一个控制器类,在这种情况下,所有方法都将映射为相对于类级别的请求,表示该控制器处理的所有请求都被映射到value属性所指示的路径下,示例代码如下:
@Controller
@RequestMapping(value="/user")
public class UserController{
@RequestMapping(value="/register")
public String register(){
return "register";
}
@RequestMapping(value="/login")
public String login(){
return "login";
}
}
由于UserController类中加入了value="/user"的@RequestMapping注解,因此所有相关路径都要加上"/user",此时方法被映射到如下请求URL:
http://localhost:8080/user/register
http://localhost:8080/user/login
属性 | 类型 | 是否必要 | 说明 |
value | String[] | 否 | 用于将指定请求的实际地址映射到方法上 |
name | String | 否 | 给映射地址制定一个别名 |
method | RequestMethod[] | 否 | 映射指定请求的方法类型,包括GET、POST、HEAD、OPTIONS、PUT、PATCH、DELETE、TRACE |
consumes | String[] | 否 | 指定处理请求的提交内容类型(Content-Type),例如application/json、text/html等 |
produces | String[] | 否 | 指定返回的内容类型,返回的内容类型必须是request请求头(Accept)中所包含的类型 |
params | String[] | 否 | 指定request中必须包含某些参数时,才让该方法处理 |
headers | String[] | 否 | 指定request中必须包含某些指定的header值,才能让该方法处理请求 |
Path | String[] | 否 | 在Servlet环境中只有:uri路径映射(例如"/myPath.do")。也支持如ant的基于路径模式(例如"/myPath/*,")。在方法层面上,支持相对路径(例如"edit.do") |
@RequestMapping注解支持的常用属性示例
@RequestMapping(value="/hello")
public ModelAndView hello(){
return ...;
}
//将hello映射到hello方法上,使用如下URL访问应用时将由hello方法进行处理:
http://localhost:8080/context/hello
//当value是空字符串时:
http://localhost:8080/context
@RequestMapping(value="/hello",method=RequestMethod.POST)
//只支持POST请求
@RequestMapping(value="/hello",method={RequestMethod.POST,RequestMethod.GET})
//支持多个HTTP请求方式
//如果没有指定,则请求处理方法可以处理任意的HTTP请求方式
consumes属性
@RequestMapping(value="/hello",method=RequestMethod.POST,consumes="application/json")
//仅处理request Content-Type为“application/json”类型的请求
produces属性
@RequestMapping(value="/hello",method=RequestMethod.POST,produces="application/json")
//仅处理request请求头Accept投中包含“application/json”的请求,同时指明了返回的内容类型为“application/json”
params属性
@RequestMapping(value="/hello",method=RequestMethod.POST,params="myParams=myValue")
//仅处理其中名为“myParams”、值为“myValue”的请求
HttpServletRequest、HttpServletResponse、HttpSesson、WebRequest或NativeWebRequest、Locale、Reader、Writer、Principal、HttpEntity>、Map、Model、ModelMap、RedirectAttributes、Errors、BindingResult、SessionStatus、UriComponentsBuilder、@PathVariable、@MatrixVariable、@RequestParam、@RequestHeader、@RequestBody、@RequestPart
其中最重要的是Model类型。这不是一个Servlet API类型,而是一个Spring MVC类型。其中包含了Map对象用来存储数据。如果方法中添加了Model参数,则每次调用请求处理方法时,Spring MVC都会创建Model对象,并将其作为参数传递给方法。
ModelAndView、Model、Map
对于MVC框架,控制器(Controller)执行业务逻辑,用于产生模型数据(Model),而视图(View)则用于渲染模型数据。
如何将模型数据传递给视图是Spring MVC框架的一项重要工作,Spring MVC提供了多种途径输出模型数据,如:
Spring MVC在内部使用了一个org.springframework.ui.Model接口存储模型数据,它的功能类似骄傲va.util.Map接口,但是比Map易于使用。org.springframework.ui.ModelMap接口实现了Map接口。
Spring MVC在调用处理方法之前会创建一个隐含的模型对象,作为模型数据的存储容器。如果处理方法的参数为Model或ModelMap类型,则Spring MVC会将隐含模型的引用传递给这些参数。在处理方法内部,开发者就可以通过这个参数对象访问模型中的所有数据,也可以像模型中添加新的属性数据。
在处理方法中,Model和ModelMap对象都可以使用如下方法添加模型数据:
addObject(Stringh attributeName,Object attributeValue)
2018.7.31
org.springframework.web.bind.annotation.RequestParam注解类型用于将指定的请求参数赋值给方法中的形参。
属性 | 类型 | 是否必要 | 说明 |
---|---|---|---|
name | String | 否 | 指定请求头绑定的名称 |
value | String | 否 | name属性的别名 |
required | String | 否 | 指示参数是否必须绑定 |
defaultValue | String | 否 | 如果没有传递参数而使用的默认值 |
请求处理方法参数的可选类型为Java基本数据类型和String。示例代码如下:
@RequestMapping(value="/login")
public ModelAndView login(@RequestParam("loginname") String loginname,@RequestParam("password") String password){
return ...;
}
假设请求如下:
http://localhost:8080/context/login?loginname=jack&password=123456
以上代码会被请求中的loginname参数的值“jack”付给loginname变量,password参数的值“123456”赋给password变量。
@RequestParam还有如下写法:
@RequestParam(value="loginname",required=true,defaultValue=admin)
其中required参数不是必须的,默认值为true。
org.springframework.web.bind.annotation.PathVariable注解类型可以非常方便地获得请求URL中的动态参数。@PathVariable注解只支持一个属性value,类型为String,表示绑定的名称,如果省略则默认绑定同名参数。示例代码如下:
@RequestMapping(value="/pathVariableTest/{userId}")
public void pathVariableTest(@PathVariable Integer userId)
加入请求的URL为“http://localhost:8080/DataBindingTest/pathVariable/1”,则自动将URL中模板变量{userId}绑定到通过@ParhVariable注解的同名参数上,即userId变量将被赋值为1。
2018.8.1
org.springframework.web.bind.annotation.RequestHeader注解类型用于将请求的头信息数据映射到功能处理方法的参数上。
属性 | 类型 | 是否必要 | 说明 |
---|---|---|---|
name | String | 否 | 指定请求头绑定的名称 |
value |
String | 否 | name属性的别名 |
required | boolean | 否 | 指示参数是否必须绑定 |
defaultValue | String | 否 | 如果没有传递参数而使用的默认值 |
@RequestHeader注解示例代码如下:
@RequestMapping(value="/requestHeaderTest")
public void requestHeaderTest(@RequestHeader("User-Agent") String userAgent,@RequestHeader(value="Accept") String[] accepts)
以上配置自动将请求头“User-Agent”的值赋到userAgent变量上,并将“Accept”请求头的值赋到accepts上。
org.springframework.web.bind.annotation.CookieValue注解类型用于将请求的Cookie数据印书馆河道功能处理方法的参数上。
属性 | 类型 | 是否必要 | 说明 |
---|---|---|---|
name | String | 否 | 指定请求头绑定的名称 |
value | String | 否 | 那么属性的别名 |
required | boolean | 否 | 只是参数是否必须绑定 |
defaultValue | String | 否 | 如果没有传递参数而使用的默认值 |
@CookieValue注解示例代码如下:
@RequestMapping(value="/cookieValueTest")
public void cookieValueTest(@CookieValue(value="JSESSIONID",defaultValue="") String sessionId)
以上配置会自动将JSESSIONID值设置到sessionId参数上,defaultValue表示Cookie中没有JSESSION时默认为空。
org.springframework.web.bind.annotation.SessionAttributes注解类型允许我们有选择地指定Model中的哪些属性需要转存到HttpSession对象当中。
属性 | 类型 | 是否必要 | 说明 |
---|---|---|---|
names | String[] | 否 | Model中属性的名称,即存储在HttpSession当中的属性 |
value | String[] | 否 | names属性的别名 |
types | Class>[] | 否 | 指示参数是否必须绑定 |
@SessionAttributes只能声明在类上,不能声明在方法上。
org.springframework.web.bind.annotation.ModelAttribute注解类型将请求参数绑定到Model对象。
@ModelAttribute注解只支持一个属性value,类型为String,表示绑定的水星名称。
被@ModelAttribute注释的方法会在Controller每个方法执行前被执行,因此在一个Controller映射到多个URL时,要谨慎使用。
@ModelAttribute注解的使用方式:
HttpMessageConverter
DispatcherServlet默认已经装配了RequestMappingHandlerAdapter作为Handler组建的实现类,即HttpMessageConverter由RequestMappingHandlerAdapter使用,将请求信息转换为对象,或将对象转换为响应信息。
HttpMessageConverter
Spring为HttpMessageConverter
RequestMappingHandlerAdapter默认已经装配了以下的HttpMessageConverter:
如果需要装配其他类型的HttpMessageConverte,则可以在Spring的Web容器的上下文中自定义一个RequestMappingHandlerAdapter,如下所示:
//无法使用,会报错,可能不是用于此处,Spring5.0.7实践。
备注:书中第二个Converter本来是XmlAwareFormHttpMessageConverter,实际实践时使用的Spring版本是Spring5.0.7,找不到该Converter,Spring4.1.5中该Converter可以找到,但是已经被添加中划线。Spring5.0.7中含有一个AbstractXmlHttpMessageConverter,但是添加后报错“abstract class not allowed for non-abstract bean”,使用方法不明。
如果在Spring Web容器中显式定义了一个RequestMappingHandlerAdapter,则Spring MVC的RequestMappingHandlerAdapter默认装配的HttpMessageConverter将不再起作用。
Spring MVC提供了处理JSON格式请求/响应的HttpMessageConverter:
因此只需要在Spring Web容器中为RequestMappingHandlerAdapter装配处理JSON的HttpMessageConverter,并在交互过程中通过请求的Accept指定MIME类型,Spring MVC就可以使服务端的处理方法和客户端JSON格式的消息进行通信了,开发者几乎无须关心通信层数据格式的问题,可以将精力集中到业务处理上面。
org.springframework.web.bind.annotation.RequestBody注解用于读取Request请求的body部分数据,使用系统默认配置的HttpMessageConverter进行解析,然后把相应的数据绑定到Controller中方法的参数上。
当前台页面使用GET或POST方式提交数据时,数据编码格式由请求头的ContentType指定。可以分为以下几种情况:
在实际开发工作中使用@RequestBody注解可以很方便地接受JSON格式的数据,并将其转换成对应地数据类型。
Spring的官方文档说明,Spring MVC默认使用MappingJackson2HttpMessageConverter转换JSON格式的数据,Jackson开源类包可以非常轻松地将Java对象转换成json对象和xml文档,同样也可以将java对象、xml文档转换成java对象。
Spring MVC提供了处理XML格式请求/响应地HttpMessageConverter,如Jaxb2RootElementHttpMessageConverter通过JAXB2读写XML消息,并将请求消息转换到注解XmlRootElement和XmlType作用的类中。
因此只需要在Spring Web容器中为RequestMappingHandlerAdapter装配处理XML的HttpMessageConverter,并在交互过程中通过请求的Accept指定MIME类型,Spring MVC就可以使服务端的处理方法和客户端XML格式的消息进行通信了,开发者几乎无须关心通信层数据格式的问题,可以将精力集中到业务处理上面。
在Spring官方文档中,Spring MVC默认使用Jaxb2RootElementHttpMessageConverter转换XML格式的数据,JAXB(Java Architecture for XML Binding)可以很方便地生成XML,也能够很方便地生成JSON,这样一来可以更好地在XML和JSON之间进行转换。
JAXB是一个业界的标砖,是一项可以根据XML Schema产生Java类的技术。在该过程中,JAXB提供了将XML实力文档反向生成Java对象地方法,并能够将Java对象地内容重新写到XML实例文档中,从而使得Java开发作者在Java应用程序中能够很方便地处理XML数据。
JAXB常用的注解包括:@XmlRootElement、@XmlElement等。
2018.8.2
Home Sweet Home—YUKI
世界既不白也不黑,而是一道精致的灰。