当前位置: 首页 > news >正文

Spring MVC的请求和响应

一、SpringMVC请求与响应的基本理论

在Web应用中,请求与响应是前端与后端之间的主要交互方式。具体到Spring MVC框架,请求通常指客户端发送到服务器的HTTP请求,而响应指服务器对请求的反馈。

请求与响应的处理流程

  1. HTTP请求:客户端(如浏览器)发送请求(包括请求路径、方法、参数等),Spring MVC通过DispatcherServlet接收到请求,进行处理。
  2. 控制器(Controller):根据请求的不同,DispatcherServlet会将请求分派到相应的控制器方法,进行逻辑处理。
  3. 视图解析(View Resolver):控制器返回的视图名称将通过视图解析器转换为具体的视图(如JSP页面、Thymeleaf模板等)。
  4. HTTP响应:控制器返回的数据可以通过视图渲染成HTML,也可以直接以JSON或XML格式返回给客户端。

Spring MVC 请求-响应流程图

二、RequestMapping注解

RequestMapping注解的作用是建立请求URL和处理方法之间的对应关系

RequestMapping注解可以作用在方法和类上

1. 作用在类上:第一级的访问目录

2. 作用在方法上:第二级的访问目录

3. 细节:路径可以不编写 / 表示应用的根目录开始

1、RequestMapping的属性

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

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Controller
@RequestMapping("/Hello")// 路径不能一样
public class HelloController {
    // 返回页面
    // 最常用的方式
    @RequestMapping("/toA")
    public String toA(){
        return "A";
    }

    // jsp的形式
    // 还没被淘汰,使用比较少
    @RequestMapping("/toB")
    public ModelAndView toB(){
        ModelAndView mv =new ModelAndView();
        mv.addObject("msg","this is msg B");
        mv.setViewName("B");
        return  mv;
    }

    @RequestMapping("/test")
    public void test(HttpServletRequest request,HttpServletResponse response) throws IOException {
        response.getWriter().println("hello ,String");
    }
}

2、常用的 RequestMaping 属性

属性

说明

示例

value

映射的URL路径

@RequestMapping("/greet")

method

指定请求方法类型(GET, POST等)

@RequestMapping(method = RequestMethod.GET)

params

请求参数的条件

@RequestMapping(params = "id=1")

headers

请求头的条件

@RequestMapping(headers = "key=value")

produces

指定返回的内容类型(MIME类型)

@RequestMapping(produces = "application/json")

consumes

指定请求的内容类型

@RequestMapping(consumes = "application/json")

3、请求参数绑定

public String save3(@RequestParam(value = "name",required = false)String name){
    System.out.println(name);
    return "B";
}

三、转发和重定向

1、转发和重定向

Spring MVC支持两种类型的跳转:

  • 转发(forward):服务器端的请求转发,页面仍然保持在当前地址。
  • 重定向(redirect):客户端的请求重新发送,浏览器地址栏会发生变化。
// 请求转发————》只能在网站内部资源之间进行转发
/*
 * 请求转发本身是一种服务器端行为
 * 浏览器的地址栏不会发生任何变化
 * 从始至终都是一个请求
 * request信息在Servlet中是共享的,因为从始至终都是一个request
 * */
// 将test1中的request信息转发的test2中
@RequestMapping("/test1")
public void test1(HttpServletRequest request,HttpServletResponse response) throws IOException, ServletException {
    request.getRequestDispatcher("test2").forward(request,response);
}

@RequestMapping("/test2")
public void test2(HttpServletRequest request,HttpServletResponse response) throws IOException {
    String name = request.getParameter("name");
    String password = request.getParameter("password");
    System.out.println(name+ " "+ password);
}

// 重定向————》 可以访问站外资源
/*
* 本身是一种客户端行为
* 地址栏发生改变
* 浏览器会发起两次请求
*
* */
@RequestMapping("/test3")
public void test3(HttpServletRequest request,HttpServletResponse response) throws IOException, ServletException {
    response.sendRedirect("/SpringMVC_Demo/Hello/test4");
}

@RequestMapping("/test4")
public void test4(HttpServletRequest request,HttpServletResponse response) throws IOException {
    System.out.println("this msg ordered from test3");
}

// @RequestMapping("/t1")
// public String testt(){
//     return "B";
// }

/*
* SprintMVC 的请求和转发,不会走配置的页面路径
* */
@RequestMapping("/t1")
public String testt(){
    return "forward:/html/B.html";
}
@RequestMapping("/t2")
public String testt2(){
    return "redirect:/html/B.html";
}

2、返回JSON相应

Spring MVC支持自动将Java对象转化为JSON格式并返回。只需要在方法上使用 

@ResponseBody 注解即可。

import com.goose.model.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
@RequestMapping("/B")
public class BController {
    @RequestMapping("/find")
    @ResponseBody // 保证返回的数据是json格式
    public User find(){
        User user =new User("张三",12,'女');
        return user;
    }
}

四、实现文件上传和下载

1、文件上传

/**
 * 文件上传功能
 * @param file
 * @return
 * @throws IOException
 */
@RequestMapping(value="/upload",method= RequestMethod.POST)
@ResponseBody
public  String upload(@RequestParam("file") MultipartFile file, HttpServletRequest request) throws IOException {
    // uploads文件夹位置
    String rootPath = request.getSession().getServletContext().getRealPath("WEB-INF/upload");
    // 原始名称
    String originalFileName = file.getOriginalFilename();
    // 新文件
    File newFile = new File(rootPath + File.separator  + File.separator + originalFileName);
    // 判断目标文件所在目录是否存在
    if( !newFile.getParentFile().exists()) {
        // 如果目标文件所在的目录不存在,则创建父目录
        newFile.getParentFile().mkdirs();
    }
    System.out.println("----------");
    System.out.println("----------");
    System.out.println("----------");
    System.out.println("----------");
    System.out.println("----------");
    System.out.println("----------");
    System.out.println("----------");
    System.out.println(newFile);
    // 将内存中的数据写入磁盘
    file.transferTo(newFile);
    return  "{\"data\":\"success\"}";
}

文件上传常见问题

问题

解决方案

文件过大

CommonsMultipartResolver

中设置

maxUploadSize

文件名冲突

可通过自定义文件名生成逻辑解决(如加时间戳)

文件类型限制

可以通过

Content-Type

进行限制

2、文件下载(本地文件目录模拟数据库)

/**
 * 文件下载功能
 * @param request
 * @param response
 * @throws Exception
 */
@RequestMapping("/down")
public void down(HttpServletRequest request, HttpServletResponse response) throws Exception{
    String filename = request.getParameter("filename");
    System.out.println(filename);
    //模拟文件,myfile.txt为需要下载的文件
    String fileName = request.getSession().getServletContext().getRealPath("WEB-INF/upload")+"/"+filename;
    //获取输入流
    InputStream bis = new BufferedInputStream(new FileInputStream(new File(fileName)));
    //假如以中文名下载的话
    // String filename = "下载文件.txt";
    //转码,免得文件名中文乱码
    filename = URLEncoder.encode(filename,"UTF-8");
    //设置文件下载头
    response.addHeader("Content-Disposition", "attachment;filename=" + filename);
    //1.设置文件ContentType类型,这样设置,会自动判断下载文件类型
    response.setContentType("multipart/form-data");
    BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());
    int len = 0;
    while((len = bis.read()) != -1){
        out.write(len);
        out.flush();
    }
    out.close();
}

五、需要的配置文件

1、pom.xml

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.goose</groupId>
  <artifactId>SpringMVC_Demo</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>war</packaging>

  <name>SpringMVC_Demo Maven Webapp</name>
  <!-- FIXME change it to the project's website -->
  <url>http://www.example.com</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>8</maven.compiler.source>
    <maven.compiler.target>8</maven.compiler.target>
    <spring.version>5.0.2.RELEASE</spring.version>
  </properties>



  <dependencies>

    <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-core</artifactId>
      <version>2.9.0</version>
    </dependency>
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-annotations</artifactId>
      <version>2.9.0</version>
    </dependency>

    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>${spring.version}</version>
    </dependency>

    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-web</artifactId>
      <version>${spring.version}</version>
    </dependency>

    <!--SpringMVC-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>${spring.version}</version>
    </dependency>

    <!--servlet API-->
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>servlet-api</artifactId>
      <version>2.5</version>
      <scope>provided</scope>
    </dependency>

    <dependency>
      <groupId>javax.servlet.jsp</groupId>
      <artifactId>jsp-api</artifactId>
      <version>2.0</version>
      <scope>provided</scope>
    </dependency>

    <!--日志-->
    <dependency>
      <groupId>ch.qos.logback</groupId>
      <artifactId>logback-classic</artifactId>
      <version>1.2.3</version>
    </dependency>

    <dependency>
      <groupId>org.thymeleaf</groupId>
      <artifactId>thymeleaf-spring4</artifactId>
      <version>3.0.9.RELEASE</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-core</artifactId>
      <version>2.9.0</version>
    </dependency>
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-annotations</artifactId>
      <version>2.9.0</version>
    </dependency>
    <dependency>
      <groupId>commons-fileupload</groupId>
      <artifactId>commons-fileupload</artifactId>
      <version>1.3.1</version>
    </dependency>
    <dependency>
      <groupId>commons-io</groupId>
      <artifactId>commons-io</artifactId>
      <version>2.4</version>
    </dependency>
  </dependencies>

  <build>
    <finalName>SpringMVC_Demo</finalName>
    <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
      <plugins>
        <plugin>
          <artifactId>maven-clean-plugin</artifactId>
          <version>3.4.0</version>
        </plugin>
        <!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging -->
        <plugin>
          <artifactId>maven-resources-plugin</artifactId>
          <version>3.3.1</version>
        </plugin>
        <plugin>
          <artifactId>maven-compiler-plugin</artifactId>
          <version>3.13.0</version>
        </plugin>
        <plugin>
          <artifactId>maven-surefire-plugin</artifactId>
          <version>3.3.0</version>
        </plugin>
        <plugin>
          <artifactId>maven-war-plugin</artifactId>
          <version>3.4.0</version>
        </plugin>
        <plugin>
          <artifactId>maven-install-plugin</artifactId>
          <version>3.1.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-deploy-plugin</artifactId>
          <version>3.1.2</version>
        </plugin>
      </plugins>
    </pluginManagement>
  </build>
</project>

2、SpringMVC.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">

    <!--配置spring创建容器时要扫描的包-->
    <context:component-scan base-package="com.goose"></context:component-scan>

    <!--设置静态资源不过滤-->
    <mvc:resources mapping="/css/**" location="/css/"/> <!--样式-->
    <mvc:resources mapping="/images/**" location="/images/"/> <!--图片-->
    <mvc:resources mapping="/js/**" location="/js/"/> <!--javascript-->

    <!--配置文件上传的解析器组件。id的名称是固定,不能乱写-->
    <bean id="multipartResolver"
          class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <!--设置上传文件的总大小 8M = 8 * 1024 * 1024 -->
        <property name="maxUploadSize" value="8388608" />
    </bean>

    <!--处理映射器-->
    <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>

    <!--处理器适配器-->
    <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>

    <!--配置视图解析器-->
    <bean id="viewResolver" class="org.thymeleaf.spring4.view.ThymeleafViewResolver">
        <property name="order" value="1"/>
        <property name="characterEncoding" value="UTF-8"/>
        <property name="templateEngine" ref="templateEngine"/>
    </bean>
    <!-- templateEngine -->
    <bean id="templateEngine" class="org.thymeleaf.spring4.SpringTemplateEngine">
        <property name="templateResolver" ref="templateResolver"/>
    </bean>
    <bean id="templateResolver" class="org.thymeleaf.spring4.templateresolver.SpringResourceTemplateResolver">
        <property name="prefix" value="/html/" />
        <property name="suffix" value=".html" />
        <property name="templateMode" value="HTML5"/>
    </bean>
    <!-- JSON View -->
    <bean
            class="org.springframework.web.servlet.view.json.MappingJackson2JsonView">
    </bean>
    <!-- 配置spring开启注解mvc的支持  默认就是开启的 ,要想让其他组件(不包含映射器、适配器、处理器)生效就必须需要配置了-->
    <mvc:annotation-driven/>
</beans>

3、web.xml

<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
   http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">

    <!--在web.xml中配置Spring提供的过滤器类 -->
    <filter>
        <filter-name>encodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <async-supported>true</async-supported>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
    </filter>

    <filter-mapping>
        <filter-name>encodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <!--不拦截所有是html的页面请求-->
    <servlet-mapping>
        <servlet-name>default</servlet-name>
        <url-pattern>*.html</url-pattern>
    </servlet-mapping>

    <!--配置前端控制器,对浏览器发送的请求进行统一处理-->
    <servlet>
        <servlet-name>dispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!--加载springmvc.xml配置文件的位置和名称,配置的是Spring配置-->
        <init-param>
            <!--contextConfigLocation:上下文配置路径,固定值-->
            <param-name>contextConfigLocation</param-name>
            <!--classpath:类路径,值得是Java和resources文件夹-->
            <!--springmvc.xml:指的是配置文件的名称:需要配置springmvc.xml,在下面-->
            <param-value>classpath:SpringMVC.xml</param-value>
        </init-param>
        <!--配置启动加载-->
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>dispatcherServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

    <!--开启项目时打开的页面-->
    <welcome-file-list>
        <welcome-file>/index.html</welcome-file>
    </welcome-file-list>

</web-app>

4、file.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>this page for file updown and shangchuan</title>
</head>
<body>
    <h1>文件上传</h1>
        <form action="/SpringMVC_Demo/file/upload" method="post" enctype="multipart/form-data">
            选择文件:<input type="file" name="file" width="120px">
            <input type="submit" value="上传">
        </form>

    <div id="upMenu" class="white_content">
        <form id="downForm"   lay-filter="updata" action="/SpringMvc_Demo/file/down" method="get">
            请输入想要下载的文件名称:<input type="text" id="filename" name="filename">
            <input type="submit" value="下载">
        </form>
        <input type="button" value="完成"/>
    </div>
</body>
</html>

相关文章:

  • JavaScript 函数基础
  • IoTDB看门狗配置后不生效
  • 算法 | 小龙虾优化算法原理,引言,公式,算法改进综述,应用场景及matlab完整代码
  • ISIS-2 邻居建立关系
  • 4.1 C#获取目录的3个方法的区别
  • 【考研政治】2026考研政治马原部分关键词带背 导论
  • Mysql基本查询(上)
  • 情绪分析和深度强化学习确实能够在一定程度上增强股市预测
  • 实战-MySQL5.7升级8.0遇到的四个问题
  • 解决安卓so库异常无法打印堆栈的问题
  • 网络拓扑图
  • 区块链驱动金融第九章——解锁比特币 “平台” 的多元潜力
  • vue中ts引入组件,无法找到模块xxx的声明文件。xxx隐式拥有 “any“ 类型。
  • HTTP长连接与短连接的前世今生
  • 【商城实战(63)】配送区域与运费设置全解析
  • Python字典
  • Flume-试题
  • TCP/IP 协议栈深度解析
  • 在我的电脑上构建ollama+deepseek-r1-7b运行环境;
  • C++相关
  • 已婚女子谎称单身恋爱2年多,骗取男友38.8万元彩礼被刑拘
  • 专访|导演王沐:希望听障家庭的声响被更多人听到
  • 家国万里,从家庭叙事看超大城市文明治理的上海方案
  • 31只北交所主题基金齐刷净值纪录,年内最高涨超80%,已有产品打出“限购牌”
  • 失智老人有两个儿子却欠费住养老院两年多,法检合力指定监护人
  • 中国华能:1-4月新能源装机突破1亿千瓦,利润总额再创新高