Spring 学习笔记3——SpringMVC HTTP请求

本文学习资源来自:《SpringMVC实战指南》
《Spring 3.x企业应用开发实战》

实例

  1. 使用MyEclipse新建web站点
  2. 添加Spring引用
    这里写图片描述

  3. 修改 web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://java.sun.com/xml/ns/javaee"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
    version="3.0">
    <display-name>Web</display-name>
    <!--    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:applicationContext.xml</param-value>
    </context-param>  -->
    <!-- 添加下面部分 -->
    <servlet>
        <servlet-name>dispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>dispatcherServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
    <!-- 注释掉这部分,是把xml写到src/下的写法
        <servlet>
        <servlet-name>springmvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
              <param-name>contextConfigLocation</param-name>
              <param-value>classpath:springmvc-servlet.xml</param-value>
          </init-param>
         <load-on-startup>1</load-on-startup> 
    </servlet> 
    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
     -->
</web-app>

web.xml说明

  • load-on-startup:表示启动容器时初始化该Servlet;
  • url-pattern:表示哪些请求交给Spring Web MVC处理, “/” 是用来定义默认servlet映射的。也可以如“*.html”表示拦截所有以html为扩展名的请求。

在WEB-INF下新建文件:dispatcherServlet-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/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">

    <!-- 自动扫描的包名 -->
    <context:component-scan base-package="com.test.controller"></context:component-scan>

    <!-- 默认的注解映射的支持 -->
    <mvc:annotation-driven />

    <!-- 视图解释类 -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/Views/" />
        <!--可为空,方便实现自已的依据扩展名来选择视图解释类的逻辑 -->
        <property name="suffix" value=".jsp" />
    </bean>
</beans>

新建Hello.java

package com.test.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class Hello {
    @RequestMapping(value = "/hello")
    public String hello() {
        System.out.println("spring mvc hello world!");
        return "hello";
    }
}

项目结构如下:
这里写图片描述

运行
这里写图片描述

访问:
http://localhost:8080/Web/hello

命令行输出结果:
这里写图片描述

Spring MVC3.0新特性

  • 支持REST风格的URL
  • 添加更多注解,可完全注解驱动
  • 引入HTTP输入输出转换器
  • 和数据转换、格式化、验证框架无缝集成
  • 对静态资源处理提供特殊支持
  • 更加灵活的控制器方法签名,可完全独立于Servlet API

Spring MVC 框架结构

这里写图片描述

package com.baoming.web;
...
@Controller
@RequestMapping("/user")
public class UserController{
   @RequestMapping(value="/register")
   public String register(){
      return "user/register";
   }
}

SpringMVC运行流程分析

这里写图片描述

说明:
1. 若一个请求匹配 DispatcherServlet 的请求映射路径(在 web.xml 中指定), WEB容器将该请求转交给 DispatcherServlet 处理
2. DispatcherServlet 接收到请求后, 将根据请求信息(包括 URL、HTTP 方法、请求头、请求参数、Cookie 等)及 HandlerMapping 的配置找到处理请求的处理器(Handler).可将 HandlerMapping 看成路由控制器,将 Handler 看成目标主机。
3. 当 DispatcherServlet 根据 HandlerMapping 得到对应当前请求的 Handler 后,通过 HandlerAdapter 对 Handler 进行封装,再以统一的适配器接口调用 Handler。
4. 处理器完成业务逻辑的处理后将返回一个 ModelAndView 给 DispatcherServlet,ModelAndView 包含了视图逻辑名和模型数据信息
5. DispatcherServlet 借助 ViewResoler 完成逻辑视图名到真实视图对象的解析
6. 得 到 真 实 视 图 对 象 View 后 , DispatcherServlet 使 用 这 个 View 对ModelAndView 中的模型数据进行视图渲染

HTTP请求映射原理

这里写图片描述

@RequestMapping

不但支持标准的URL,还支持Ant网格(即?、、*等字符)和带{xxx}占位的URL。
示例

  • /user/*/createUser
  • /user/**/createUser
  • /user/createUser??
  • /user/{userId}
  • /user/**/{userId}
  • comapny/{companyId}/user/{userId}/detail

通过URL限定,绑定{xxx}中的值

@RequestMapping("/{userId}")
public ModelAndView showDetail(@PathVariable("userId") String userId){
    ModelAndView mav = new ModelAndView();
    mav.setViewName("user/showDetail");
    mav.addObject("user", userService.getUserById(userId));
    return mav;
}

示例中URL中的{xxx}占位符可以通过@PathVariable(“xxx”)绑定到操作方法的入参中。

@Controller
@RequestMapping("/owners/{ownerId}")
public class RelativePathUriTemplateController {
    @RequestMapping("/pets/{petId}")
    public void findPet(@PathVariable String ownerId,
    @PathVariable String petId, Model model) {
    …
    }
}

如果@PathVariable不指定参数名,只有在编译时打开debug开关(javac-debug=no)时才行,不建议这样操作。

通过请求方法限定:请求方法

示例

@RequestMapping(value="/delete", method=RequestMethod.POST )
public String test1(@RequestParam("userId") String userId){
    return "user/test1";
}

通过在web.xml中配置一个org.springframework.web.filter.HiddenHttpMethodFilter通过POST请求的_method参数指定请求方法,HiddenHttpMethodFilter动态更改HTTP头信息。

通过请求参数限定

@RequestMapping(value="/delete", params="userId")
public String test1(@RequestParam("userId") String userId){
    ...
}

通过请求头参数限定

@RequestMapping(value="/show",headers="content-type=text/*")
public String test2(@RequestParam("userId") String userId){
    ...
}

params和headers分别通过请求参数及报文头属性进行映射,它们支持简单的表达式。
params表达式示例

  • “param1”:表示请求必须包含名为param1的请求参数
  • “!param1”:表示请求不能包含名为param1的请求参数
  • “param1!=value1”:表示请求包含名为param1的请求参数,但其值不能为value1
  • {“param1=value1”,”param2”} :请求必须包含名为param1和param2的两个请求参数,且param1参数的值必须为value1

通过注解绑定示例

@RequestMapping(value="/handle1")
public String handle1(@RequestParam("userName") String userName,
@RequestParam("password") String password,
@RequestParam("realName") String realName){
    ...
}
@RequestMapping(value="/handle2")
public String handle2(@CookieValue("JSESSIONID") String sessionId,
@RequestHeader("Accept-Language") String accpetLanguage){
    ...
}

@RequestParam有以下三个参数:

  • value:参数名
  • required:是否必须,默认为true,表示请求中必须包含对应的参数名,如果不存在将抛出异常
  • defalutValue:默认参数名,设置该参数时,自动将required设为false。一般不需要设置。

使用命令/表单对象绑定

所谓命令/表单对象并不需要实现任何接口,仅是一个拥有若干属性的POJO。Spring MVC按:
”HTTP请求参数名=命令/表单对象的属性名“
的规则,自动绑定请求数据,支持级联属性名,自动进行基本类型数据转换。

@RequestMapping(value="/handle14")
public String handle14(User user){
   ...
}

这时传递的参数:
userName=xxx&password=yyy
会被转换成:

class User{
    private String userName;
    private String password;
}

使用Servlet API对象作为入参

在Spring MVC中,控制类可以不依赖任何Servlet API对象,但是Spring MVC并不阻止我们使用Servlet API的类作为处理方法的入参。值得注意的是,如果处理方法自行使用HttpServletResponse返回响应,则处理方法的返回值设置成void即可。

@RequestMapping(value = "/handle21")
public void handle21(HttpServletRequest request,HttpServletResponse response) {
    String userName = WebUtils.findParameterValue(request, "userName");
    response.addCookie(new Cookie("userName", userName));
}
public String handle23(HttpSession session) {
session.setAttribute("sessionId", 1234);
    return "success";
}
public String handle24(HttpServletRequest request,
@RequestParam("userName")String userName) {
    …
    return "success";
}

使用Spring 的 Servlet API代理类

Spring MVC在org.springframework.web.context.request包中定
义了若干个可代理Servlet原生API类的接口,如WebRequest和NativeWebRequest,它们也允许作为处理类的入参,通过这些代理类可访问请求对象的任何信息。

@RequestMapping(value = "/handle25")
public String handle25(WebRequest request) {
    String userName = request.getParameter("userName");
    return "success";
}

使用IO对象作为入参

@RequestMapping(value = "/handle31")
public void handle31(OutputStream os) throws IOException{
    Resource res = new ClassPathResource("/image.jpg");//读取类路径下的图片文件
    FileCopyUtils.copy(res.getInputStream(), os);//将图片写到输出流中
}

其它类型的参数

  • java.util.Locale
  • java.security.Principal

使用@RequestBody/@ResponseBody

@RequestMapping(value = "/handle41")
public String handle41(@RequestBody String requestBody ) {
    System.out.println(requestBody);
    return "success";
}
@ResponseBody
@RequestMapping(value = "/handle42/{imageId}")
public byte[] handle42(@PathVariable("imageId") String imageId) throws IOException {
    System.out.println("load image of "+imageId);
    Resource res = new ClassPathResource("/image.jpg");
    byte[] fileData =FileCopyUtils.copyToByteArray(res.getInputStream());
    return fileData;
}

使用HttpEntity/ResponseEntity

@RequestMapping(value = "/handle43")
public String handle43(HttpEntity<String> httpEntity){
    long contentLen = httpEntity.getHeaders().getContentLength();
    System.out.println(httpEntity.getBody());
    return "success";
}
@RequestMapping(params = "method=login")
public ResponseEntity<String> doFirst(){
    HttpHeaders headers = new HttpHeaders();
    MediaType mt=new MediaType("text","html",Charset.forName(“UTF-8"));
    headers.setContentType(mt);
    ResponseEntity<String> re=null;
    String return = new String("test");
    re=new ResponseEntity<String>(return,headers, HttpStatus.OK);
    return re;
}
@RequestMapping(value = "/handle51")
public ResponseEntity<User> handle51(HttpEntity<User> requestEntity){
    User user = requestEntity.getBody();
user.setUserId("1000");
    return new ResponseEntity<User>(user,HttpStatus.OK);
}

控制输出XML/JSON




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

编程圈子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值