所谓的Spring MVC程序开发,其实也是一个Spring Boot项目。
MVC是Model View Controller的缩写,它是软件工程中的一种软件架构模式,它把软件系统分为模型,视图,控制器三个部分。
项目使用什么技术实现的??
- SSM项目 Spring + Spring MVC + Mybatis(中期)
Spring Boot + Spring web(Spring MVC)+ Mybatis(现在)
- SM项目 Spring Boot(Spring web)+ Mybatis(现在)
- Spring MVC是一个Web框架
- Spring MVC是基于Servlet API构建的
MVC和Spring MVC的关系:
MVC是一种思想,而Spring MVC是对MVC思想的具体实现。
总结来说,Spring MVC是一个实现MVC模式,并继承了Servlet API的Web框架,既然是Web框架,那么当用户在浏览器输入url之后,我们的Spring MVC项目就可以感知到用户的请求。
现在绝大部分Java项目,都是基于Spring(或者Spring Boot)的,而Spring的核心就是Spring MVC。
Spring MVC是Spring框架的核心模块,Spring Boot是Spring的脚手架
怎么学Spring MVC?
学习Spring MVC我们只需要掌握以下3个功能:
- 连接的功能,将用户(浏览器)和Java程序连接起来,也就是访问一个地址能够调用到我们的Spring程序。
- 获取参数的功能,用户访问的时候会带一些参数,在程序中要想办法获取到。
- 输出数据的功能,执行了业务逻辑之后,要把程序执行的结果返回给用户。
对于Spring MVC来说,掌握了以上3个功能,就相当于掌握了Spring MVC。
创建Spring MVC项目:
在2018年之前,使用Maven项目添加Spring MVC框架的方式来进行创建(复杂,太麻烦),现在我们来使用Spring Boot来创建Spring MVC项目!
创建的时候,选择lombok,Spring Web(可添加Spring MVC框架),Spring Boot DevTools(热部署)。
@RestController //@RestController = @ResponseBody + @Controller
//通过注解
public class UserController {
@RequestMapping("/say") //一级路由,可设置多级路由
public String sayHi(){
return "hi Spring MVC";
}
}
在上述代码中,我们使用了: @RequestMapping("/say"),该注解支持GET,POST,PUT,DELETE等请求。
如下述仅支持POST类请求的代码:
@RequestMapping(Value = "/sayhi", method = RequestMethod.POST)
//这两个都可表示仅仅支持POST类请求:
@PostMapper("/sayHello")
public String sayHello() {
return "hello Spring MVC ";
}
如下述仅支持GET类请求的代码:
@GetMapper("/hi")
public String sayHello() {
return "hi Spring MVC ";
}
获取参数:
获取一个参数:
@RestController
public class UserController {
@RequestMapping("/sayHi")
public String sayHi(String name){
return "hi " + name;
}
}
参数传递建议不要使用基础数据类型(容易报错),建议使用包装类
在浏览器输入:localhost:8080/sayHi?name=zhangsan(注意:参数名name一定要相同,否则会出错)
获取多个参数:
具体代码可参考获取一个参数的代码!
@RestController
public class UserController {
@RequestMapping("/sayHi")
public String sayHi(String name,String password){
return "hi " + name +" " + password;
}
}
获取对象:
首先,我们来自定义一个对象吧!
@Data //@Data丰富java自动资源管理,自动生成getter、setter、equals、hashCode和toString等
public class Userinfo {
private int id;
private String name;
private String password;
private int age;
}
获取参数代码:
@RestController
public class UserController {
@RequestMapping("/reg")
public Object reg(Userinfo userinfo){ //框架会实现自动的参数映射
System.out.println(userinfo);
return userinfo;
}
}
在浏览器输入:localhost:8080/reg?name=zhangsan&password=123456&id=1&age=18(框架会实现自动的参数映射)
当然,也可以获取一个HTML标签:
获取一个HTML标签:
@RestController
public class UserController {
@RequestMapping("/he")
public Object getHe(){
return "<h1>我是HTML中H1标签</h1>";
//HTML的标签
}
}
在浏览器中输入:localhost:8080/he
后端参数重命名:
@RestController
public class UserController {
@RequestMapping("/reg2")
public Object reg(@RequestParam("username")String name,String password){
//将前端传递来的名称(username)改为name(后端)
//必传参数username
return name+" "+password;
}
}
在上述代码中:
前端传递的参数username(必传参数)
后端使用的参数name
意思是:将前端传递来的参数username被后端更改为name
在浏览器中输入:localhost:8080/reg2?username=zhangsan&password=123456
在上述代码中:username属于必传参数,当然也可以变为非必传参数,如果不传的话,默认为null
@RestController
public class UserController {
@RequestMapping("/reg2")
public Object reg(@RequestParam(value = "username",required = false)String name,String password){
//将前端传递来的名称(username)改为name(后端)
//必传参数username
return name+" "+password;
}
}
获取JSON对象:
在这个操作中,我们来借助Postman来进行操作:
@RestController
public class UserController {
@RequestMapping("/reg3")
public Object reg3(@RequestBody Userinfo userinfo){
return userinfo;
}
}
在Postman中,我们通过:Body------》raw------》JSON------》设置参数------》sign来进行操作:
所设置的参数为:
{
"id":"1",
"name":"zhangsan",
"password":"123456",
"age":"18"
}
运行程序,并点击sign后端的相应为:
从基础URL中获取参数:
从基础URL中获取参数(不是URL的参数部分的参数)
@RestController
public class UserController {
@RequestMapping("/reg4/{name}/{password}")
public Object reg4(@PathVariable String name,@PathVariable("password")String password){
return "name = "+name+" | password ="+password;
}
}
在浏览器中输入:localhost:8080/reg4/zhangsan/123456(顺序需要一一对应)
当然,对于上述的必需参数,也可以更改为非必须参数:
@RestController
public class UserController {
@RequestMapping("/reg4/{name}/{password}")
public Object reg4(@PathVariable String name,@PathVariable(required = false,name = "password")String password){
return "name = "+name+" | password ="+password;
}
}
那么,我们来看一下注解@PathVariable和注解@RequestParm吧!
- 注解@PathVariable:基础URL里面的参数(?之前的参数)
- 注解@RequestParm:URL参数部分的参数(?之后的参数)
获取上传图片:
@RestController
public class UserController {
@RequestMapping("myupload")
public Object upload(@RequestPart("mying")MultipartFile file){
//@RequestPart("mying")拿到请求的文件,赋值给MultipartFile file
File saveFile=new File("D:\\Data\\mying.png");
//D:\Data\mying.png想要将请求的文件上传到的路径
//mying.png上传后的文件名
try {
file.transferTo(saveFile);
return true;//上传成功
} catch (IOException e) {
e.printStackTrace();
}
return false;//上传失败
}
}
本次也通过Postman来进行操作:
Boby,form-data,mying右侧选择file,mying.png
当然,在这个过程中,我们需要注意图片的大小,太大就容易上传失败(可以在配置文件中自行设置图片的最大范围)
spring.servlet.multipart.max-file-size=100MB spring.servlet.multipart.max-request-size=100MB
最后的结果为:
那么,接下来又有个问题:
后面再次上传的图片会覆盖前面的图片,名称为:mying.png
因此,我们可以在获得的原文件名的后缀带有一个独一无二的UUID,那么这个问题不就解决了吗??
String fileName= UUID.randomUUID()+ //文件名 file.getOriginalFilename().substring( //源文件进行分割 file.getOriginalFilename().lastIndexOf(".")); //添加后缀 File saveFile=new File("D:\\Data\\"+fileName);
通过上述的代码即可。
因此总的代码为:
@RestController public class UserController { @RequestMapping("myupload") public Object upload(@RequestPart("mying")MultipartFile file){ //@RequestPart("mying")拿到请求的文件,赋值给MultipartFile file String fileName= UUID.randomUUID()+ //文件名 file.getOriginalFilename().substring( //源文件进行分割 file.getOriginalFilename().lastIndexOf(".")); //添加后缀 File saveFile=new File("D:\\Data\\"+fileName); // File saveFile=new File("D:\\Data\\mying.png"); //D:\Data\mying.png想要将请求的文件上传到的路径 //mying.png上传后的文件名 try { file.transferTo(saveFile); return true;//上传成功 } catch (IOException e) { e.printStackTrace(); } return false;//上传失败 } }
当我们重新运行程序,再次上传图片的时候:
因此,这样才能多次获取新的图片,并且每次都能成功的保存下来!
获取Cookie
1.获取单个Cookie
@RestController
public class UserController {
@RequestMapping("/getck") //获取名称为java的Cookie,并赋值给java
public Object getCk(@CookieValue(value ="java",required = false)String java){
return java;
}
}
2.获取所有Cookie
@RestController
public class UserController {
@RequestMapping("/getck")
public String getCk(HttpServletResponse response,HttpServletRequest request){
String name=request.getParameter("name");
//获取所有Cookie信息
Cookie[] cookies=request.getCookies();
return name+" 你好! ";
}
}
获取Header中的某个信息:
@RestController
public class UserController {
@RequestMapping("/gethd")
public Object getHeader(@RequestHeader("User-Agent")String ua){
return "header---->" + ua;
}
}
在浏览器中输入:http://localhost:8080/gethd
运行结果为:
获取Session:
在获取Session之前,一定要进行存储Session,才能进行获取,存Session没有捷径可走,不能通过注解的方式实现。
什么时候才会有Session的存储??只有当用户的用户名和密码都正确的情况下,才会存储Session。
在Servlet阶段,如何存储Session,那么,在现阶段也是如何存储Session的!!
@RestController
public class UserController {
//定义全局变量
private static final String SESSION_KEY="USERINFO_SESSION";
//存储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){ //赋值给name
return "session + "+name;
}
}
在浏览器中输入:http://localhost:8080/getsess
返回数据:
1.返回静态页面:
Java后端代码:
@Controller
@RequestMapping("/test")
public class TestController {
@RequestMapping("/index")
public Object getIndex(){
return "/index.html"; //静态页面(VSCode)
//加个"/"(斜杠)表示从根路径取找index.html
//如果不加斜杠,则会404报错
}
}
HTML静态页面代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<h1 style="color: red">我是 index.html</h1>
</body>
</html>
在浏览器输入:localhost:8080/test/index
请求转发和重定向:
请求转发和重定向:forward VS redirect
return不但可以返回一个视图,还可以实现跳转,跳转的方式有两个:
-
forward :请求转发
-
redirect :请求重定向
@Controller
@RequestMapping("/test")
public class TestController {
//请求转发
@RequestMapping("/fw")
public String fw(){
return "forward:/index.html";
}
//浏览器输入localhost:8080/test/fw//请求重定向 @RequestMapping("/rd") public String rd(){ return "redirect:/index.html"; } //浏览器输入localhost:8080/test/rd会跳转到localhost:8080/index.html //请求重定向到百度《------》另一种写法 @RequestMapping("/rd2") public void rd2(HttpServletResponse response) throws IOException{ response.sendRedirect("https://www.baidu.com/"); } //浏览器输入localhost:8080/test/rd2会跳转到百度
}
浏览器输入localhost:8080/test/fw
浏览器输入localhost:8080/test/rd会跳转到localhost:8080/index.html
浏览器输入localhost:8080/test/rd2会跳转到百度
请求转发forward和请求重定向redirect的区别!!(面试题)
- 定义不同
- 跳转方不同
- 数据共享不同
- 最终URL不同
- 代码实现不同
- ........................