【JavaEE】SpringMVC

news2025/5/23 9:12:32

目录

SpringMVC

获取连接

@RequestMapping / @GetMapping...

获取参数

获取querystring中的参数(获取表单数据基本相同)

获取URL中的参数

获取JSON对象

获取文件(通过表单)

获取Cookie

获取Header

获取Session

返回数据

返回数据

返回JSON对象

返回静态页面

请求转发 + 请求重定向


SpringMVC

SpringMVC是基于Servlet的一种Web框架。

它提供了一种模型(Model)-视图(View)-控制器(Controller)架构的实现方式,可以帮助开发者更加高效地构建Web应用程序。


在SpringMVC中,

模型指的是业务逻辑和数据访问层

视图是用户界面层

控制器是将模型和视图进行关联的桥梁

SpringMVC把请求映射为一个控制器方法,这个方法会处理请求并返回一个包含模型数据和视图信息的ModelAndView对象。视图对象则负责生成最终的HTML内容,将模型数据渲染到视图上。由于现在是前后端分离的开发模式,所以现在的都是数据。

学习SpringMVC最主要的部分就是建立连接,获取参数,返回数据。

在SpringMVC这里,几乎都是通过注解来实现相应的操作,就相当于学习注解。

获取连接

@RequestMapping / @GetMapping...

这一类注解都可以获取参数,其中@GetMapping、@Post Mapping等可以看作是@RequestMapping的具体化,这些注解获取连接只能使用指定的方法。

源码如下:

  1. value/path:指定请求的URI路径或模式,即客户端发送请求的URL地址,如@RequestMapping(value="/users")表示匹配以"/users"结尾的URI路径。
  2. method:指定请求的HTTP方法,可选值为RequestMethod.GET、RequestMethod.POST等。
  3. params:指定请求参数的条件,如@RequestParam(name="id", required=true)表示必须包含名为"id"的请求参数,且不能为空。
  4. headers:指定请求头的条件,如@RequestMapping(headers="Accept=text/plain")表示只有在"Accept"请求头为"text/plain"时才会匹配。
  5. consumes:指定请求内容类型的条件,如@RequestMapping(consumes= MediaType.APPLICATION_JSON_VALUE)表示只有当请求内容类型为JSON时才会匹配。
  6. produces:指定响应内容类型的条件,如@RequestMapping(produces=MediaType.APPLICATION_JSON_VALUE)表示请求处理方法返回的内容类型为JSON。

package com.example.demo.controller;

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

@Controller // 把这个类交给Spring管理,一启动就加载
@RequestMapping("/connection")  // 这是一个获取连接的注解  内容是路由
public class TestConnectionController {

    /**
     * 测试方法不带参数的@RequestMapping注解
     */

    @RequestMapping("/test1") // 每个方法上可以加一个路由
    public void test1() {
        System.out.println("此时已经建立连接!");
        System.out.println();
    }

    @RequestMapping("/test2/other")
    public void test2() {
        System.out.println("多级路由也可以使用!");
        System.out.println();
    }

    //这样的效果相当于@PostMapping注解
    @RequestMapping(value = "/test3", method = RequestMethod.POST)
    public void test3() {
        System.out.println("若是没有指定特定方法,此注解可以使用任何方法传递");
        System.out.println("这里只能使用POST方法进行传参!");
        System.out.println("若只想用其他方法,就可以改成GET等");
        System.out.println();
    }
}

 


获取参数

获取querystring中的参数(获取表单数据基本相同)

package com.example.demo.controller;

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

import javax.servlet.http.HttpServletRequest;

@Controller
@RequestMapping("/parameters")
public class TestParametersController {

    /**
     * 测试表单传递参数
     */

    @RequestMapping("/test1")
    // 这里的参数部分的名称(name)要和表单中的Key名称一致
    public void test1(String name) {
        System.out.println("test1: " + name);
        System.out.println();
    }

    @RequestMapping("/test2")
    // 顺序可以不一致,但是名称一定要能对应上
    public void test2(String name, String message, String password) {
        System.out.println("test2: " + name + " : " + password + " : " + message);
        System.out.println();
    }

    @RequestMapping("/test3")
    // 如果前端的表单名字和后端不同且两边都无法修改
    // 使用@RequestParam(value="这是前端的key") 类型  这是后端的名称
    public void test3(@RequestParam(value = "username") String name) {
        System.out.println("test3: " + name);
        System.out.println();
    }

    @RequestMapping("/test4")
    public void test4(@RequestParam(required = true) String name) {
        // 这里的 name 如果是必须要传的,则可以改成 true
        // 默认是false,表示可以不用传
        System.out.println("test4: " + name);
        System.out.println();
    }

    @RequestMapping("/test5")
    public void test5(Integer id) {
        // 一般参数的类型建议使用非基本类型
        // 比如有int类型的参数,则使用其包装类Integer更好
        // 如果没有收到参数时,默认给赋值null,后续处理
        // 如果是基本类型,此时则会直接报错
        if (id == null) {
            // 此时可以返回 传参失败的提示 给前端
            // 这里暂时不做处理
        }
        System.out.println("test5: " + id);
        System.out.println();
    }

    @RequestMapping("/test6")
    public void test6(int id) {
        // 这里如果没有收到id则会报错
        System.out.println("test6: " + id);
        System.out.println();
    }

    @RequestMapping("/test7")
    public void test7(HttpServletRequest request) {
        // 也可以像之前的 Servlet 一样
        // SpringMVC中也是内置了 HttpServletRequest 和 HttpServletResponse
        // 使用方式和方法和Servlet的一样
        String name = request.getParameter("username");
        System.out.println("test7: " + name);
        System.out.println();
    }
}

 下面参数的传递都是通过querystring方法传递的,表单也是类似

 


获取URL中的参数

package com.example.demo.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.RequestParam;

import javax.servlet.http.HttpServletRequest;

@Controller
@RequestMapping("/parameters")
public class TestParametersController {

    /**
     * 测试获取URL中的参数
     */

    @RequestMapping("/test8/{username}/{password}")
    // @PathVariable中的参数部分要和路由中的参数相同
    public void test8(@PathVariable("username") String name,
                      @PathVariable("password") String password) {
        System.out.println("test8: " + name + " : " + password);
        System.out.println();
    }
}


获取JSON对象

  1. 需要在后端创建一个对应的类
  2. 使用@RequestBody来接收JSON对象

与JSON对应的类

package com.example.demo.entity;

import lombok.Data;

@Data
public class User {
    private Integer id;
    private String name;
    private Integer age;
}

package com.example.demo.controller;

import com.example.demo.entity.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

import javax.servlet.http.HttpServletRequest;

@Controller
@RequestMapping("/parameters")
public class TestParametersController {

    /**
     * 测试接收JSON对象
     */
    @RequestMapping("/test9")
    // 对应的类中字段顺序可以不相同,但是名称要和JSON的key相同
    // 这样才可以一一映射上,否则就无法匹配赋值
    public void test9(@RequestBody User user) {
        System.out.println("test9: ");
        System.out.println(user);
        System.out.println();
    }

}


获取文件(通过表单)

package com.example.demo.controller;

import com.example.demo.entity.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;

@Controller
@RequestMapping("/parameters")
public class TestParametersController {
    /**
     * 测试保存传来的文件
     */
    @RequestMapping("/test10")
    public void test10(@RequestPart("keyname")MultipartFile file) {
        // 创建出一个文件对象,并且指定保存路径+文件名称
        File saveFile = new File("D:\\ATest\\cat.png");
        try {
            // 通过这个方法把文件保存下来
            file.transferTo(saveFile);
            System.out.println("test10: 文件已保存!");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

  

上述代码虽然保存了文件,但是有个致命的错误,就是下次再上传文件的时候,之前的旧文件会被新文件覆盖,原因是文件名写死了。 

修改代码如下:

package com.example.demo.controller;

import com.example.demo.entity.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.util.UUID;

@Controller
@RequestMapping("/parameters")
public class TestParametersController {
    /**
     * 测试保存传来的文件
     */

    @RequestMapping("/test11")
    public void test11(@RequestPart("cat") MultipartFile file) {
        // 先生成一个独一无二的文件名
        // UUID生成的字符串是独一无二的
        // 把原文件的类型拿出来
        String fileName = UUID.randomUUID() +
                file.getOriginalFilename().substring(
                        file.getOriginalFilename().indexOf("."));
        File saveFile = new File("D:\\ATest\\" + fileName);
        try {
            file.transferTo(saveFile);
            System.out.println("test11: 文件已保存!");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

  


获取Cookie

package com.example.demo.controller;

import com.example.demo.entity.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.util.UUID;

@Controller
@RequestMapping("/parameters")
public class TestParametersController {

    /**
     * 测试获取Cookie
     */
    @RequestMapping("/test12")
    public void test12(@CookieValue(value = "cookieKey") String cookieValue) {
        System.out.println("test12: " + cookieValue);
    }
}


获取Header

package com.example.demo.controller;

import com.example.demo.entity.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.util.UUID;

@Controller
@RequestMapping("/parameters")
public class TestParametersController {

    /**
     * 测试获取Header
     */
    @RequestMapping("/test13")
    public void test13(@RequestHeader(value = "Host") String headerValue) {
        System.out.println("test13: " + headerValue);
    }
}


获取Session

package com.example.demo.controller;

import com.example.demo.entity.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.io.File;
import java.io.IOException;
import java.util.UUID;

@Controller
@RequestMapping("/parameters")
public class TestParametersController {
    /**
     * 测试获取Session
     */
    // 首先手动存储Session
    @RequestMapping("/test16")
    public void test14(HttpServletRequest request) {
        // 这里是得不到session的
        HttpSession session = request.getSession();
        // 自行设置session
        session.setAttribute("sessionKey", "sessionValue");
    }

    @RequestMapping("/test17")
    // @SessionAttribute 中的参数是 session的key
    // 通过该注解可以直接获取到对应的session的value
    public void  test18(@SessionAttribute("sessionKey") String session) {
        System.out.println("test17: " + session);
    }
}

 


返回数据

返回text/html + json/html

package com.example.demo.controller;

import com.example.demo.entity.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;


@ResponseBody
// @ResponseBody 会自动把要返回的数据转成合适的格式
@Controller
@RequestMapping("/data")
// @Controller + @RequestMapping = @RestController
// 这两个注解可以组合写成@RestController,效果一样
public class TestReturnDataController {

    /**
     * 测试返回对象
     * @return 返回的是User对象-->JSON对象
     */
    @RequestMapping("/test2")
    public User test2() {
        User user = new User();
        user.setId(1);
        user.setName("李四");
        user.setAge(20);
        // 这里的user会自动转成JSON对象发送过去
        return user;
    }

    /**
     * 测试返回一般数据
     * @return 返回的是非对象数据
     */
    @RequestMapping("/test1")
    public String test1() {
        // 如果是字符串,会自动转成text/html
        return "这是返回的内容";
    }
}

 


返回静态页面(视图)

这种返回静态页面的方法在现在一般不使用了,前后端分离只需要返回数据即可。

package com.example.demo.controller;

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

@Controller
@RequestMapping("/page")
public class TestPageController {

    /**
     * 测试返回一个静态页面
     * @return
     */
    @RequestMapping("/static")
    // 返回类型未知都可以使用Object类来接收
    public Object test17() {
        // 第一个 /  表示根路径
        // 只有从根路径出发,才可以访问到其他页面
        return "/user/index.html";
    }
}
<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <h1>这是返回的静态页面</h1>
</body>
</html>

  


请求转发 + 请求重定向

请求转发:

请求转发是指将请求从一个Web组件(如Servlet或JSP)发送到另一个Web组件,过程中不会改变URL。在请求转发期间,Web容器将控制权传递给另一个Web组件,该组件可以继续处理请求并产生响应。
简单来说就是  客户端给服务器发送请求,服务器自己继续帮客户端找资源,然后返回给客户端(这一切客户端是未知的,所以URL不会变)


请求重定向:

请求重定向是指将请求从一个Web资源(如Servlet或JSP)发送到另一个Web资源,并且在过程中会更改URL。在请求重定向期间,Web容器会向浏览器发送一个302 HTTP状态码的响应,该响应包含一个新的URL,浏览器会自动发送一个新的请求以获取新的资源。请求重定向通常用于将客户端重定向到另一个Web资源,以便实现更好的用户体验或处理不同类别的请求。

简单来说就是  客户端像服务器发送请求,服务器这里不处理这个请求,但是会给客户端一个URL,然后客户端根据返回的URL重新访问。

package com.example.demo.controller;

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

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

@Controller
@RequestMapping("/page")
public class TestPageController {

    // 测试请求转发
    @RequestMapping("/forward")
    public Object test18() {
        // 在转发的网址前面 写 forward:  即可
        return "forward:/user/index.html";
    }

    // 测试请求重定向
    @RequestMapping("/redirect")
    public Object test19() {
        // 在重定向的网址前面 写 redirect:  即可
        return "redirect:/user/index.html";
    }
}

请求转发(forward)结果:

请求重定向(redirect)结果:

 

可以看到URL变了。


有什么问题评论区指出。希望可以帮到你。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/517336.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

云渲染时可以关机吗_云渲染电脑可以关闭吗?

云渲染可简单理解为放在云端的渲染农场&#xff0c;可区别于用户本地自己搭建的小型私有农场&#xff0c;用户只需将自己制作好的项目文件进行打包&#xff0c;通过 云渲染平台提供的客户端或网页端将文件上传到云端进行渲染。很多用户通过云渲染作业&#xff0c;解放了自己本地…

深耕5G+AIoT产业赛道,2023高通&美格智能物联网技术开放日隆重举行

5月11日&#xff0c;高通技术公司携手美格智能联合举办了“高通&美格智能物联网技术开放日”深圳站活动。大会现场&#xff0c;智能物联网行业合作伙伴齐聚一堂&#xff0c;围绕5GAIoT前沿技术&#xff0c;通过大咖专业的技术分享、落地应用介绍和现场丰富的产品展示&#…

Pytorch nn.Softmax(dim=?) 详解

本文参考自&#xff1a;Pytorch nn.Softmax(dim?) - 知乎 原文写得很好了&#xff0c;我这边另外完善了一些细节&#xff0c;让大家理解地更加直白一些。 可以先去看上面的参考文章&#xff0c;也可以直接看我这篇。 目录 1、tensor1 1&#xff09;已知该矩阵的维度为&am…

vue实现聊天框自动滚动

需求 1、聊天数据实时更新渲染到页面 2、页面高度随聊天数据增加而增加 3、竖向滚动 4、当用户输入聊天内容或者接口返回聊天内容渲染在页面后&#xff0c;自动滚动到底部 5、提供点击事件操控滚动条上下翻动 环境依赖 vue&#xff1a;vue…

两小时搭建属于自己的chatGPT(ChatGLM)免硬件(白嫖)

目录 准备&#xff08;注册&#xff09;: 搭建: API模式: 测试&#xff1a; 总结&#xff1a; 准备&#xff08;注册&#xff09;: 注册modelscope(白嫖)免费使用服务器 https://modelscope.cn/ 按照图片里的选择(选择其他好像不能创建成功) 可以白嫖60多个小时的配置 8…

Java 8 Time 关于java.time包中你可能不知道的使用细节

目录 前言一、时区与时间1. 世界标准时&#xff1a;UTC、GMT、UT2. 地区时&#xff1a;Asia/Shanghai、UTC83. 时区&#xff1a;ZoneId、TimeZone4. 时间偏移量&#xff1a;ZoneOffset5. 时区简称&#xff1a;CTT、PRC 二、主要时间类1. 重要时间接口&#xff1a;Temporal2. 时…

【CocosCreator入门】CocosCreator组件 | Collider(碰撞)组件

Cocos Creator是一款流行的游戏开发引擎&#xff0c;具有丰富的组件和工具&#xff0c;其中碰撞系统组件是该引擎的重要组成部分。该组件可用于检测游戏中各个元素之间的碰撞&#xff0c;例如玩家角色与敌人、子弹与障碍物等。 目录 一、组件介绍 二、组件属性 2.1BoxCollid…

基于SpringBoot+微信小程序的农产品销售平台

基于SpringBoot微信小程序的农产品销售平台 ✌全网粉丝20W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取项目下载方式&#x1f345; 一、项目…

Test Doubles测试替身: Testing in Distributed Systems and Real World

什么是Test Doubles In software testing, we developed unit tests and integration tests to test the codes functionality. However, in the real world, it is very common for a piece of code to interact with external components, for example, databases, public A…

【人工智能概论】pyplot作图中文显示、逐点坐标显示、保存图像

【人工智能概论】pyplot作图中文显示、逐点标记、保存图像 文章目录 【人工智能概论】pyplot作图中文显示、逐点标记、保存图像一. 简单的绘图二. 逐点坐标显示三. 中文显示四. 中文显示可能遇到的问题——缺少字体4.1 下载 SimHei.ttf4.2 复制 SimHei.ttf 到 Matplotlib 的 fo…

好的Robots.txt设计对Google收录有很大的帮助

Robots.txt 文件是用于指导搜索引擎爬虫在网站上爬行的标准。正确地设计 Robots.txt 文件可以帮助 Google 爬虫更好地理解您的网站结构&#xff0c;从而提高您的网站在 Google 搜索引擎上的收录率。 以下是一些设计 Robots.txt 文件的技巧&#xff0c;可以帮助 Google 爬虫更好…

security 报错:There is no PasswordEncoder mapped for the id “null“

security在登录的时候 无法登录成功 首先解读错误 下面百度翻译 安全框架设置了登录验证 说你没有密码编辑器 解决方法 一: 往容器中注册一个PasswordEncoder 解决方法二: 设置用户权限和角色的时候添加方法,加进去一个PasswordEncoder 只需要解决方案的话 下面的内容…

K8S系列之污点和容忍度详细分析

架构图 本篇文档主要介绍污点和容忍度的关系。 污点和容忍度 污点顾名思义就是脏的东西&#xff0c;给节点添加污点来限制pod调度到该节点上&#xff0c;如果pod可以容忍这种污点就可以被调度到有污点的节点上&#xff0c;如果不能容忍就不能被调度到该节点上。 污点作用于节…

排队领奖模式吸引新消费者,电商平台如何创新引流拓客?

在当前的电商市场中&#xff0c;由于竞争日趋激烈&#xff0c;很多电商平台产生了引流拓客缺乏新意的难题&#xff0c;即很难找到新的流量&#xff0c;并且难以把这些流量转化为消费者。在这个瞬息万变的时代&#xff0c;当然是谁有创意谁能吸引消费者&#xff0c;谁才能当道。…

Sequence-to-Sequence Knowledge Graph Completion and Question Answering

[2203.10321] Sequence-to-Sequence Knowledge Graph Completion and Question Answering (arxiv.org) 目录 1 Abstract 2 Introduction 3 KGT5 Model 3.1 Textual Representations & Verbalization 3.2 Training KGT5 for Link Prediction 3.3 Link Prediction Inf…

Inception Network

文章目录 一、Inception Network简介二、CNN的痛点三、Inception Network1. 1x1卷积核1.1 升维/降维&#xff1a;1.2. 调节参数数量&#xff1a;1.3. 增加非线性特性&#xff1a; 2. Inception原始模型3. Inception Module4. Inception Network 四、代码示例 一、Inception Net…

接口自动化测试 vs. UI自动化测试:为什么前者更快,更省力,更稳定?

从入门到精通&#xff01;企业级接口自动化测试实战&#xff0c;详细教学&#xff01;&#xff08;自学必备视频&#xff09; 目录 前言&#xff1a; 一、什么是接口自动化测试和 UI 自动化测试 二、为什么接口自动化测试效率比 UI 自动化测试高 1.执行速度 2.维护成本 3.…

AI人工智能与机器人的探索和应用1.1

文章来源于&#xff1a;https://mp.weixin.qq.com/s/fqivYVdakVKG-zDVfD4Qzg 研究机器人和人工智能的技术已有多年了&#xff0c;想来想去&#xff0c;觉得还是有必要对过往的技术做一些凝练和总结。在此过程中&#xff0c;除了能够将知识系统化&#xff0c;构建自己的知识体系…

三次输错密码后,系统是怎么做到不让我继续尝试的?

故事背景 忘记密码这件事&#xff0c;相信绝大多数人都遇到过&#xff0c;输一次错一次&#xff0c;错到几次以上&#xff0c;就不允许你继续尝试了。 但当你尝试重置密码&#xff0c;又发现新密码不能和原密码重复&#xff1a; 相信此刻心情只能用一张图形容&#xff1a; 虽…

python二次加工标准类型 | 包装与授权

欢迎关注博主 Mindtechnist 或加入【Linux C/C/Python社区】一起学习和分享Linux、C、C、Python、Matlab&#xff0c;机器人运动控制、多机器人协作&#xff0c;智能优化算法&#xff0c;滤波估计、多传感器信息融合&#xff0c;机器学习&#xff0c;人工智能等相关领域的知识和…