×

springMVC请求映射全面分析

消耗积分:1 | 格式:rar | 大小:0.6 MB | 2017-10-11

分享资料个

 在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条评论

快来发表一下你的评论吧 !

'+ '

'+ '

'+ ''+ '
'+ ''+ ''+ '
'+ ''+ '' ); $.get('/article/vipdownload/aid/'+webid,function(data){ if(data.code ==5){ $(pop_this).attr('href',"/login/index.html"); return false } if(data.code == 2){ //跳转到VIP升级页面 window.location.href="//m.obk20.com/vip/index?aid=" + webid return false } //是会员 if (data.code > 0) { $('body').append(htmlSetNormalDownload); var getWidth=$("#poplayer").width(); $("#poplayer").css("margin-left","-"+getWidth/2+"px"); $('#tips').html(data.msg) $('.download_confirm').click(function(){ $('#dialog').remove(); }) } else { var down_url = $('#vipdownload').attr('data-url'); isBindAnalysisForm(pop_this, down_url, 1) } }); }); //是否开通VIP $.get('/article/vipdownload/aid/'+webid,function(data){ if(data.code == 2 || data.code ==5){ //跳转到VIP升级页面 $('#vipdownload>span').text("开通VIP 免费下载") return false }else{ // 待续费 if(data.code == 3) { vipExpiredInfo.ifVipExpired = true vipExpiredInfo.vipExpiredDate = data.data.endoftime } $('#vipdownload .icon-vip-tips').remove() $('#vipdownload>span').text("VIP免积分下载") } }); }).on("click",".download_cancel",function(){ $('#dialog').remove(); }) var setWeixinShare={};//定义默认的微信分享信息,页面如果要自定义分享,直接更改此变量即可 if(window.navigator.userAgent.toLowerCase().match(/MicroMessenger/i) == 'micromessenger'){ var d={ title:'springMVC请求映射全面分析',//标题 desc:$('[name=description]').attr("content"), //描述 imgUrl:'https://'+location.host+'/static/images/ele-logo.png',// 分享图标,默认是logo link:'',//链接 type:'',// 分享类型,music、video或link,不填默认为link dataUrl:'',//如果type是music或video,则要提供数据链接,默认为空 success:'', // 用户确认分享后执行的回调函数 cancel:''// 用户取消分享后执行的回调函数 } setWeixinShare=$.extend(d,setWeixinShare); $.ajax({ url:"//www.obk20.com/app/wechat/index.php?s=Home/ShareConfig/index", data:"share_url="+encodeURIComponent(location.href)+"&format=jsonp&domain=m", type:'get', dataType:'jsonp', success:function(res){ if(res.status!="successed"){ return false; } $.getScript('https://res.wx.qq.com/open/js/jweixin-1.0.0.js',function(result,status){ if(status!="success"){ return false; } var getWxCfg=res.data; wx.config({ //debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。 appId:getWxCfg.appId, // 必填,公众号的唯一标识 timestamp:getWxCfg.timestamp, // 必填,生成签名的时间戳 nonceStr:getWxCfg.nonceStr, // 必填,生成签名的随机串 signature:getWxCfg.signature,// 必填,签名,见附录1 jsApiList:['onMenuShareTimeline','onMenuShareAppMessage','onMenuShareQQ','onMenuShareWeibo','onMenuShareQZone'] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2 }); wx.ready(function(){ //获取“分享到朋友圈”按钮点击状态及自定义分享内容接口 wx.onMenuShareTimeline({ title: setWeixinShare.title, // 分享标题 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); //获取“分享给朋友”按钮点击状态及自定义分享内容接口 wx.onMenuShareAppMessage({ title: setWeixinShare.title, // 分享标题 desc: setWeixinShare.desc, // 分享描述 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 type: setWeixinShare.type, // 分享类型,music、video或link,不填默认为link dataUrl: setWeixinShare.dataUrl, // 如果type是music或video,则要提供数据链接,默认为空 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); //获取“分享到QQ”按钮点击状态及自定义分享内容接口 wx.onMenuShareQQ({ title: setWeixinShare.title, // 分享标题 desc: setWeixinShare.desc, // 分享描述 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); //获取“分享到腾讯微博”按钮点击状态及自定义分享内容接口 wx.onMenuShareWeibo({ title: setWeixinShare.title, // 分享标题 desc: setWeixinShare.desc, // 分享描述 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); //获取“分享到QQ空间”按钮点击状态及自定义分享内容接口 wx.onMenuShareQZone({ title: setWeixinShare.title, // 分享标题 desc: setWeixinShare.desc, // 分享描述 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); }); }); } }); } function openX_ad(posterid, htmlid, width, height) { if ($(htmlid).length > 0) { var randomnumber = Math.random(); var now_url = encodeURIComponent(window.location.href); var ga = document.createElement('iframe'); ga.src = 'https://www1.elecfans.com/www/delivery/myafr.php?target=_blank&cb=' + randomnumber + '&zoneid=' + posterid+'&prefer='+now_url; ga.width = width; ga.height = height; ga.frameBorder = 0; ga.scrolling = 'no'; var s = $(htmlid).append(ga); } } openX_ad(828, '#berry-300', 300, 250);