一. Spring MVC简介
1.1 编码基本步骤
- 创建web工程,导入核心jar包;
- 在web.xml中配置Spring MVC的前端控制器:
DispatcherServlet
- 配置SpringMvc的核心配置文件,如springmvc.xml
- 编写请求处理器
- 浏览器端发送请求,请求处理器中处理请求
- 测试
1.2 Spring MVC的前端控制器DispatcherServlet
<!--spring mvc的前端控制器:DispatcherServlet-->
<servlet>
<servlet-name> springDispatcherServlet</servlet-name>
<servlet-calss>org.springframework.web.servlet.DispatcherServlet </servlet-calss>
<!--为DispatcherServlet配置初始化参数,指定spring mvc的核心配置文件-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>springmvc.xml</param-value>
</init-param>
<!--load-on-startup设置DispatcherServlet 的加载时机,在服务器启动时加载,1表示优先级
servlet的创建时机包括:1.请求到达后创建 2.服务器启动后创建
-->
<load-on-startup> 1</load-on-startup>
</servlet>
<!--指定请求的匹配-->
<servlet-mapping>
<servlet-name>springDispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
其中,springmvc.xml为自定义的spring mvc的核心配置文件,该核心配置文件中包含了spring mvc容器。
1.3 Spring MVC的核心配置文件
<!--1.组件扫描-->
<context:component-scan base-package="com.xx.springmvc.xml"></context:component-scan>
<!--2.视图解析器
工作机制:prefix+请求处理方法的返回值+suffix=物理视图路径
即就是:/WEB-INF/views/success.jsp(success见1.4节)
WEB-INF: 是服务器的内部路径 ,不能直接从浏览器端访问该路径下的资源,但是可以内部转发进行访问
-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
1.4 Spring MVC的请求处理器
/**
@Controller:标注这个类是一个请求处理器
**/
@Controller
public class SpringMVCHandler{
/**
* 处理客户端请求:http://localhost:8080/springmvc01/hello
**/
@ResquestMapping(value="/hello")
public String handleHello(){
//处理请求代码
...
//通过视图解析器解析得到具体的视图,再自动转发去往该视图
return "success";
}
}
1.5 @RequestMapping
映射请求注解
(1) @RequestMapping
- 该注解既可以加在类上,也可以加在方法上,标注在类上表示提供初步的请求映射信息,相对于WEB应用的根目录,标注在方法上表示提供进一步的细分映射信息,相对于标记在类上的URL来说。
- 该注解的作用就是在DispatcherServlet截获请求后,就通过控制器上的该注解提供的映射信息确定请求所对应的处理方法。
- 主要包含了value,method以及param等属性标识。
(2)RequestMapping
映射请求占位符PathVariable
注解
通过@PathVariable
可以将URL中占位符参数绑定到控制器处理方法的入参中,比如在控制器方法中占位符所传id为1:
/**
@Controller:标注这个类是一个请求处理器
**/
@Controller
@RequestMapping(value="springmvc")
public class SpringMVCHandler{
/**
* 处理客户端请求:http://localhost:8080/springmvc01/hello
**/
@ResquestMapping(value="/hello/{id}")
public String handleHello(@PathVariable("id") Interger id){
//处理请求代码
...
//通过视图解析器解析得到具体的视图,再自动转发去往该视图
return "success";
}
}
<!--请求的链接-->
<a herf="springmvc/hello/1"
1.6 小结
首先tomcat服务器启动时,会加载DispatcherServlet
,随后会读取springmvc.xml这个自定义的核心配置文件,进而创建好springmvc的容器对象,在springmvc容器对象的配置文件中组件扫描会扫描到请求处理器以及请求处理中的@ResquestMapping注解,能得到具体的请求和请求处理器方法中的映射。
&ensp当服务器启动后,客户端发送请求会先去访问index.jsp页面,这个页面中的<a herf="hello">xx</a>
会使得页面显示xx,当我们点击xx时,请求会来到web.xml中的<url-pattern>
的位置匹配请求,匹配成功后,将这个请求交给spring mvc为我们提供的DispatcherServlet
,它根据请求与请求处理方法的映射,负责将这个请求交给具体的请求处理器,也就是@Controller
标识的类处理器,随后请求处理器根据映射将请求交给具体的处理方法。当请求方法返回时,视图解析器根据请求处理结果解析拼接物理视图路径后将响应转发去往该视图。
二. REST
2.1 REST风格的URL
REST风格的URL请求的处理方法的查找方式是通过具体的url和请求方法来查找区分的。
2.2 HiddenHttpMethodFilter过滤器
由于浏览器端只能发送GET或者POST方式的请求,而无法发送PUT以及DELETE方式的请求,但是又希望当请求到达控制器或者处理方法时有这四种方式,这时就需要过滤器。因此需要在到达控制器DispatcherServlet之前将请求做一个转换,因为过滤器的执行时机是在Servlet之前的。
可在配置DispatcherServlet前端控制器的xml文件中配置REST过滤器HiddenHttpMethodFilter,如下:
<!--配置REST过滤器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>
在index.jsp中:
<!--修改订单:REST PUT-->
<form action="order" method="post">
<!--隐藏域-->
<input type="hidden" name="_method" value="PUT"/>
<input type="submit" value="REST PUT"/>
</form>
<br>
<!--添加一个新的订单:REST POST-->
<form action="order" method="post">
<input type="submit" value="REST POST"/>
</form>
<br>
<!--删除id为1001的订单:REST DELETE-->
<form action="order/1001" method="post">
<!--隐藏域-->
<input type="hidden" name="_method" value="DELETE"/>
<input type="submit" value="REST DELETE"/>
</form>
<br>
<!-查询id为1001的订单:REST GET-->
<a herf="order/1001">REST GET</a>
在后台的处理器类中编写对应的测试方法即可。
2.3 小结
对于过滤器而言,只有原来为POST请求,并且能通过**_method**获取到一个请求参数值才能被转换成DELETE或者PUT请求。
开放平台如蚂蚁金服开放平台(百度搜索该平台,找到对应的API文档,https://open.alipay.com/api
),它是一种用于对接第三方的平台,作为双方之间互相调用的中间平台,提供一些接口说明,这些接口都是通过REST的方式来实现的。
三. 处理请求数据
3.1 请求处理方法签名
spring mvc通过分析处理方法的签名(指的是处理方法的名称以及参数列表),HTTP请求信息绑定到处理方法的相应的形参中。spring mvc对控制器处理方法签名的限制非常宽松,几乎可以按喜欢的任何方式对方法进行签名。
3.2 @RequestParam
获取请求参数
@RequestParam
用于获取请求的参数。
- 如果请求参数名与形参名一致,则可以省略@RequestParam的指定。
- @RequestParam注解标注的形参默认必须要能从请求对象中获取到对应的请求参数,可以设置
@RequestParam(value="age",required=false) Interger age
; - 可以设置默认值来指定一个默认值:
@RequestParam(value="age",required=false,defaultValue=“0”) int age
;
/**
@Controller:标注这个类是一个请求处理器
**/
@Controller
public class SpringMVCHandler{
/**
* 处理客户端请求:http://localhost:8080/springmvc01/hello
**/
@ResquestMapping(value="/hello")
public String handleHello(@RequestParam("username") String username,@RequestParam("age") Interger age){
//处理请求代码
System.out.println(username+" "+age);
//通过视图解析器解析得到具体的视图,再自动转发去往该视图
return "success";
}
}
3.3 @RequestHeader
映射请求头信息到请求处理方法的形参中
/**
@Controller:标注这个类是一个请求处理器
**/
@Controller
public class SpringMVCHandler{
@ResquestMapping(value="/hello")
public String handleHello(@RequestHeader("Accept-Language") String acceptLanguage){
//处理请求代码
System.out.println("acceptLanguage= "+acceptLanguage);
//通过视图解析器解析得到具体的视图,再自动转发去往该视图
return "success";
}
}
3.4 @CookieValue
注解
使用@CookieValue
注解绑定请求中的cookie信息,映射cookie的信息到请求处理方法的形参中。
/**
@Controller:标注这个类是一个请求处理器
**/
@Controller
public class SpringMVCHandler{
@ResquestMapping(value="/hello")
public String handleHello(@CookieValue("JSESSIONID") String sessionId){
//处理请求代码
System.out.println("sessionId="+sessionId);
//通过视图解析器解析得到具体的视图,再自动转发去往该视图
return "success";
}
}
3.5 使用POJO作为参数
使用POJO对象绑定请求参数值,spring mvc会按请求参数名和POJO属性名进行自动匹配,自动为该对象填充属性值,支持级联属性,如dept.deptid、dept.adress.tel等。
如:User类及Address 如下
public class User{
private String username;
private String password;
private String email;
private String gender;
private Address address;
/**
get()及set()、toString()方法
**/
}
public class Address {
private String province;
private String city;
/**
get()及set()、toString()方法
**/
}
index.jsp中:
<form action="testPOJO" method="post">
用户名称:<input type="text" name="username"/><br/>
用户密码:<input type="text" name="password"/><br/>
用户邮箱:<input type="text" name="email"/><br/>
用户性别:男<input type="radio" name="gender" value=“1”/>
女<input type="radio" name="gender" value=“0”/> <br/>
用户省份:<input type="text" name="address.province"/><br/>
用户城市:<input type="text" name="address.city"/><br/>
<input type="submit" value="注册"/>
</form>
控制器处理方法:
/**
@Controller:标注这个类是一个请求处理器
**/
@Controller
public class SpringMVCHandler{
@ResquestMapping(value="/testPOJO")
public String testPOJO(User user){
//处理请求代码
System.out.println("user="+user);
//通过视图解析器解析得到具体的视图,再自动转发去往该视图
return "success";
}
}
3.6 使用Servlet原生API作为参数
Servlet原生API如Request、Response等对象,MVC的处理方法可以接受包括HttpServletRequest、HttpServletResponse、HttpSession、InputStream、OutputStream、Reader、Writer
等Servlet API类型的参数。
@Controller
public class SpringMVCHandler{
@ResquestMapping(value="/testServletAPI")
public void testServletAPI(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException{
//处理请求代码
System.out.println("request="+request);
System.out.println("response="+response);
//请求转发
request.getRequesrDispatcher("/WEN-INF/views/success.jsp").forward(request,response);
//重定向,将数据写给客户端
response.sendRedirect("http://www.baidu.com");
//写
response.getWriter.println("hello springmvc");
}
}
四. 处理响应数据
spring mvc提供了以下几种途径输出模型数据:
- ModelAndView:处理方法返回值类型为ModelAndView时,方法体即可通过该对象添加模型数据。
- Map及Model:入参为org.springframework.ui.Model。
org.springframework.ui.Model或者ModelAndView时,处理方法返回时,Map中数据会自动添加到模型中。
4.1 ModelAndView处理模型数据
处理器方法的返回值如果为ModelAndView,则其既包含视图信息,也包含模型以及数据信息。在添加模型数据时,可以使用(1)ModelAndView addObject(String attributeName,Object atrributeValue)
;(2)ModelAndView addAllObject(Map<String,?> modelMap)
。除此之外,设置视图可以使用(1) void setView(View view)
;(2)void setViewName(String viewName)
。
@Controller
public class SpringMVCHandler{
@ResquestMapping(value="/testModelAndView ")
public ModelAndView testModelAndView () {
//模型数据:username=admin
ModelAndView mav=new ModelAndView();
//添加模型数据
mav.addObject("username","admin");
//设置视图信息
mav.setViewName("success");
return mav;
}
}
随后,在success的jsp页面中使用username:${username}
便可以获取得到username的值。username:${username}
写法默认会从四个域对象pageScope、requestScope、sessionScope以及applicationScope中去找,我们也可通过指定某一个域来限定,比如username:${requestScope.username}
。值得一提的是,springmvc会把ModelAndView 中的模型数据放到request域对象requestScope中。
4.2 Map及Model处理模型数据
(1)MAP
@Controller
public class SpringMVCHandler{
@ResquestMapping(value="/testMap ")
public String testMap (Map<String,Object> map) {
//模型数据:username=admin
map.put("username","admin");
return "success";
}
}
随后,在success的jsp页面中使用username:${requestScope.username}
便可以获取得到username的值。实际上,springmvc会把Map中的模型数据放到request域对象requestScope中。springmvc在调用完请求处理方法后,不管方法的返回值是什么类型,都会处理成一个ModelAndView对象。
(2)Model
@Controller
public class SpringMVCHandler{
@ResquestMapping(value="/testModel ")
public String testModel (Model model) {
//模型数据:username=admin
model.addAtribute("username","admin");
return "success";
}
}
随后,在success的jsp页面中使用username:${requestScope.username}
便可以获取得到username的值。实际上,springmvc会把Map中的模型数据放到request域对象requestScope中。springmvc在调用完请求处理方法后,不管方法的返回值是什么类型,都会处理成一个ModelAndView对象。