SpringMVC入门 -- 参数绑定
一、REST与RESTful
1、简介
(1)REST(Representational State Transfer):表现层状态转移,一种软件架构风格,不是标准。REST描述的是在网络中client和server的一种交互形式,即资源在网络中以某种表现形式进行状态转移。
(2)基于REST构建的API就是Restful风格。
2、相关概念
(1)资源(Resources):指的是网络上的一个具体的信息(文本、图片等),通过一个URL可以唯一的指向它。
(2)表现层(Representational ):将信息表现出来的形式,比如使用txt表示文本,或者html表示文本。
(3)状态转移(State Transfer):客户端每发送一次请求到服务器,服务器响应会涉及到数据以及状态的切换。而HTTP属于一种无状态的协议,所有状态均保存在服务端,客户端想要去操作服务端,则需要通过某种手段(HTTP协议里的动词)使服务端发生状态转移,且显示在表现层。
3、常见HTTP动词
(1)GET(SELECT): 从服务器获取资源(一项或多项)
(2)POST(CREATE): 在服务器新建一个资源
(3)PUT(UPDATE): 在服务器更新资源(客户端提供改变后的完整资源)
(4)DELETE(DELETE):从服务器删除资源。
4、使用样例
(1)浏览器的 form 表单只支持 GET 与 POST请求,不支持 DELETE、PUT 请求。
(2)Spring 3.0后,添加了一个过滤器(HiddenHttpMethodFilter),可以将POST请求转为DELETE、PUT请求,从而整体支持 DELETE、PUT、GET、POST。
(3)发送 PUT 请求和 DELETE 请求的实现步骤:
step1:需要在web.xml配置 HiddenHttpMethodFilter
step2:需要发送 POST 请求
step3:需要在发送 POST 请求时携带一个 name="_method" 的隐藏域, 值为 DELETE 或 PUT
【主要操作:】 【web.xml中配置 过滤器】 <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> 【即web.xml】 <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" version="4.0"> <servlet> <servlet-name>dispatcher</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:dispatcher-servlet.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>dispatcher</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <!--配置过滤器,将post请求转为delete,put--> <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> </web-app> 【index.jsp中配置 请求】 <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" isErrorPage="true"%> <html> <head> <title>首页</title> </head> <body> <%--测试get请求--%> <form action="/testRestful/1"> <input type="submit" value="test get"/> </form> <%--测试post请求--%> <form action="/testRestful" method="post"> <input type="submit" value="test post"/> </form> <%--测试post请求,不转为delete、put请求--%> <form action="/testRestful/1" method="post"> <input type="submit" value="test post2"/> </form> <%--测试post请求,转为put请求--%> <form action="/testRestful/1" method="post"> <input type="hidden" name="_method" value="PUT"/> <input type="submit" value="test put"/> </form> <%--测试post请求,转为delete请求--%> <form action="/testRestful/1" method="post"> <input type="hidden" name="_method" value="DELETE"/> <input type="submit" value="test delete"/> </form> </body> </html> 【HelloController.java 中处理请求:】 package com.lyh.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; import org.springframework.web.servlet.ModelAndView; @Controller public class HelloController { // 测试get请求,获取某条数据 @RequestMapping(value = "/testRestful/{id}", method = RequestMethod.GET) public ModelAndView testGet(@PathVariable("id") Integer id) { ModelAndView model = new ModelAndView("hello"); model.getModel().put("msg", id); model.getModel().put("message", "test get"); return model; } // 测试post请求,插入某条数据 @RequestMapping(value = "/testRestful", method = RequestMethod.POST) public ModelAndView testPost() { ModelAndView model = new ModelAndView("hello"); model.getModel().put("message", "test post"); return model; } // 测试post请求,不转为delete、put请求 @RequestMapping(value = "/testRestful/{id}", method = RequestMethod.POST) public ModelAndView testPost2(@PathVariable("id") Integer id) { ModelAndView model = new ModelAndView("hello"); model.getModel().put("msg", id); model.getModel().put("message", "test post2"); return model; } // 测试post请求,转为put请求,更新某条数据 @RequestMapping(value = "/testRestful/{id}", method = RequestMethod.PUT) public ModelAndView testPut(@PathVariable("id") Integer id) { ModelAndView model = new ModelAndView("hello"); model.getModel().put("msg", id); model.getModel().put("message", "test put"); return model; } // 测试post请求,转为delete请求,删除某条数据 @RequestMapping(value = "/testRestful/{id}", method = RequestMethod.DELETE) public ModelAndView testDelete(@PathVariable("id") Integer id) { ModelAndView model = new ModelAndView("hello"); model.getModel().put("msg", id); model.getModel().put("message", "test delete"); return model; } } 【hello.jsp 跳转的页面】 <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" isErrorPage="true"%> <html> <head> <title>Test Restful</title> </head> <body> <h2>${message}</h2> <h2>${msg}</h2> </body> </html> 【dispatcher-servlet.xml】 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd"> <context:component-scan base-package="com.lyh.controller"/> <mvc:default-servlet-handler/> <mvc:annotation-driven /> <bean id="defaultViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/"/><!--设置JSP文件的目录位置--> <property name="suffix" value=".jsp"/> </bean> </beans>
项目结构如下:其余操作可以参考 https://www.cnblogs.com/l-y-h/p/11502440.html
若访问delete、put请求出现405问题,在当前 jsp 页面的 头部添加 isErrorPage="true"。
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" isErrorPage="true"%>
二、方法参数常用注解
1、@RequestMapping
(1)简介
SpringMVC提供的一个注解,用于处理指定的请求。
请求经过DispatcherServlet后,通过@RequestMapping的映射信息确定所需对应的处理方法。
@RequestMapping可以在控制器 的类名前、方法名前定义。
【用法样例:】 package com.lyh.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; @Controller @RequestMapping("/test") public class HelloController { @RequestMapping("/hello") public String show(){ return "hello"; } }
(2)参数
value:表示请求的URL。
method:表示请求方法(GET、POST、DELETE、PUT)。
params:表示请求参数。
headers:表示请求头的映射条件。
注:
param1:表示请求必须包含名为 param1 的请求参数。
!param2:表示请求不能包含名为 parma2 的请求参数。
param1 != value1: 表示请求包含名为 param1 的请求参数,且其值不为 value1。
{"param1 = value1", "param2"}:表示请求必须包含param1,param2,且param1的值为value1。
value 地址支持通配符。
? :表示匹配文件名中的一个字符。比如:/hello/? ,可以获取 /hello/2,不能获取/hello/22
* :表示匹配文件名中任意一个字符。比如:/hello/* ,可以获取 /hello/2, 可以获取/hello/22,不能获取/hello/2/2
** :表示匹配多层路径。比如:/hello/**,可以获取/hello/2,可以获取/hello/22,可以获取/hello/2/2.
【用法样例:】
package com.lyh.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@Controller
@RequestMapping("/test")
public class HelloController {
@RequestMapping(value = "/hello", params = {"username", "age != 10"}, method = RequestMethod.GET, headers = "Referer: https://www.baidu.com/")
public String show(){
return "hello";
}
}
2、@PathVariable
(1)简介
SpringMVC提供的一个注解,在方法参数中使用,用于获取参数。
Spring3.0后支持 带占位符的URL,即相当于 /get/{id} 的形式。通过@PathVariable 可以将URL中的占位符参数绑定到方法的参数中。
【用法样例:】 package com.lyh.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; @Controller public class HelloController { @RequestMapping("/get/{id}") public String show(@PathVariable("id") Integer id){ return "hello"; } }
3、@RequestParam
(1)简介
SpringMVC提供的一个注解,在方法参数中使用,用于获取参数。
@RequestParam 用于获取表单参数。等价于request.getParameter("name")。而@PathVariable 用于获取 URL 中的占位符。
(2)参数
value:用于获取参数。
required :表示是否需要该数据,默认为true,若不存在,则会抛出异常。
defaultValue :表示默认的值,对于包装类型,默认为null,可以不设值,对于基本类型数据,需要设个初始值。
【举例:】 【index.jsp】 <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" isErrorPage="true"%> <html> <head> <title>首页</title> </head> <body> <form action="/testRequestParam/1"> <label for="nickname">姓名</label> <input type="text" id="nickname" name ="nickname" placeholder="请输入姓名..." /> <label for="password">密码</label> <input type="password" id="password" name ="password" placeholder="请输入密码..." /> <label for="age">年龄</label> <input type="text" id="age" name ="age" placeholder="请输入年龄..." /> <label for="salary">工资</label> <input type="text" id="salary" name ="salary" placeholder="请输入工资..." /> <input type="submit" value="test requestParam"/> </form> </body> </html> 【hello.jsp】 <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" isErrorPage="true"%> <html> <head> <title>Test RequestParam</title> </head> <body> <h2>${message}</h2> <h2>${msg}</h2> </body> </html> 【HelloController.java】 package com.lyh.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; import org.springframework.web.servlet.ModelAndView; @Controller public class HelloController { @RequestMapping(value = "/testRequestParam/{id}") public ModelAndView testRequestParam(@PathVariable("id") Integer id, @RequestParam(value = "nickname") String nickname, @RequestParam(value = "password") String password, @RequestParam(value = "age", required = false) Integer age, @RequestParam(value = "salary", required = false, defaultValue = "0.0") double salary) { ModelAndView model = new ModelAndView("hello"); model.getModel().put("msg", id + "," + nickname + "," + password + "," + age + "," + salary); model.getModel().put("message", "test RequestParam"); return model; } }
4、@RequestHeader
(1)简介
SpringMVC提供的一个注解,在方法参数中使用,用于获取请求头参数。
【index.jsp】 <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" isErrorPage="true"%> <html> <head> <title>首页</title> </head> <body> <a href="/testRequestHeader/1">testRequestHeader</a> </body> </html> 【hello.jsp】 <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" isErrorPage="true"%> <html> <head> <title>Test RequestHeader</title> </head> <body> <h2>${message}</h2> <h2>${msg}</h2> </body> </html> 【HelloController.java】 package com.lyh.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; import org.springframework.web.servlet.ModelAndView; @Controller public class HelloController { @RequestMapping(value = "/testRequestHeader/{id}") public ModelAndView testRequestHeader(@PathVariable("id") Integer id, @RequestHeader("Accept-Language") String language) { ModelAndView model = new ModelAndView("hello"); model.getModel().put("msg", id + "," + language); model.getModel().put("message", "test RequestHeader"); return model; } }
5、@CookieValue
(1)简介
SpringMVC提供的一个注解,在方法参数中使用,用于获取cookie参数。
【index.jsp】 <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" isErrorPage="true"%> <html> <head> <title>首页</title> </head> <body> <a href="/testCookieValue/1">testCookieValue</a> </body> </html> 【hello.jsp】 <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" isErrorPage="true"%> <html> <head> <title>Test CookieValue</title> </head> <body> <h2>${message}</h2> <h2>${msg}</h2> </body> </html> 【HelloController.java】 package com.lyh.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; import org.springframework.web.servlet.ModelAndView; @Controller public class HelloController { @RequestMapping(value = "/testCookieValue/{id}") public ModelAndView testCookieValue(@PathVariable("id") Integer id, @CookieValue("JSESSIONID") String jsessionId) { ModelAndView model = new ModelAndView("hello"); model.getModel().put("msg", id + "," + jsessionId); model.getModel().put("message", "test CookieValue"); return model; } }
6、自动给对象绑定请求参数值
(1)简介
SpringMVC可以根据请求参数名以及对象(POJO,Plain Ordinary Java Object)的属性名 自动匹配,自动为该对象绑定属性值,同时支持级联属性(如:"dept.salary")。
【新建实体类:DeptEntity.java】 package com.lyh.entity; public class DeptEntity { private String deptName; private Double salary; public String getDeptName() { return deptName; } public void setDeptName(String deptName) { this.deptName = deptName; } public Double getSalary() { return salary; } public void setSalary(Double salary) { this.salary = salary; } @Override public String toString() { return "DeptEntity{" + "deptName='" + deptName + '\'' + ", salary=" + salary + '}'; } } 【新建实体类:PersonEntity.java】 package com.lyh.entity; public class PersonEntity { private String name; private String password; private DeptEntity dept; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public DeptEntity getDept() { return dept; } public void setDept(DeptEntity dept) { this.dept = dept; } @Override public String toString() { return "PersonEntity{" + "name='" + name + '\'' + ", password='" + password + '\'' + ", dept=" + dept + '}'; } } 【index.jsp】 <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" isErrorPage="true"%> <html> <head> <title>首页</title> </head> <body> <form action="/testPOJO/1"> <label for="name">姓名</label> <input type="text" id="name" name ="name" placeholder="请输入姓名..." /> <label for="password">密码</label> <input type="password" id="password" name ="password" placeholder="请输入密码..." /> <label for="deptName">部门名</label> <input type="text" id="deptName" name ="dept.deptName" placeholder="请输入部门名..." /> <label for="salary">工资</label> <input type="text" id="salary" name ="dept.salary" placeholder="请输入工资..." /> <input type="submit" value="test POJO"/> </form> </body> </html> 【hello.jsp】 <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" isErrorPage="true"%> <html> <head> <title>Test POJO</title> </head> <body> <h2>${message}</h2> <h2>${msg}</h2> </body> </html> 【HelloController.java】 package com.lyh.controller; import com.lyh.entity.PersonEntity; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; import org.springframework.web.servlet.ModelAndView; @Controller public class HelloController { @RequestMapping(value = "/testPOJO/{id}") public ModelAndView testPOJO(@PathVariable("id") Integer id, PersonEntity person) { ModelAndView model = new ModelAndView("hello"); model.getModel().put("msg", id + "," + person); model.getModel().put("message", "test POJO"); return model; } }
对于能映射到的属性,会自动赋值,否则为默认值。使用级联赋值时,需要注意变量名不能写错了。