目录
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的具体化,这些注解获取连接只能使用指定的方法。
源码如下:
- value/path:指定请求的URI路径或模式,即客户端发送请求的URL地址,如@RequestMapping(value="/users")表示匹配以"/users"结尾的URI路径。
- method:指定请求的HTTP方法,可选值为RequestMethod.GET、RequestMethod.POST等。
- params:指定请求参数的条件,如@RequestParam(name="id", required=true)表示必须包含名为"id"的请求参数,且不能为空。
- headers:指定请求头的条件,如@RequestMapping(headers="Accept=text/plain")表示只有在"Accept"请求头为"text/plain"时才会匹配。
- consumes:指定请求内容类型的条件,如@RequestMapping(consumes= MediaType.APPLICATION_JSON_VALUE)表示只有当请求内容类型为JSON时才会匹配。
- 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对象
- 需要在后端创建一个对应的类
- 使用@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变了。
有什么问题评论区指出。希望可以帮到你。