springmvc 发送PUT 和 DELETE 请求
一: 发送 DELETE 或者 PUT 请求:
1、在表单中加入一个隐藏的参数: _method , 值是 DELETE (或者PUT)
<form action="springmvc/testRest/a1we2!3#d" method="post"> <input type="hidden" name="_method" value="DELETE"></input> <input type="submit" value="test Rest delete"></input> </form>
2、 发送的POST 请求, 配置一个 HiddenHttpMethodFilter 过滤器:
<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>
该过滤器会把 获取 String paramValue = request.getParameter("_method");
paramValue 值是 DELETE , 然后把该POST 的 HTTP请求的 改成 DELETE 请求。
3、在Controller 中匹配,获取上面的 DETELE 请求
@RequestMapping(value="/testRest/{ss}", method=RequestMethod.DELETE) public String testRestDelete(@PathVariable("ss") String sid) { System.out.println("test DELETE: " + sid); return SUCCESS; }
输出: test DELETE: a1we2!3
点了 test Rest delete 这个按钮后,请求的url 是 http://localhost:8080/springmvc-1/springmvc/testRest/a1we2!3#d , 在springmvc 中通过 PathVariable 注解获取 REST风格的URL 中的参数,获取的时候 ss 值是 a1we2!3 , 保存到 sid 中。 (把 # 后面的内容去掉了)
二:在 前台页面中写的链接:
<a href="springmvc/tsetParameters?username=zhou&age=11">tsetParameters</a></br>
RequestMapping 注解中可以使用 params 匹配请求中的参数, 用headers 匹配http请求中头域
controller 方法中:
@RequestMapping(value="tsetParameters", params={"username", "age!=10"},headers={"Accept-Language=zh-CN,zh;q=0.9" , "User-Agent=Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36"}) public String testParameters() { System.out.println("testParameters"); return SUCCESS; }
当 前台发送的请求 是: http://localhost:8080/springmvc-1/springmvc/tsetParameters?username=zhou&age=11 并且http 请求中带有:
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36
Accept-Language: zh-CN,zh;q=0.9
这两个头域的时候, 才会执行 testParameters 方法。
即执行 testParameters 方法需要同时满足以下的条件:
1、请求url tsetParameters 中必须含有 username 参数,必须含有 age 参数 并且 值不能是 10.
2、请求header 中 必须有 Accept-Language 和 User-Agent 。 并且值是 RequestMapping 中写的。
否则就会报404 错误。
四: @RequestMapping 可以映射参数:
value 值即请求参数的参数名
required 该参数是否是必须,默认是true 。
defaultValue 请求参数的默认值
比如请求url: http://localhost:8080/springmvc-1/springmvc/testRequestParam?username=zhou
controller 方法:
@RequestMapping(value="/testRequestParam") public String testRequestParam(@RequestParam(value="username") String name, @RequestParam(value="age",required=false, defaultValue="0") int age){ System.out.println("name:" + name + "======" + "age:" + age); return SUCCESS; }
输出: name:zhou======age:0
RequestHeader 注解可以获取 http 请求的头域:
@RequestMapping("/testHeader") public String testRequestHeader(@RequestHeader("User-Agent") String ua) { System.out.println(ua); return SUCCESS; }
CookieValue 可以获取cookie 值
@RequestMapping("/testCookie") public String testCookieVal(@CookieValue("JSESSIONID") String cook) { System.out.println(cook); return SUCCESS; }
Servlet 原生API 作为目标方法的参数支持以下类型:
HttpServletRequest、HttpServletResponse、HttpSession、java.security.Principal、Local InputStream、 OutputStream、 Reader、Writer 。
@RequestMapping("/testServletAPI") public void testServletAPI(HttpServletRequest req, HttpServletResponse rep,Writer writer) throws IOException { System.out.println("HttpServletRequest:" + req + "--------" + rep); writer.write("this is servlet api"); }
前台页面上显示: this is servlet api
五:
springmvc 可以返回目标方法中的map对象:
Controller 方法:
@RequestMapping("/testMap") public String testMap(Map<String, Object> map) { map.put("names", Arrays.asList("tim","jack","mike")); return SUCCESS; }
在返回的页面 success.jsp 中 可以接收 names 对象:
<body>
${requestScope.names}
${names}
</body>
页面显示:
[tim, jack, mike] [tim, jack, mike]
Controller 层也可以返回 ModelAndView 对象:
@RequestMapping("/testModelView") public ModelAndView testModel() { String viewName = SUCCESS; ModelAndView modelview = new ModelAndView(viewName); modelview.addObject("time",new Date()); return modelview; }
success.jsp 通过 ${names} 或者 ${requestScope.names} 接收,在页面上显示时间。
六:
@sessionAttributes 可以通过属性名指定放到会话中的属性(value属性值), 也可以通过模型属性的对象类型指定哪些模型属性需要放到会话中(types属性值)。
Controller 方法:
@RequestMapping("/testSessionAttr") public String testSessionAttr(Map<String, Object> map) { User user = new User("tom","123","tomc@guigu.com", 20); map.put("userone", user); map.put("school", "qinghua"); User user2 = new User("mike","365","mm@guigu.com", 30); map.put("usertwo2", user2.getAge());
return SUCCESS; }
需要在Controller 类上加上注解: @SessionAttributes(value={"userone"}, types={String.class})
user: ${userone} </br> 在前台界面上取的值是: User [username=tom, password=123, email=tomc@guigu.com, age=20, address=null]
request user: ${requestScope.userone} </br> User [username=tom, password=123, email=tomc@guigu.com, age=20, address=null]
sessionScope user: ${sessionScope.userone}</br> User [username=tom, password=123, email=tomc@guigu.com, age=20, address=null]
school: ${school}</br> qinghua
requestScope school: ${requestScope.school}</br> qinghua
sessoin school: ${sessionScope.school}</br> qinghua
usertwo: ${usertwo2}</br> 30
requestScope usertwo: ${requestScope.usertwo2}</br> 30
sessionScope usertwo: ${sessionScope.usertwo2}</br> 空
只有把 String 类型的值放到 session 中时, sessionScope 中才会取到。
七:
在前台页面向Controller传递bean 的属性时,如果bean 对象没有空的构造函数,并且前台页面传的属性和bean 的构造函数参数不匹配时,就会报错,没有空的构造函数:
严重: Servlet.service() for servlet [springmvc] in context with path [/springmvc-1] threw exception [Request processing failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.zhou.entity.User]: No default constructor found; nested exception is java.lang.NoSuchMethodException: com.zhou.entity.User.<init>()] with root cause
java.lang.NoSuchMethodException: com.zhou.entity.User.<init>()
at java.lang.Class.getConstructor0(Class.java:2849)
at java.lang.Class.getDeclaredConstructor(Class.java:2053)
需要加上一个空的构造函数。
1、在方法定义上使用 @ModelAttribute 注解:SpringMVC 在调用Controller 目标处理方法前,会先逐个调用在方法级上标注了 @ModelAttribute 的方法。
2、在方法的入参前使用 @ModelAttribute 注解 ,可以从隐含对象中获取隐含的模型数据中获取对象,再将请求参数绑定到对象中,再传入入参,将方法入参对象添加到模型中
前台页面传入 username、email、 age:
<form action="springmvc/testModeAttr"> <input type="hidden" name="id" value="1"> username: <input type="text" name="username" value="Tom"><br/> email: <input type="text" name="email" value="tomca@126.com"><br/> age: <input type="text" name="age" value="26"><br/> <input type="submit" value="提交"><br/> </form>
Controller 中的方法:
@RequestMapping("/testModeAttr") public String testModeAttr(User user,Map<String, Object> map) { System.out.println("modify:" + user); map.put("user", user); return SUCCESS; } @ModelAttribute public void getUser(@RequestParam(value="id", required=false) Integer id,Map<String, Object> map) { if(id!= null){ User user = new User(1,"Tome", "12345","tom@guigu.com", 12); System.out.println("从数据库中获取的对象:" + user); map.put("user", user); } }
1、先执行 @ModelAttribute 注解的 getUser 方法, 输出: 从数据库中获取的对象:User [id=1, username=Tome, password=12345, email=tom@guigu.com, age=12]
把 user 存入 key是 user 的对象中。
2、 SpringMVC 把 从Map 中取出的 User 对象,并把表单的请求参数 赋给该 User 对象的对应属性。 (这一步是SpringMVC 完成的) (在@ModelAttribute 修饰的方法中,放入到Map 时的键需要和目标方法入参类型的第一个字母小写的字符一致,)
如果在 @ModelAttribute 修饰的方法中,map存入的对象 和 目标方法的参数类名的第一个字母小写的字符不一致,可以在目标方法中用 @ModelAttribute 修改该参数。 比如:
@RequestMapping("/testModeAttr") public String testModeAttr(@ModelAttribute("usera") User user,Map<String, Object> map) { System.out.println("modify:" + user); map.put("user", user); return SUCCESS; } @ModelAttribute public void getUser(@RequestParam(value="id", required=false) Integer id,Map<String, Object> map) { if(id!= null){ User user = new User(1,"Tome", "12345","tom@guigu.com", 12); System.out.println("从数据库中获取的对象:" + user); map.put("usera", user); } }
则在 目标方法 testModeAttr 中的参数 user 也就是 map 中存入的 key 是 usera 的对象。
3、 再执行 目标方法 testModeAttr , 把上面的user 对象传入 该目标方法。