springmvc请求返回一个字符_springMVC请求映射全面分析

原标题:springMVC请求映射全面分析

在springMVC的控制器中,我们常使用@RequestMapping来完成我们的请求映射,我们可以在类定义上和方法定义上使用注解,其配置的路径将为类中定义的所有方法的父路径,如上篇实例中的/user(类)/hello(方法)。

一般的,我们类定义上的路径注解起到命名空间的作用,防止不同方法的路径映射产生冲突,比如我在UserController和ArticleController下都定义了如下的方法:

@RequestMapping("list") publicvoidlist(){ .... }

一个list映射路径,这时候springMVC就不知道该将请求交给到哪个方法处理。当然,我们也能在方法上进行二级路径配置区分:

/*************UserController***********/@RequestMapping("user/list") publicvoidlist(){ .... } /*************ArticleController***********/@RequestMapping("article/list") publicvoidlist(){ .... }

这样就能有效防止冲突了,但如果我有很多个方法存在这样的冲突,是否都要在每个方法加上前缀呢?这时候我们可以选择在类路径上注解@RequestMapping来对全体方法进行区分。

通过url进行映射

1. Ant风格字符匹配

除了标准的url外,@RequestMapping还支持Ant风格字符,即”?”、”*”、”**”,其中

1. “?”:匹配一个任意字符,如/user/a?,匹配user/aa,user/ab等路径

2. “*”:匹配任意字符串,如/user/a*,匹配/user下任意以a开头的路径如/user/abc,/user/aqw等

3. “**“:匹配多级路径字符串,如/user/**/list,匹配/user/user1/list,/user/1resu/list等

在这里,需要注意的是当*的 位置与 个数不同时,*可以代表的 字符数有区别,看下面示例:

@RequestMapping("u1/*")//只能匹配u1/a,u1/b,不能匹配u1/————即此时*表示一个或多个字符publicvoidtest(HttpServletResponse response) throwsIOException{ response.getWriter().print("u1/*"); } @RequestMapping("u1/**")//能够匹配u1/,u1/qq,u1/qq/ww,这里要特别注意的是,“**“能匹配零个而“*”不能publicvoidtest(HttpServletResponse response) throwsIOException{ response.getWriter().print("u1/*"); } @RequestMapping("u2/a*")//能够匹配u2/a,u2/ab,u2/aqqqq等————即此时*表示零个或零个以上字符publicvoidtest1(HttpServletResponse response) throwsIOException{ response.getWriter().print("u2/a*"); }

2. restful占位符匹配

除了使用上面风格,@RequestMapping还支持restful风格占位符的形式,假如我们需要针对特定用户查看其特定文章,restful风格路径匹配如下所示:

@Controller//注解为控制器,通过spring容器扫描,会注册为一个Bean@RequestMapping("/user/{uid}")//一级访问路径,对类中所有方法生效publicclassUserController{@RequestMapping("article/{aid}") publicString detail(@PathVariable("uid")Integer uid,@PathVariable("aid")Integer aid){ System.out.println( "查看id为"+ uid + "的用户文章,且文章id为"+aid); return"someplace"; } }

这里,如果我们想访问用户id为1,文章id为2的用户文章,就可以访问如下路径:[项目根路径]/user/1/article/2来完成。

我们使用@PathVariable(“val”)来完成对应路径中{val}的资源请求,这里的两个val名称需一致,紧接着的方法入参名字任意,我们刚刚示例了一个多路径参数绑定,假设只有一个,如下也是合法的:

@RequestMapping("user/{uid}") publicString detail(@PathVariable("uid")Integer notUid){//notUid名字也能成功绑定return"someplace"; }

此外,如果我们入参名字和url路径资源名称一致,则可以省略配置@PathVariable中的value值,如下实例也能正确绑定路径资源到入参

@RequestMapping("user/{uid}") publicString detail(@PathVariable Integer uid){//notUid名字也能成功绑定return"someplace"; }

3. 优先匹配规则

url还有如下两个常见匹配准则: 最长最精确优先匹配和 占位符优先匹配

1. 最长最精确优先匹配

下面我们来看前一个匹配实例:

@RequestMapping("test/**") publicvoidtest2(HttpServletResponse response) throwsIOException{ response.getWriter().print("test/**"); } @RequestMapping("test/*") publicvoidtest3(HttpServletResponse response) throwsIOException{ response.getWriter().print("test/*"); } @RequestMapping("test/*/**") publicvoidtest4(HttpServletResponse response) throwsIOException{ response.getWriter().print("test/*/**"); } @RequestMapping("test/*/*") publicvoidtest5(HttpServletResponse response) throwsIOException{ response.getWriter().print("test/*/*"); } @RequestMapping("test/1/*") publicvoidtest6(HttpServletResponse response) throwsIOException{ response.getWriter().print("test/1/*"); } @RequestMapping("test/1/2") publicvoidtest7(HttpServletResponse response) throwsIOException{ response.getWriter().print("test/1/2"); }

直接看上面匹配会觉得很乱,我们直接看下面的测试:

测试

匹配结果

test/a 匹配test/*而不匹配test/**(更精确优先匹配)

test/a/a/aa/a 匹配test/**而不匹配test/*/**,(在多层匹配中,**比***更精确)

test/a/a 匹配test/*/*,因为/*/*比**精确

test/1/a 匹配test/1/*,因为/1/*比/*/*精确

test/1/2 匹配test/1/2,这是完全匹配

2. 占位符优先匹配原则

占位符是指@PathVariable等路径资源占位符,下面我们在看一个实例

@RequestMapping("test/1/2") publicvoidtest7(HttpServletResponse response) throwsIOException{ response.getWriter().print("test/1/2"); } @RequestMapping("test/1/{id}") publicvoidtest8(HttpServletResponse response,@PathVariable Integer id ) throwsIOException{ response.getWriter().print("test/1/(myId=)"+ id ); } @RequestMapping("test/1/a") publicvoidtest7(HttpServletResponse response) throwsIOException{ response.getWriter().print("test/1/a"); }

从上一个实例的所有路径映射中,我们测试出test/1/2是最精确的。但我们根据添加了占位符映射,在游览器输入 test/1/2,此时游览器返回 test/1/(myId=)2,即 占位符的优先级比普通字符串的优先级更高!但如果我们此时输入 test/1/a。程序不会因为我们的 在方法入参中id映射为Integer类型而放弃匹配,占位符的优先级依然比字符(串)a的优先级高,但由于 “a”不能转化为Integer类型,所以服务器会返回 400错误

通过HTTP其它请求资源映射

除了使用url外,我们还能通过请求参数、请求方法、或请求头进行映射

我们先看看@RequestMapping的完整属性列表:

属性

说明

value 指定请求的实际地址, 比如 /action/info之类。

method 指定请求的method类型, GET、POST、PUT、DELETE等

consumes 指定处理请求的提交内容类型(Content-Type),例如application/json, text/html;

produces 指定返回的内容类型,仅当request请求头中的(Accept)类型中包含该指定类型才返回

params 指定request中必须包含某些参数值是,才让该方法处理

headers 指定request中必须包含某些指定的header值,才能让该方法处理请求

其中,consumes, produces使用content-type信息进行过滤信息;headers中可以使用content-type进行过滤和判断。

在前面的使用中,我们发现并没有指定value属性,直接在括号里输入字符串也能向value属性赋值,这是因为在java注解中不加其他属性,直接赋值必定是针对注解的value成员,如果该注解没有名为value的成员,则会报错

下面我们先看几个示例:

示例1:vmethod,headers

@RequestMapping(value = "testa",method = RequestMethod.POST,headers = "content-type=text/*")

表示映射路径为testa,请求方法必须为POST方法(如果我们用post发出请求,会返回错误信息HTTP Status 405 - Request method ‘GET’ not supported),headers部分表示请求头信息中必须包含等号后相应部分内容,*匹配任意字符串

示例2:consumes

@RequestMapping(value = "testb", consumes="application/json")

表示方法仅匹配request Content-Type为“application/json”类型的请求。

示例3:produces

@RequestMapping(value = "/testc", produces="application/json")

表示方法匹配的请求需要请求头中Accept部分包含”application/json“,同时在响应时,会将 返回内容同时设置为”application/json‘’

示例4:params

@RequestMapping(value = "testd",method = RequestMethod.GET,params = {"id1","id2"}) publicvoidtest12(HttpServletResponse response,Integer id1,Integer id2) throwsIOException{ response.getWriter().print(id1 + "——"+ id2); }

示例表示入参需包含参数名为id1,id2的两个参数,这里如果我输入:

1. http://localhost:8080/springMVC/user/testd—-

2. http://localhost:8080/springMVC/user/testd?id1=1—报404错误

3. ttp://localhost:8080/springMVC/user/testd?id1=1&id2=2—-返回1——2

4. ttp://localhost:8080/springMVC/user/testd?id1=1&id2=2&id3=3—-返回1——2

从以上我们可以看出,只有具有相应参数的才能完成映射,且可以有除了params中要求以外的参数,如id3。

在params的常见映射规则如下:

示例规则

说明

”param1” 请求必须包含名为param1的参数

“!param1” 请求中不能包含名为param1的参数

“param1!=value1 请求中必须包含param1参数,但其值不能为value1

{“param1=value1”,”param2”} 请求中需要包含param1参数和param2参数,且param1的值必须为value1返回搜狐,查看更多

责任编辑:

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值