所谓的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;}}
在浏览器输入:localhost:8080/sayHi?name=zhangsan&password=123456
获取对象:
首先,我们来自定义一个对象吧!
@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(后端)//必传参数usernamereturn 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(后端)//必传参数usernamereturn name+" "+password;}}
在浏览器中输入:localhost:8080/reg2?password=123456
获取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参数部分的参数(?之后的参数)
http://localhost:8080/reg4?name=zhangsan&password=123456
获取上传图片:
@RestController
public class UserController {@RequestMapping("myupload")public Object upload(@RequestPart("mying")MultipartFile file){//@RequestPart("mying")拿到请求的文件,赋值给MultipartFile fileFile 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 fileString 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,并赋值给javapublic 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){ //赋值给namereturn "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不同
- 代码实现不同
- ……………………