Spring MVC程序开发

目录

1. 什么是Spring MVC?

1.1 什么是MVC

1.2 MVC和Spring MVC 的关系

1.3 为什么要学Spring MVC?

2. Spring MVC的使用

2.1 Spring MVC的创建和连接

2.1.1 项目创建

2.1.2 项目连接

2.1.2.1 连接

2.1.2.2 @RequestMapping注解介绍

2.1.2.3 @GetMapping和 @PostMapping

2.2 获取参数

获取单个参数

获取多个参数

获取对象

@RequestParam重命名后端参数 (后端参数映射)

设置参数必传@RequestParam

非必传参数设置

@RequestBody接收JSON对象

@PathVariable获取URL基础参数(不是从URL参数部分获取参数)

@RequestPart上传文件

@CookieValue获取Cookie

@RequestHeader获取header

@SessionAttribute获取Session

2.3 返回数据

返回静态页面

返回text/html

返回JSON对象

请求转发或请求重定向

两者区别

定义

请求方

数据共享

最终URL

代码实现不同

查看更多注解


1. 什么是Spring MVC?

官方描述:

Spring Web MVC is the original web framework built on the Servlet APl and has been included in the Spring Framework from the very beginning. The formal name, "Spring Web MVC", comes from the name of its source module (spring-webmvc), but it is more commonly known as "Spring MVC"
Spring Web MVC 是基于 Servlet API 构建的原始 Web 框架,从一开始就包含在 Spring 框架中。它的正式名称“Spring Web MVC”来自其源模块的名称(Spring-webmvc),但它通常被称“Spring MVC”

由官方对Spring MVC的定义可以知道:

  1. Spring MVC是一个Web框架;
  2. Spring MVC是基于Servlet API构建的.

1.1 什么是MVC

定义: MVC是Model View Controller的缩写, 它是软件工程中的一种软件架构模式, 它把软件系统分为 模型, 视图, 控制器 三个基本部分.

  • Model(模型)是应用程序中用于处理应用程序数据逻辑的部分。通常模型对象负责在数据库中存取数据。
  • View(视图)是应用程序中处理数据显示的部分。通常视图是依据模型数据创建的。
  • Controller(控制器)是应用程序中处理用户交互的部分。通常控制器负责从视图读取数据控制用户输入,并向模型发送数据

当用户发送请求的时候, 请求会首先来到Controller控制器, 然后在Controller里面 验证完请求没有问题之后就会将请求转发给Model模型层(也就是数据模型), 然后数据模型会根据请求的信息得到相应的结果, 然后把结果返回给控制器, 接下来控制器再把结果交给View视图渲染器, 然后View就根据它的模板并加上返回来的数据进行数据的解析和渲染, 最终将用户可以看得懂的页面交给用户, 这样就完成了一次响应. 这是最初的MVC的机制.

模型层是比较广义上的模型层, 程序中实体类所在的层就是这个Model模型层, 也可以叫做entity, 那么这里的模型指的是数据模型.
但是目前来讲这种模式已经过时了, 现在都是在做前后端分离的, 已经不再使用View这种已经淘汰的技术来返回页面给用户.
Spring提供的Web容器只有这一个, 我们实现的是基于http协议的, 所以我们需要用这个框架.
Spring MVC经过它的演变和改善, 是可以直接从Controller返回数据给用户的, 也就是说不再经过View视图的渲染了.

1.2 MVC和Spring MVC 的关系

MVC 是一种思想,而 Spring MVC 是对 MVC 思想的具体实现。

总结来说,Spring MVC 是一个实现了 MVC 模式,并继承了 Servlet API的 Web 框架。既然是 Web框架,那么当用户在浏览器中输入了 url 之后,我们的 Spring MVC 项目就可以感知到用户的请求。

1.3 为什么要学Spring MVC?

现在绝大部分的 Java 项目都是基于 Spring (或 Spring Boot)的,而 Spring 的核心就是 Spring MVC。也就是说 Spring MVC 是 Spring 框架的核心模块,而 Spring Boot 是 Spring 的脚手架,因此我们可以推断出,现在市面上绝大部分的 Java 项目约等于 Spring MVC 项目,这是我们要学 SpringMVC 的原因。

2. Spring MVC的使用

学习Spring MVC的使用需要掌握以下它的功能:

  1. 连接的功能: 将用户 (浏览器) 和 Java 程序连接起来,也就是访问一个地址能够调用到我们Spring程序。
  2. 获取参数的功能: 用户访问的时候会带一些参数,在程序中能够获取到用户输入的参数。
  3. 输出数据的功能: 执行了业务处理,然后把程序执行的结果返回给用户。

2.1 Spring MVC的创建和连接

2.1.1 项目创建

Spring MVC 可以基于 Spring Boot 创建,也就是创建一个 Spring Boot 项目,勾选上 Spring Web模块即可,如下图所示:

2.1.2 项目连接

2.1.2.1 连接

接下来,创建一个 UserController 类,实现用户到 Spring 程序的互联互通, 具体实现代码如下:

package com.example.demo.controller;import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;//@Controller     // 让 Spring 框架启动时, 加载
//@ResponseBody   // 返回非页面数据
@RestController     // = @Controller + @ResponseBody
public class UserController {@RequestMapping("/say")    // 该注解能让后端获取到用户请求, 后文介绍该注解public String sayHi(){return "Hi Spring MVC";}
}

这样实现之后,当访问地址: http://localhost:8080/say 时就能打印"Hi Spring MVC"的信息了.

2.1.2.2 @RequestMapping注解介绍

@RequestMapping 是 Spring Web 的常用注解之一,它是用来注册接口的路由映射的。

路由映射: 当用户访问一个 url 时, 将用户的请求对应到程序中某个的某个方法的过程就叫路由映射.

@RequestMapping的使用就如上面例子的打印"Hi Spring MVC"所示, 上例是用于修饰方法的, 那么它也可以用于修饰类. 当修饰了类和方法之后就要注意访问地址为: 类+方法.

注: 还可以在一个@RequestMapping中设置多级路由.

@RequestMapping能够支持较多的请求, 最常见的就是GET和POST, 那么它也能够支持PUT, PATCH, DELETE等其他请求, 适用范围较广. 我们通过工具Postman来发送不同种类的请求来验证(验证过程略). 也可以在它的源码中找到.

从源码中我们可以知道, 我们还可以通过加method来控制@RequestMapping的请求类型, 比如:

@RequestMapping(value = "/say", method = RequestMethod.POST)

此时只有POST类型的请求能够获取, 其他类型的请求就无法获取, 比如获取GET, 就会直接报错.

2.1.2.3 @GetMapping和 @PostMapping

通过@GetMapping和 @PostMapping可以单独的只支持GET请求或者POST请求.

@PostMapping("/sayhello")
public String sayHello() {return "hello spring mvc";
}@GetMapping("/hi")
public String hi() {return "spring mvc hi";
}

2.2 获取参数

获取单个参数

在Spring MVC中可以直接用方法中的参数来实现传参,比如以下代码:

@RequestMapping("/sayhi")
public String sayHi(String name) {return "Hi " + name;
}

获取多个参数

@RequestMapping("/sayhi") // 可以是一级路由, 也可以是 N 级路由
public String sayHi(String name, String password) {return "hi " + name + " | password: " + password;
}

注意: 当有多个参数时,前后端进行参数匹配时,是以参数的名称进行匹配的,因此参数的位置是不影响后端获取参数的结果。

获取对象

package com.example.demo.entity;import lombok.Data;@Data
public class Userinfo {private int id;public String name;private String password;private int age;
}
@RequestMapping("/reg")
public Object reg(Userinfo userinfo) {System.out.println(userinfo);return userinfo;
}


@RequestParam重命名后端参数 (后端参数映射)

某些特殊的情况下,前端传递的参数 key 和我们后端接收的 key 可以不一致,比如前端传递了一个username 给后端,而后端又是有name字段来接收的,这样就会出现参数接收不到的情况,如果出现这种情况,我们就可以使用 @RequestParam 来重命名前后端的参数值。

@RequestMapping("/reg2")
public Object reg2(@RequestParam("username") String name, String password) {return name + " : " + password;
}

设置参数必传@RequestParam

上面的例子,如果我们是前端传递一个非 username 的参数,就会出现程序报错的情况,如下图所示:

这是因为后端已经声明了前端必须传递一个username的参数,但是前端没有给后端传递,我们查看@RequestParam 注解的实现细节就可以发现端倪,注解实现如下:

required: 必须的意思,默认值为 true,因此不传递此参数就会报 400 的错误.

非必传参数设置

如果我们的实际业务前端的参数是一个非必传的参数,我们可以通过设置 @RequestParam 中的required=false 来避免不传递时报错,具体实现如下:

@RequestMapping("/reg2")
public Object reg2(@RequestParam(value = "username", required = false) String name, String password) {return name + " : " + password;
}

@RequestBody接收JSON对象

@RequestMapping("/reg3")
public Object reg3(@RequestBody Userinfo userinfo) {return userinfo;
}

@PathVariable获取URL基础参数(不是从URL参数部分获取参数)

@RequestMapping("/reg4/{name}/{pwd}")
public Object reg4(@PathVariable String name, @PathVariable(required = false, name = "pwd") String password) {return "name=" + name + " | password=" + password;
}

注意事项: @PostMapping("/reg4/{name}/{password}")中的 {password} 参数不能省略

@RequestPart上传文件

    @RequestMapping("/myupload")public Object upload(@RequestPart("myimg6") MultipartFile file) {String fileName = UUID.randomUUID() +    // 文件名file.getOriginalFilename().substring(   // 文件后缀file.getOriginalFilename().lastIndexOf("."));File saveFile = new File("D:\\JavaWebStudy\\" + fileName);try {file.transferTo(saveFile);return true; } catch (IOException e) {e.printStackTrace();}return false;}

通过Postman模拟上传文件,

注: 文件大小有要求, 那么可以通过Spring官方文档查询默认值, 进而在配置文件中修改默认大小. Common Application Properties

@CookieValue获取Cookie

@RequestMapping("/getck")
public Object getCk(@CookieValue(value = "java", required = false) String java) {return java;
}

注意, 直接访问/getck是没有任何东西在页面上的, 那么需要我们F12中手动伪造一份Cookie, 才能看见.

@RequestHeader获取header

@RequestMapping("/gethd")
public Object getHeader(@RequestHeader("Host") String host) {return "header -> " + host;
}

@SessionAttribute获取Session

    private static final String SESSION_KEY = "USERINFO_SESSION_KEY";// 存储 session@RequestMapping("/setsess")public void setSess(HttpServletRequest request) {HttpSession session = request.getSession();session.setAttribute(SESSION_KEY, "zhangsan");}// 获取 session@RequestMapping("/getsess")public Object getSession(@SessionAttribute(SESSION_KEY) String name) {return "session -> " + name;}

执行完localhost:8080/setsess后再访问localhost:8080/getsess

2.3 返回数据

返回静态页面

在resources.static中创建前端页面index.html:

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>index.html</title>
</head>
<body><h1>hello index</h1>
</body>
</html>

创建控制器TestController:

package com.example.demo.controller;import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;@Controller
@RequestMapping("/test")
public class TestController {@RequestMapping("/index")public Object getIndex(){return "/index.html";}
}


注意代码中的返回路径:

当return中加了"/"之后就代表是从根路径去找index.html的.

当不加"/"的时候, 它是在"/test"底下去找index.html的, 即在当前目录底下去找index.html的. 显然在上面的URL并找不到, 因为index.html是放在根路径下的.



返回text/html

package com.example.demo.controller;import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
public class OwnerController {@RequestMapping("/m7")public String method_1(){return "<h1>hi, h1.</h1>";}
}

返回JSON对象

    @RequestMapping("/m2")public HashMap<String, String> method_2(){HashMap<String, String> map = new HashMap<>();map.put("C", "C Value");map.put("Java", "Java Value");map.put("MySQL", "MySQL Value");return map;}

请求转发或请求重定向

    // TestController下, 类注解@RequestMapping("/test")// 请求转发@RequestMapping("/fw")public String fw(){return "forward:/index.html";}// 请求重定向@RequestMapping("/rd")public String rd(){return "redirect:/index.html";}

请求转发和请求重定向的直观区别:

请求转发: 当输入localhost:8080/test/fw后, URL不变.

请求重定向: 当输入localhost:8080/test/rd后, URL变为localhost:8080/index.html


两者区别

定义

请求转发(Forward)是发生于服务器程序内的, 当服务器收到客户端的请求之后, 服务器会先将请求转发给目标地址, 由目标地址对请求进行处理, 再将目标地址返回的结果返回给客户端. 那么显然客户端就只知道发出了请求, 并收到了返回结果, 但是客户端并不知道服务器内部发生了转发行为.

请求重定向(Redirect)主要发生于客户端程序内, 当服务器收到客户端的请求之后, 服务器会给客户端发送一个用于重定向的临时响应头, 这个响应头记录了重定向之后的目标地址, 然后客户端会向这个目标地址发起请求.

请求方


数据共享

请求转发是由服务器实现的, 在整个执行流程中, 客户端只会发送一次请求, 所以在整个交互过程中使用的都是同一个请求对象和响应对象, 这说明在请求和返回的数据是共享的.

请求重定向则是客户端向服务器发起两次完全不同的请求, 所以两次请求中的数据是不同的.

最终URL

请求转发是服务器端代为请求,再将结果返回给客户端的,所以整个请求的过程中 URL 地址是不变的;

而请求重定向是服务器端告诉客户端,"你去另一个地访问去”,所以浏览器会重新再发送一次请求,因此客户端最终显示的 URL也为最终跳转的地址,而非刚开始请求的地址,所以 URL 地址发生了改变.

代码实现不同

由前文例子可见.

注: 以上关于请求转发和请求重定向的区别说明摘自请求转发和请求重定向有什么区别? | Javaᶜⁿ 面试突击


查看更多注解

Request Mapping :: Spring Framework

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

EFLFK——ELK日志分析系统+kafka+filebeat架构

环境准备 node1节点192.168.40.16elasticsearch2c/4Gnode2节点192.168.40.17elasticsearch2c/4GApache节点192.168.40.170logstash/Apache/kibana2c/4Gfilebeat节点192.168.40.20filebeat2c/4G https://blog.csdn.net/m0_57554344/article/details/132059066?spm1001.2014.30…

【生成式AI】ProlificDreamer论文阅读

ProlificDreamer 论文阅读 Project指路&#xff1a;https://ml.cs.tsinghua.edu.cn/prolificdreamer/ 论文简介&#xff1a;截止2023/8/10&#xff0c;text-to-3D的baseline SOTA&#xff0c;提出了VSD优化方法 前置芝士:text-to-3D任务简介 text-to-3D Problem text-to-3D…

实例035 动画形式的程序界面

实例说明 在很多的程序界面中&#xff0c;都是以菜单或工具栏的形式显示窗体界面&#xff0c;这种显示方式是以静止状态显示的&#xff0c;界面不够生动。下面介绍一个以动画显示窗体界面的设计方法。运行本例&#xff0c;效果如图1.35所示。 技术要点 在该实例中用到了Micr…

配置nginx服务端口时-在同一个页面中打开多个地址端口-查看服务情况

1&#xff1a;把代码保存到xxx.html文件中 2&#xff1a;因为一个个端口打开查看&#xff0c;实在太麻烦了 3&#xff1a;在一个页面中查看多页的响应才能提高测试效率 <html><head><title>本地连接列表</title> </head><body><cente…

Java课题笔记~ HTTP协议(请求和响应)

Servlet最主要的作用就是处理客户端请求&#xff0c;并向客户端做出响应。为此&#xff0c;针对Servlet的每次请求&#xff0c;Web服务器在调用service()方法之前&#xff0c;都会创建两个对象 分别是HttpServletRequest和HttpServletResponse。 其中HttpServletRequest用于封…

shapely库的用法,高效处理点、线、面的几何关系和相关延申(GeoPandas 库)python

1、shapely库的基本用法 Shapely 是一个用于处理几何对象的 Python 库&#xff0c;它提供了各种函数和方法来进行空间分析和几何计算。下面是一些 Shapely 库的常见用法示例&#xff1a; 1. 创建几何对象&#xff1a; from shapely.geometry import Point, LineString, Poly…

【Flutter】【基础】CustomPaint 绘画功能,绘制各种图形(二)

CustomPaint 使用实例和代码&#xff1a; 1.canvas.drawColor 绘制背景颜色 class MyPainter1 extends CustomPainter {overridevoid paint(Canvas canvas, Size size) {//绘制背景颜色&#xff0c;整个UI 现在就是红色的canvas.drawColor(Colors.red, BlendMode.srcATop);}…

Maven安装与配置

目录 一、Maven简介1.1 概述1.2 作用1.3 仓库 二、安装三、配置3.1 配置环境变量3.2 环境变量测试3.3 配置仓库 一、Maven简介 1.1 概述 Maven是一个开源的项目管理工具&#xff0c;用于构建和管理Java项目&#xff0c;基于项目对象模型&#xff08;POM&#xff09;的概念。它…

数据库优化脚本执行报错

目录 一、执行数据库优化脚本 报错... 3 解决方法&#xff1a;... 4 1、直接注释掉RECYCLE_POOLS 赋值sql语句块... 4 2、手动修改脚本... 5 附录... 6 一、执行数据库优化脚本 报错 AutoParaAdj3.5_dm8.sql 1&#xff09;manager中报错 -20001: 执行失败, -7065 数据未…

青大数据结构【2015】

一、单选 二、简答 5.如果一组关键字&#xff0c;以不同的次序输入后建立起来的二叉排序树是否相同&#xff1f;当中序遍历这些二叉排序树时&#xff0c;其遍历的结果是否相同&#xff1f;为什么&#xff1f; 不同&#xff0c;因为输入次序不同&#xff0c;所放置的位置与上一…

Stable Diffusion - 俯视 (from below) 拍摄的人物图像 LoRA 与配置

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://spike.blog.csdn.net/article/details/132192139 图像来自 哥特风格 LoRA 俯视 LoRA&#xff0c;提升视觉冲击力&#xff0c;核心配置 <lora:view_from_below:0.6>,(from below,…

时间复杂度与空间复杂度的详解

目录 1.时间复杂度 2.时间复杂度计算例题 3.空间复杂度 1.时间复杂度 算法中的基本操作的执行次数&#xff0c;为算法的时间复杂度。 如何表达 时间复杂度&#xff1f; 大O的渐进表示法 实际中我们计算时间复杂度时&#xff0c;我们其实并不一定要计算精确的执行次数&#xf…

nginx基于源码安装的方式对静态页面、虚拟主机(IP、端口、域名)和日志文件进行配置

一.静态页面 1.更改页面内容 2.更改配置文件 3.测试 二.虚拟主机配置 1.基于IP &#xff08;1&#xff09;在html目录下新建目录存放测试文件 &#xff08;2&#xff09;修改nginx.conf文件&#xff0c;在htttp模块中配置两个server模块分别对应两个IP &#xff08;3&am…

外部节点访问 k8s 集群内的 starrocks

问题描述 用kubeadm在虚拟机搭建了k8s&#xff0c;按starrocks官网步骤&#xff0c;用k8s部署了starrocks 部署成功&#xff1a; 在 k8s集群内节点访问到 sr&#xff1a;&#xff08;通过 clusterIP &#xff09; mysql -h 10.97.182.109 -uroot -P 9030 k8s 节点内访问成功…

创建CREATE_STAT_TABLE 统计信息表在达梦和oracle中的使用

达梦 创建CREATE_STAT_TABLE 统计信息表 PROCEDURE CREATE_STAT_TABLE ( STATOWN VARCHAR(128), STATTAB VARCHAR(128), TABLESPACE VARCHAR(128) DEFAULT NULL, GLOBAL_TEMPORARY BOOLEAN DEFAULT FALSE ); 创建普通表的对应系统表的列名字段包括以下&#xff1a; OWNER TABL…

Linux MQTT智能家居项目(智能家居界面布局)

文章目录 前言一、创建工程项目二、界面布局准备工作三、正式界面布局总结 前言 一、创建工程项目 1.选择工程名称和项目保存路径 2.选择QWidget 3.添加保存图片的资源文件&#xff1a; 在工程目录下添加Icon文件夹保存图片&#xff1a; 将文件放入目录中&#xff1a; …

大数据课程I1——Kafka的概述

文章作者邮箱&#xff1a;yugongshiyesina.cn 地址&#xff1a;广东惠州 ▲ 本章节目的 ⚪ 了解Kafka的概念&#xff1b; ⚪ 掌握Kafka的配置与启动&#xff1b; 一、简介 1. 基本概念 Apache kafka 是一个分布式数据流平台。可以从如下几个层面来理解&#x…

ngrok内网穿透可以实现资源共享吗?快解析更加简洁

随着互联网的高速发展&#xff0c;越来越多的人开始意识到内网穿透技术的重要性。在这一技术中&#xff0c;ngrok已经成为了一个备受关注的工具。然而&#xff0c;很多人对于ngrok是否可以进行资源共享存在疑问。本文将从新的角度出发&#xff0c;深入探讨这个问题。 了解什么…

TEC2083BS-PD码转换器(解决博世矩阵控制PELCO派尔高球机的问题)

TEC2083BS-PD码转换器 使用说明 1.设备概述 控制码转换器在安防工程中起着非常重要的角色&#xff0c;随着高速球型摄像机在安防工程中大范围的使用&#xff0c;而高速球厂家都因为某些原因很少使用博世、飞利浦的协议。为此&#xff0c;工程商经常会遇到博世协议和PELCO协议之…

【Linux】云服务器自动化部署VuePress博客(Jenkins)

前言 博主此前是将博客部署在 Github Pages&#xff08;基于 Github Action&#xff09;和 Vercel 上的&#xff0c;但是这两种部署方式对于国内用户很不友好&#xff0c;访问速度堪忧。因此将博客迁移到自己的云服务器上&#xff0c;并且基于 Jenkins&#xff08;一款开源持续…