SpringMVC的请求和响应

导读:本篇文章讲解 SpringMVC的请求和响应,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

SpringMVC的请求和响应

一、SpringMVC的响应

SpringMVC的数据响应方式有以下:

  1. 页面跳转
    1. 直接返回字符串
    2. 通过ModelAndView对象返回
  2. 回写数据
    1. 直接返回字符串
    2. 返回对象或者集合

1、页面跳转


1.1、直接返回字符串

在SpringMVC入门的代码中就是采用了直接返回字符串的形式了来实现页面的跳转

    @RequestMapping(value = "/quick", method = RequestMethod.GET, params = {"username"})   //请求映射
    public String quickMethod(){
        System.out.println("quickMethod running.......");
        //return:要跳转的视图
        //要加一个/表示当前web目录下
        return "quick";
    }

1.2、通过ModelAndView对象返回

ModelAndView代表的是SpringMVC中的M和V

主要作用是设置转向地址,将获取到的数据进行存储,然后将数据传递到View(视图中)

存储的数据都可以通过EL表达式在jsp文件中使用

其主要方法如下:

  • setViewName(String viewName):‎设置此 ModelAndView 的视图名称, 由 DispatcherServlet 通过 ViewResolver 解析‎
  • addObject(String attributeName, Object attributeValue):通过key/value的方式绑定数据

ModelAndView的创建有两种方式:

  • 自行new一个ModelAndView对象
  • ModelAndView作为参数,由springMVC框架自动创建
    @RequestMapping(value = "/quick3")   //请求映射
    public ModelAndView quickMethod3(ModelAndView modelAndView){
        //ModelAndView对象作为形参,由SpringMVC框架自行创建
        modelAndView.setViewName("quick");
        modelAndView.addObject("username", "喜羊羊");
        return modelAndView;
    }

    @RequestMapping(value = "/quick2")   //请求映射
    public ModelAndView quickMethod2(){
        //自己创建ModelAndView对象
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("quick");
        modelAndView.addObject("username", "小明");
        return modelAndView;
    }

1.3、其他

可以通过Javaweb学的HttpServletRequest对象把数据存储在域中,然后转发到相应的视图,再利用EL表达式展示

也可以利用Model对象进行存储数据

    @RequestMapping(value = "/quick5")   //请求映射
    public String quickMethod5(HttpServletRequest request){
        request.setAttribute("username", "红太狼");
        return "quick";
    }


    @RequestMapping(value = "/quick4")   //请求映射
    public String quickMethod4(Model model){
        model.addAttribute("username", "灰太狼");
        return "quick";
    }

2、回写数据

2.1、直接返回字符串

回写数据在JavaWeb阶段也学习过,使用response对象进行回写

    @RequestMapping(value = "/quick6")   //请求映射
    public void quickMethod6(HttpServletResponse response) throws IOException {
        response.getWriter().println("Hello kang");
    }

这种方法在开发中并不常用,可以使用@ResponseBody注解可以告知SpringMVC框架,方法返回的字符串不是跳转而是直接在http响应体内返回(不写该注释默认返回视图的名称)

    @RequestMapping(value = "/quick8")   //请求映射
    @ResponseBody
    public String quickMethod8() throws IOException {
        //回写json
        return "{\"username\":\"zhangsan\",\"age\":18}";
    }

    @RequestMapping(value = "/quick7")   //请求映射
    @ResponseBody
    public String quickMethod7(HttpServletResponse response) throws IOException {
        //回写字符串
        return "Hello quick7";
    }

一般开发中返回json的操作比较多,但是自己手动编写json比较麻烦,因此Java中提供了Java对象转json对象的工具类

  • 使用JSON.toJSONString(Object)需要导入依赖

        <dependency>
          <groupId>com.alibaba</groupId>
          <artifactId>fastjson</artifactId>
          <version>1.2.62</version>
        </dependency>
    
  • 使用objectMapper.writeValueAsString()也需要导入依赖

        <!--jackson-->
        <dependency>
          <groupId>com.fasterxml.jackson.core</groupId>
          <artifactId>jackson-core</artifactId>
          <version>2.9.0</version>
        </dependency>
    
        <dependency>
          <groupId>com.fasterxml.jackson.core</groupId>
          <artifactId>jackson-databind</artifactId>
          <version>2.9.0</version>
        </dependency>
        
        <dependency>
          <groupId>com.fasterxml.jackson.core</groupId>
          <artifactId>jackson-annotations</artifactId>
          <version>2.9.0</version>
        </dependency>
    
    @RequestMapping(value = "/quick10")   //请求映射
    @ResponseBody
    public String quickMethod10() throws IOException {
        User user = new User();
        user.setName("lisi");
        user.setAge(20);
        return JSON.toJSONString(user);
    }

    @RequestMapping(value = "/quick9")   //请求映射
    @ResponseBody
    public String quickMethod9() throws IOException {
        User user = new User();
        user.setName("lisi");
        user.setAge(20);
        ObjectMapper objectMapper = new ObjectMapper();
        return objectMapper.writeValueAsString(user);
    }

2.2、返回对象或者集合

除了上面自己手动将Java对象转为JSON对象外,SpringMVC会自动帮我们将对象或者集合进行json字符串的转换并回写

这需要我们为处理器适配器配置消息转换参数指定jackson进行对象或者集合的转换,因此需要在spring-mvc进行如下配置(配置的目的是为了告诉springmvc,我们返回的对象需要用到这个json转换器来转换)

(注意要加入mvc的空间)

<?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.kang.controller">
        <!--扫描com.kang.controller包下的Controller注解-->
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>

    <!--配置内部资源视图解析器-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <!--配置前缀-->
        <property name="prefix" value="/jsp/"></property>
        <!--配置后缀-->
        <property name="suffix" value=".jsp"></property>
    </bean>

    <!--配置处理器映射器-->
    <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
        <property name="messageConverters">
            <list>
                <!--配置json转换工具-->
                <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"></bean>
            </list>
        </property>
    </bean>

</beans>

配置完成之后,就不要再返回字符串,而是直接返回对象或者集合,SpringMVC框架会自动帮我们完成Json对象的转化并回写

    @RequestMapping(value = "/quick11")   //请求映射
    @ResponseBody
    public User quickMethod11() throws IOException {
        User user = new User();
        user.setName("liu");
        user.setAge(20);
        return user;
    }

2.3、提升(重要)

上述通过配置spring-mvc.xml中的处理器映射器来实现java对象转化为json对象,但是这样的配置操作会很多,因此我么可以用mvc的注解驱动来简化以上操作

    <!--注解驱动-->
    <mvc:annotation-driven/>

在SpringMVC的各个组件中,处理器映射器、处理器适配器、视图解析器成为SpringMVC的三大组件,使用自动加载 RequestMappingHandlerMapping(处理映射器)和 RequestMappingHandlerAdapter( 处 理 适 配 器 ),可用在Spring-xml.xml配置文件中使用 替代注解处理器和适配器的配置。 同时使用默认底层就会集成jackson进行对象或集合的json格式字符串的转换。


二、SpringMVC获得请求数据

一般来讲,客户端请求数据一般都是这种格式:name=XXX&password=XXX

在Javaweb阶段,这些请求数据都需要程序猿对数据进行封装和处理

但是在SpringMVC框架中,这些相应的封装可以由框架完成

SpringMVC可以接受如下的类型的参数:

  • 基本类型参数
  • POJO类型参数
  • 数组类型参数
  • 集合类型参数

1、基本类型参数

Controller中的业务方法的参数名称要与请求参数的name一致,参数值会Spring框架就会自动映射匹配。

    @RequestMapping(value = "/quick12")   //请求映射
    @ResponseBody
    public void quickMethod12(String username, int age){
        System.out.println(username);
        System.out.println(age);
    }
http://localhost:8080/SpringMVC/quick12?username=zhangsan&age=12

2、POJO类型参数

Controller中的业务方法的POJO参数的属性名与请求参数的name一致,参数值会自动映射匹配。

    public class User {
    	private String name;
    	private int age;
    	get/set
    }
    
    
    @RequestMapping(value = "/quick13")   //请求映射
    @ResponseBody
    public void quickMethod13(User user){
        System.out.println(user.getName());
        System.out.println(user.getAge());
    }
http://localhost:8080/SpringMVC/quick13?username=zhangsan&age=12

3、数组类型参数

Controller中的业务方法数组名称与请求参数的名称一致,参数值会自动映射匹配。

    @RequestMapping(value = "/quick14")   //请求映射
    @ResponseBody
    public void quickMethod14(String[] strs){
        System.out.println(Arrays.asList(strs));
    }
http://localhost:8080/SpringMVC/quick14?strs=111&strs=222&strs=333

4、集合类型参数

获取集合的请求数据的方法有两种

  • 将集合参数包装到一个POJO类中
  • 使用ajax提交

4.1、将集合参数包装到一个POJO类中(了解)

  • 首先讲集合包装到一个POJO类中

    package com.kang.poj;
    
    import java.util.List;
    
    public class Vo {
        List<User> userList;
    
        public List<User> getUserList() {
            return userList;
        }
    
        public void setUserList(List<User> userList) {
            this.userList = userList;
        }
    
        @Override
        public String toString() {
            return "Vo{" +
                    "userList=" + userList +
                    '}';
        }
    }
    
  • 编写Controller

        @RequestMapping(value = "/quick15")   //请求映射
        @ResponseBody
        public void quickMethod15(Vo vo){
            System.out.println(vo);
        }
    
  • 编写对应的jsp

    <%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
    <html>
    <head>
        <title>Title</title>
    </head>
    <body>
        <form action="${pageContext.request.contextPath}/user/quick15" method="post">
            <input type="text" name="userList[0].name"><br>
            <input type="text" name="userList[0].age"><br>
            <input type="text" name="userList[1].name"><br>
            <input type="text" name="userList[1].age"><br>
            <input type="submit" value="提交">
        </form>
    </body>
    </html>
    

通过这种方法,表单提交的数据就会提交到quick15中去,对应的Controller业务方法里面是一个POJO类

然后就会根据input标签的name匹配对应的集合的位置,然后存储数据进去,进而完成集合类型参数的包装

但是这种方法并不推荐


4.2、使用ajax提交

当使用ajax提交时,可以指定contentType为json形式,那么在方法参数位置使用@RequestBody可以 直接接收集合数据而无需使用POJO进行包装。

${pageContext.request.contextPath}就是获得对应的虚拟地址,也就是SpringMVC这个地址


<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<script src="js/jquery-3.6.0.js"></script>
<script>
    var userList = new Array();
    userList.push({name: "zhangsan", age: "20"});
    userList.push({name: "lisi", age: "18"});
    $.ajax({
        type: "POST",
        url: "${pageContext.request.contextPath}/user/quick16",
        data: JSON.stringify(userList),
        contentType: 'application/json;charset=utf-8'
    });
</script>
</body>
</html>

但是当访问这个jsp文件的时候,发现jquery-3.6.0.js并未被加载

这是因为SpringMVC的前端控制器DispatcherServlet的url-pattern配置的是/,是代表对所有的资源进行过来操作

也就是说本来请求是找js/jquery-3.6.0.j这个文件的,但是springMVC认为是找类似@RequestMapping(value = “/quick15”)的资源,所以匹配找不到

因此,可以通过以下两种方式指定放行静态资源:

  • 在spring-mvc.xml配置文件中指定放行的资源
<mvc:resources mapping="/js/**" location="/js/"/>
  • 交给tomcat处理

    <mvc:default-servlet-handler/>
    
    • 这个xml配置的意思找资源的时候,首先找@RequestMapping中的匹配的地址,如果找不到的话,那么就交给原始容器tomcat去找,tomcat没有拦截,所以可以找到对应的静态资源
    @RequestMapping(value = "/quick16")   //请求映射
    @ResponseBody
    public void quickMethod16(@RequestBody List<User> userList){
        System.out.println(userList);
    }

5、请求数据乱码问题

当使用post请求的时候,倘若输入的是中文,那么控制台输出就会是乱码,这时候我们可以在web.xml设置一个过滤器来进行编码的过滤

  <!--配置全局过滤的filter-->
  <filter>
    <filter-name>CharacterEncodingFilter</filter-name>
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    <init-param>
      <param-name>encoding</param-name>
      <param-value>UTF-8</param-value>
    </init-param>
  </filter>
  <filter-mapping>
    <filter-name>CharacterEncodingFilter</filter-name>
        <!--对任何资源都起作用-->
    <url-pattern>/*</url-pattern>
  </filter-mapping>

6、参数绑定注解@requestParam

前后端分离的项目中,难免会出现前端工程师给某一个input命名的name和后端工程师给对应Controller命名的形参名称不一样

这时候就可以使用@requestParam来进行参数绑定

  • value:请求参数名称
  • required:此在指定的请求参数是否包括,默认为true,提交时如果没有此参数则会报错
  • defaultValue:当没有指定请求参数的时候,则使用指定的默认值赋值
    @RequestMapping(value = "/quick17")   //请求映射
    @ResponseBody
    public void quickMethod17(@RequestParam(value = "name", required = false, defaultValue = "kang") String userName){
        System.out.println(userName);
    }

7、 获得Restful风格的参数(了解)

Restful是一种软件架构风格、设计风格,而不是标准,只是提供了一组设计原则和约束条件。主要用于客户端和服务 器交互类的软件,基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存机制等。

Restful风格的请求是使用“url+请求方式”来表示一次目的,HTT协议里面四个表示操作方式的动词如下:

  • GET:用于获取资源
  • POST:用于新建资源
  • PUT:用于更新资源
  • DELETE:用于删除资源

例如:

  • /user/1 GET: 得到id=1的user
  • /user/1 DELETE: 删除id=1的user
  • /user/1 PUT: 更新id=1的user
  • /user POST: 新增user

上述url地址/user/1中的1就是要获得的请求参数,在SpringMVC中可以使用占位符进行参数绑定地址/user/1可以写成 /user/{id},占位符{id}对应的就是1的值

在业务方法中我们可以使用@PathVariable注解进行占位符的匹配获取工作。

    @RequestMapping(value = "/quick18/{username}")   //请求映射
    @ResponseBody
    public void quickMethod18(@PathVariable(value = "username") String userName){
        System.out.println(userName);
    }

8、自定义类型转换器

SpringMVC 默认已经提供了一些常用的类型转换器,例如客户端提交的字符串转换成int型进行参数设置。

但是不是所有的数据类型都提供了转换器,没有提供的就需要自定义转换器,例如:日期类型的数据就需要自 定义转换器。

自定义类型转换器的开发步骤:

  1. 定义转换器类实现Converter接口

    package com.kang.converter;
    
    import org.springframework.core.convert.converter.Converter;
    
    import java.text.ParseException;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    
    /**
     * @ClassName DataConverter
     * @Description TODO
     * @Author kang
     * @Date 2022/2/27 下午 2:18
     * @Version 1.0
     */
    public class DataConverter implements Converter<String, Date> {
        @Override
        public Date convert(String s) {
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
            Date date = null;
            try {
                date = simpleDateFormat.parse(s);
            } catch (ParseException e) {
                e.printStackTrace();
            }
            return date;
        }
    }
    
  2. 在配置文件中声明转换器

        <!--配置文件中声明转换器-->
        <bean id="converterService" class="org.springframework.context.support.ConversionServiceFactoryBean">
            <property name="converters">
                <list>
                    <bean class="com.kang.converter.DataConverter"></bean>
                </list>
            </property>
        </bean>
    
  3. 在< annotation-driven >中引用转换器

    <!--注解驱动-->
    <mvc:annotation-driven conversion-service="converterService"/>

9、 获得请求头

9.1、 @RequestHeader

使用@RequestHeader可以获得请求头信息,相当于web阶段学习的request.getHeader(name) @RequestHeader注解的属性如下:

  • value:请求头的名称
  • required:是否必须携带此请求头
    @RequestMapping(value = "/quick21")   //请求映射
    @ResponseBody
    public void quickMethod21(@RequestHeader(value = "User-Agent", required = false) String userAgent){
        System.out.println(userAgent);
    }

9.2、 @CookieValue

使用@CookieValue可以获得指定Cookie的值 @CookieValue注解的属性如下:

  • value:指定cookie的名称
  • required:是否必须携带此cookie
    @RequestMapping(value = "/quick22")   //请求映射
    @ResponseBody
    public void quickMethod22(@CookieValue(value = "JSESSIONID", required = false) String cookie){
        System.out.println(cookie);
    }

10、文件上传的实现

在网页中经常能看见需要我们上传文件

文件上传的原理:

  • 当form表单修改为多部分表单时,request.getParameter()将失效。

  • enctype=“application/x-www-form-urlencoded”时,form表单的正文内容格式是:

    key=value&key=value&key=value

  • 当form表单的enctype取值为Mutilpart/form-data时,请求正文内容就变成多部分形式:

设置为多部份表单的时候,不再是键值对的形式,所以无法通过getParameter()方法获取数据

在这里插入图片描述


10.1、单文件上传步骤

  • 导入fileupload和io坐标
    <dependency>
      <groupId>commons-fileupload</groupId>
      <artifactId>commons-fileupload</artifactId>
      <version>1.2.2</version>
    </dependency>
    <dependency>
      <groupId>commons-io</groupId>
      <artifactId>commons-io</artifactId>
      <version>2.4</version>
    </dependency>
  • 配置文件上传解析器
    <!--文件上传解析器-->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <!--上传文件总大小-->
        <property name="maxInMemorySize" value="5242800"/>
        <!--上传单个文件的大小-->
        <property name="maxUploadSizePerFile" value="5242800"/>
        <!--上传文件的编码类型-->
        <property name="defaultEncoding" value="UTF-8"/>
    </bean>
  • 编写文件上传代码
    @RequestMapping(value = "/quick23")   //请求映射
    @ResponseBody
    public void quickMethod23(String name, MultipartFile uploadFile) throws IOException {
        //获取文件名
        String originalFilename = uploadFile.getOriginalFilename();
        //保存文件
        uploadFile.transferTo(new File("F:\\笔记记录\\文件上传test\\" + originalFilename));
    }
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <form action="${pageContext.request.contextPath}/user/quick23" method="post" enctype="multipart/form-data">
        名称<input type="text" name="username"><br>
        文件<input type="file" name="uploadFile"><br>
        <input type="submit" value="提交">
    </form>
</body>
</html>

10.2、多文件上传实现

​ 可以使用数组来实现

    @RequestMapping(value = "/quick24")   //请求映射
    @ResponseBody
    public void quickMethod24(String name, MultipartFile[] uploadFile) throws IOException {
        for (MultipartFile multipartFile : uploadFile) {
            //获取文件名
            String originalFilename = multipartFile.getOriginalFilename();
            //保存文件
            multipartFile.transferTo(new File("F:\\笔记记录\\文件上传test\\" + originalFilename));
        }
    }

<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <form action="${pageContext.request.contextPath}/user/quick24" method="post" enctype="multipart/form-data">
        名称<input type="text" name="username"><br>
        文件1:<input type="file" name="uploadFile"><br>
        文件2:<input type="file" name="uploadFile"><br>
        <input type="submit" value="提交">
    </form>
</body>
</html>

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由半码博客整理,本文链接:https://www.bmabk.com/index.php/post/95018.html

(0)

相关推荐

半码博客——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!