SpringMVC——请求映射

一、请求的匹配和校验
 前端请求:

<a href="${pageContext.request.contextPath }/carryParams?age=11&name=zhang">
	To Success Page 
</a>

 处理方法:SpringMVC可以限制请求参数以及请求参数的值

@RequestMapping(value = "/carryParams", params = { "age", "name=wang" }, method = RequestMethod.GET)
public String carryParams(Integer age, String name) {
	System.out.println(age + "-" + name);
	return "success";
}

Tip
  1️⃣@RequestMapping的params属性跟参数的注入并没有关系,参数值的注入是根据参数名来的(在不加@RequestParam指定请求参数名时会注入同名参数的值,否则会注入@RequestParam指定的参数值),params属性的作用是要求该方法处理的请求必须携带哪些参数以及这些参数需要满足什么条件,如果请求参数不符合params属性的要求,则会匹配不到处理方法(No matching handler method found for servlet request …)报404错误,另外并不是params中的参数一定要在方法的形参列表中出现。简单地说,params中的参数是请求必带的参数,而且参数的值要符合params的要求,比如示例中要求请求该方法时必须携带age和name两个参数,且name的值必须是wang(参数中比较相等或不相等使用=和!=)
  2️⃣method的类型有GET、POST、DELETE、PUT等
  3️⃣同一个处理方法可以处理多个请求,示例如下:前端发送的/test和/test1请求都由该方法处理,这里也配置了params属性,虽然方法的入参中并没有参数,但只要params中配置了参数则请求时就必须携带指定的参数,且值要符合要求

@RequestMapping(value = {"/test","/test1"},params={"age","tel!=110"})
public String test() {
	System.out.println("Hello springmvc");
	return "success";
}

 除了对请求参数进行限制之外,还可以对请求头进行限制:要求请求的host必须是localhost:8080,这时使用127.0.0.1:8080就请求不通了

	@RequestMapping(value = "/carryParams", headers = { "Host=localhost:8080" }, method = RequestMethod.GET)
	public String carryParams(Integer age, String name) {
		System.out.println(age + "-" + name);
		return "success";
	} 

 params和headers还支持简单的表达式,以params为例,当params的值是params={“age”,"!name",“gender=1”,“email!=lgs@qq.com”}时,要求请求参数中必须包含age、gender、email且一定不能含有name参数,同时gender的值必须是1,email的值必须不是lgs@qq.com

二、请求路径映射
 1、Ant风格(通配符式)的url映射:通配符可以混用

通配符说明
?一个?匹配一个字符
*一个*匹配零个或多个字符
**匹配零级或多级路径

  示例:
   ①、一个?表示一个占位符:示例中的处理方法只能处理类似于/testStyle/ab或者/testStyle/dy等后面只有两个字符的请求访问,一个?代表一个字符

@RequestMapping(value="/testStyle/??",method=RequestMethod.GET)
public String antStyle(){
    return "success";
}  

   ②*代表零个或多个字符:表示该方法只能处理类似/testStyle/a或/testStyle/fesbwcs/a这类请求

@RequestMapping(value="/testStyle/*/a",method=RequestMethod.GET)
public String antStyle(){
    return "success";
}  

   ③**表示多级路径:表示该处理方法可以处理以/testStyle/开头并且最后一级只有一个字符的请求

@RequestMapping(value="/testStyle/**/?",method=RequestMethod.GET)
public String antStyle(){
    return "success";
}

 2、路径变量PathVariable风格(路径上带变量)的url映射:借助这种风格可以获取到路径中的变量,使用路径中的变量,比如使用id作为变量,在处理方法中很容易就能取得id的值
在这里插入图片描述
  示例:

@RequestMapping(value="/testPathVariable/{abcd}",method=RequestMethod.GET)
public String pathVariable(@PathVariable("abcd") String uu){
    System.out.println("hello" + uu);
    return "success";
}  

三、RESTFul风格
 REST,全称为Representational State Transfer,即具象化状态传输。RESTful是一种软件架构风格、设计风格,而不是标准,只是提供了一组设计原则和约束条件。它主要用于客户端和服务器交互类的软件,基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。
 RESTful的关键是定义可表示流程元素/资源的对象。在REST中,每一个对象都是通过URL来表示的,对象用户负责将状态信息打包进每一条消息内,以便对象的处理总是无状态的。
 每发出一个请求,就代表了客户端和服务端的一次交互。HTTP协议是一个无状态的协议,所有的状态都保存在服务器端。因此客户端要想操作服务器,必须通过某种手段,让服务器发生状态转化(State Transfer)。具体地说,就是通过HTTP协议的操作方式(主要有GET、POST、PUT、DELETE)分别对应相应的服务器中的操作(查、增、改、删)。
在这里插入图片描述
 1、GET方式:对应获取,与普通的get方式无异,一个普通的超链接即为get方式,使用PathVariable风格的url映射可以传递一个id等,在处理方法中根据id获取资源,在处理方法中指定method=RequestMethod.GET

<a href="${pageContext.request.contextPath}/order/217">GET</a>
@RequestMapping(value="/order/{uuid}",method=RequestMethod.GET)
public String testResuful_GET(@PathVariable("uuid") Integer uuid){
    System.out.println("------testResuful_GET:  "+uuid);
    return "ok";
} 

 2、POST方式:对应添加,表单与普通的post方式无异,指定提交方式为post,处理方法中也指定method=RequestMethod.POST

<form action="${pageContext.request.contextPath}/order" method="post">
	<input name="code" value="123456" />
	<input name="amount" value="10" />
    <input type="submit" value="post_commit" />
</form>
@RequestMapping(value="/order",method=RequestMethod.POST)
public String testResuful_POST(@RequestBody("order") Order order){
    System.out.println("------testResuful_POST" + order);
    return "ok";
} 

 3、DELETE方式:对应删除,表单中的提交方式是post,需要一个name="_method"、value=“DELETE"的隐藏域,同时需要配置转化提交方式的过滤器(该过滤器会通过name=”_method"的隐藏域将post请求转化为DELETE或者PUT请求),将提交方式由POST转化为DELETE

<form action="${pageContext.request.contextPath}/order/216" method="post">
    <input type="hidden" name="_method" value="delete"> 
    <input type="submit" value="delete_commit" />
</form>
@RequestMapping(value="/order/{uuid}",method=RequestMethod.DELETE)
public String testResuful_DELETE(@PathVariable("uuid") Integer uuid){
    System.out.println("------testResuful_DELETE:  "+uuid);
    return "ok";
}

 4、PUT方式:对应修改,表单中的提交方式是post,需要一个name="_method"、value="PUT"的隐藏域辅助,同时需要配置转化提交方式的过滤器,将提交方式由POST转化为PUT

<form action="${pageContext.request.contextPath}/order" method="post">
    <input type="hidden" name="_method" value="PUT"> 
    <input name="id" value="123456" />
	<input name="amount" value="10" />
    <input type="submit" value="put_commit" />
</form>
@RequestMapping(value="/order",method=RequestMethod.PUT)
public String testResuful_PUT(@RequestBody("order") Order order){
    System.out.println("------testResuful_PUT:" + order);
    return "ok";
}

Tip:请求的映射不仅可以通过请求的路径区分,还可以通过请求的方式来区分,当请求路径相同,请求方式不同时也可以精确匹配到不同的处理方法

 提交方式转化的过滤器的配置:在web.xml中配置如下

<!-- 配置org.springframework.web.filter.HiddenHttpMethodFilter,实现POST转换为PUT、DELETE -->
<filter>
    <filter-name>HiddenHttpMethodFilter</filter-name>
    <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>HiddenHttpMethodFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping> 

四、请求参数映射
 URL地址中的请求参数,表单中的参数都可以注入到处理方法的同名参数中作为实参供方法使用。
 1、请求参数的单值映射:使用@RequestParam获取单个的请求参数

<a href="${pageContext.request.contextPath}/testRequestParam?age=26>
	testRequestParam
</a>  
@RequestMapping(value="/testRequestParam",method=RequestMethod.GET)
public String testRequestParam(@RequestParam(value="age",required=false,defaultValue="99") Integer age){
	System.out.println("------testRequestParam:  "+age);
	return "ok";
}  

  Tip
   1️⃣若请求参数名和处理方法的入参相同时,不加@RequestParam指定也是可以的,SpringMVC默认即会将同名参数的值注入到入参中
   2️⃣required和defaultValue是对参数的限制,可有可无,据情况而定
 2、请求参数的多值映射:当请求参数是数组时,处理方法的入参也使用数组接收

<a href="${pageContext.request.contextPath}/testParam?roleId=11&roleId=12&roleId=13">
	testRequestParam
</a>  
@RequestMapping(value="/testParam",method=RequestMethod.GET)
public String testRequestParam(@RequestParam("roleId") String[] roleIds){
	for (int i = 0; i < roleIds.leng; i++){
		System.out.println(roleIds[i]);
	}
	return "ok";
} 

 3、获取请求头的信息:形参列表处用@RequestHeader获取对应的请求头,以Host为例,其他的都可以以请求头的key获取

@RequestMapping(value="/testRequestHeader",method=RequestMethod.GET)
public String testRequestHeader(@RequestHeader(value="Host") String host){
    System.out.println("------testRequestHeader: "+ host);
    return "ok";
} 

 4、获取请求的Cookie:使用@CookieValue获取请求中的Cookie值,此处以JSESSIONID为例

@RequestMapping(value="/testCookieValue",method=RequestMethod.GET)
public String testCookieValue(@CookieValue("JSESSIONID") String seesionId){
	System.out.println("------testRequestHeader: " + seesionId);
	return "ok";
}  

 5、POJO对象作为形参:由表单中的参数注入生成POJO对象,注意表单中各项的name的值要和对象的属性名一致

<form action="${pageContext.request.contextPath}/testPOJO" method="post">
    userName:<input type="text" name="userName" value="z3"/><br>
    passWord:<input type="password" name="passWord" value="123456"/><br>
    age:<input type="text" name="age" value="25"/><br>
    email:<input type="text" name="email" value="z3@163.com"/><br>
    <input type="submit" value="testPOJO_commit">
</form>  
@RequestMapping(value="/testPOJO",method=RequestMethod.POST)
public String testPOJO(User user){
    System.out.println("------testPOJO: " + user.toString());
    return "ok";
}  

  也可以使用@RequestBody获取表单中的对象属性值
 6、直接获取到ServletAPI:除了request、response之外,其他的也可以获取到

@RequestMapping(value="/testServletAPI",method=RequestMethod.GET)
public void testServletAPI(HttpServletRequest request,HttpServletResponse response,Writer writer) throws IOException{
    System.out.println("------testServletAPI:" + request.getContextPath());
    System.out.println("------testServletAPI:" + response.getCharacterEncoding());
    response.setContentType("text/html");
    response.setCharacterEncoding("UTF-8");
    writer.write("welcomt to springmvc......");
    writer.flush();
    writer.close();
}  

  示例中的方法看似没有返回值,实际上是以流的方式将内容直接传送给浏览器,在浏览器中就会直接输入writer的内容
  底层获取Servlet原生API的代码:会根据自己方法的形参列表选择性的获取

@Override
protected Object resolveStandardArgument(Class<?> parameterType, NativeWebRequest webRequest) throws Exception {
    HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
    HttpServletResponse response = webRequest.getNativeResponse(HttpServletResponse.class);
    if (ServletRequest.class.isAssignableFrom(parameterType) ||
            MultipartRequest.class.isAssignableFrom(parameterType)) {
        Object nativeRequest = webRequest.getNativeRequest(parameterType);
        if (nativeRequest == null) {
            throw new IllegalStateException(
                    "Current request is not of type [" + parameterType.getName() + "]: " + request);
        }
        return nativeRequest;
    }
    else if (ServletResponse.class.isAssignableFrom(parameterType)) {
        this.responseArgumentUsed = true;
        Object nativeResponse = webRequest.getNativeResponse(parameterType);
        if (nativeResponse == null) {
            throw new IllegalStateException(
                    "Current response is not of type [" + parameterType.getName() + "]: " + response);
        }
        return nativeResponse;
    }
    else if (HttpSession.class.isAssignableFrom(parameterType)) {
        return request.getSession();
    }
    else if (Principal.class.isAssignableFrom(parameterType)) {
        return request.getUserPrincipal();
    }
    else if (Locale.class.equals(parameterType)) {
        return RequestContextUtils.getLocale(request);
    }
    else if (InputStream.class.isAssignableFrom(parameterType)) {
        return request.getInputStream();
    }
    else if (Reader.class.isAssignableFrom(parameterType)) {
        return request.getReader();
    }
    else if (OutputStream.class.isAssignableFrom(parameterType)) {
        this.responseArgumentUsed = true;
        return response.getOutputStream();
    }
    else if (Writer.class.isAssignableFrom(parameterType)) {
        this.responseArgumentUsed = true;
        return response.getWriter();
    }
    return super.resolveStandardArgument(parameterType, webRequest);
}  

  最后当所有的if条件都不满足时说明,形参部分不是原生的API,无法由SpringMVC提供,就会调用最后这一行,这一行的底层本质上是新建一个Object对象兜底的。下面是Handler方法可以接收的ServletAPI类型的参数:
   •HttpServletRequest
   •HttpServletResponse
   •HttpSession
   •java.security.Principal
   •Locale
   •InputStream
   •OutputStream
   •Reader
   •Writer

五、请求的转发和重定向
 SpringMVC中对请求转发或重定向时只需要在返回的逻辑视图名中加上相应的前缀即可,转发加forward:,重定向加redirect:

//转发
@RequestMapping(value="/testForward",method=RequestMethod.GET)
public String testForward(){
	return "forward:myforward.jsp";
}

//重定向
@RequestMapping(value="/testRedirect",method=RequestMethod.GET)
public String testRedirect(){
	return "redirect:myredirect.jsp";
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值