张裕 发表于 2024-8-25 02:28:30

Spring Web MVC

1. Spring Web MVC

Spring Web MVC是⼀个Web框架 
1.1 MVC

 https://i-blog.csdnimg.cn/direct/db71cc8315c44cc2b84e7c45f55823c3.png
举个例子理解:
Controller相当于前台,接送请求,传给相干部分,部分派人处置惩罚,此时这就是Model 
MVC是一种思想,Spring举行了实现,称为Spring MVC
Spring Boot是创建Spring MVC项目的一种方式而已
1.2 Spring MVC

 https://i-blog.csdnimg.cn/direct/3f5fdf50d3054013b8bc45825ddd9e48.png
而在当前阶段,MVC的概念又发生了一些变化,后端开辟人员不涉及前端页面的开辟,以是也就没有view层
view层又有了一种解释:
之间返回的是试图,现在返回的是视图所需要的数据
https://i-blog.csdnimg.cn/direct/be62ce1c449341a1844b3041884f72e0.png

2. 学习SpringMVC

学习SpringMVC,重点也就是学习如何通过浏览器和⽤⼾程序进⾏交互.


[*]建⽴连接(客户端和服务器)
[*]请求
[*]响应
2.1 @RequestMapping

2.1.1  @RequestMapping修饰方法和类

访问地址:类的路径+方法路径
https://i-blog.csdnimg.cn/direct/ca06e367045e4d5c8e33466e60eacfe5.pnghttps://i-blog.csdnimg.cn/direct/b57c597a4b074eedb214065bbec4c692.png
2.1.2 @RequestMapping支持get和post

https://i-blog.csdnimg.cn/direct/ddd6728fd16b4f8a983f9f65b9e04625.png
https://i-blog.csdnimg.cn/direct/d298c5ded9a54023a9b158e6de997612.png
那么如果就想要get请求怎么办?
https://i-blog.csdnimg.cn/direct/f7aea28305a649bbae5a573fed84326e.png
   留意:
https://i-blog.csdnimg.cn/direct/4e5697be84f44fbb9dc278f3c0ea7b21.png

此时再用postman发送post请求:
https://i-blog.csdnimg.cn/direct/2421c7d4b5c0485dad2537b19719bfa1.png
2.2 请求(即传参)

2.2.1 传递单个函数

https://i-blog.csdnimg.cn/direct/809f69691cbe4462b8cf1e9c6e3e8d64.png
底层逻辑:
从请求的参数中,获取参数名为name的值,并给name赋值
2.2.2 传递多个参数

①使用Integer(包装范例)
https://i-blog.csdnimg.cn/direct/c42f649173f24010b7f154af12dad569.png
参数的顺序可以变更 
②使用int(基本范例)
https://i-blog.csdnimg.cn/direct/f09fe954b748484293bca8bacd6966f1.png
看日志:
发起使用包装范例
https://i-blog.csdnimg.cn/direct/83de75d00b534ba1ba8c56fa4076e4e6.png如果使用基本范例,必须要传值,否则会报错
2.2.3 传递对象

直接传递参数,每修改一个,就需要修改接口,为了制止这种情况,把参数封装成多个对象 
https://i-blog.csdnimg.cn/direct/7528b5c06fa04797ba14384d54b33c8f.png
 https://i-blog.csdnimg.cn/direct/c996c7f355284698870c1768aa149160.png
2.2.4 后端参数重命名

https://i-blog.csdnimg.cn/direct/ecd26d168b744f71ae21334171f5a8ff.png
那如果使用username传参呢?
https://i-blog.csdnimg.cn/direct/07a1746257a449aa93f9886aa6eb18bc.png
如果使用了重命名,必须要使用@RequestParam注解里的名字
如果不想报错:
https://i-blog.csdnimg.cn/direct/3a5a2e33df134b19b349264e3ce8ce2d.png

2.2.5 传递数组

 https://i-blog.csdnimg.cn/direct/b2fff7b406c141e588ec75c749d94dfb.png
当我们请求中,同一个参数有多个时,浏览器就会帮我们给封装成一个数组 
2.2.6 传递集合

 https://i-blog.csdnimg.cn/direct/89b3c32e662d49778ec86de0fc32e435.png
2.2.7 传递JSON(使用最多)

本质上是一个字符串,表示对象的字符串
传递JSON,使用@RequestBody
https://i-blog.csdnimg.cn/direct/e8ead73089f7499cae10008d16a5cb70.png
 https://i-blog.csdnimg.cn/direct/fdb2fc933c804afb9800ea767e60e36a.png
   留意:
https://i-blog.csdnimg.cn/direct/7c2e7c5ba3734b1dba43429fde24487e.png
这个数据一定是在请求正文中 

2.2.8 获取URL中的参数

使用注解@PathVariable
https://i-blog.csdnimg.cn/direct/c36322470bd242fc9513a7de8e0ab6c5.png
获取两个:
https://i-blog.csdnimg.cn/direct/a70cfc3717fc46efa06d9fd639ed9281.png
留意:
获取多个时,要留意顺序,请求格式必须和后端定义的URL格式匹配 
也可以修改名字:
https://i-blog.csdnimg.cn/direct/7e3c08a24b5341fd975341731e6bce65.png
2.2.9 上传图片

 https://i-blog.csdnimg.cn/direct/7401ff6d457543b98b83dae0692cfcb9.png
2.2.10 获取Cookie

简单回首:
HTTP是无状态的.即http没有记忆功能,现在请求和过段时间请求,同样的请求参数,得到的结果一样(这里并不是指数据,而是处置惩罚逻辑)
Cookie客户端机制,Session服务端机制(这里可以以门生和门岗为例理解)
Cookile可以伪造(门生证),Session不能
①先看用Servlet的方式获取:
https://i-blog.csdnimg.cn/direct/0daf752a314a467eb7797227f6c97be7.png
   留意:
https://i-blog.csdnimg.cn/direct/18a23d28e9e0454ab11e56891d36aac5.png
②使用注解的方式获取(只能一个一个去获取):
https://i-blog.csdnimg.cn/direct/38bb64c07222459393bee0d384621f54.png

2.2.11 获取Session

①先看用Servlet的方式获取: 
 https://i-blog.csdnimg.cn/direct/17cc1628cb154d999ca4c3065f44ed41.pnghttps://i-blog.csdnimg.cn/direct/6e0170a4dc284bb38cd9bbcf5604cf1b.png
   留意: https://i-blog.csdnimg.cn/direct/f64eacd9fa6b4257b036bc9089269340.png

 ②使用注解的方式获取(只能一个一个去获取):
 https://i-blog.csdnimg.cn/direct/8a8dbf0fa7e84bcc8bad133e1a1e08ba.png
 使用注解的方式,默认是一个必传参数,修改:
https://i-blog.csdnimg.cn/direct/7bc5f04b4ed041d498d771bd27f1089d.png
③通过spring的内置对象
https://i-blog.csdnimg.cn/direct/0c0aeacb12a946c8979526aa64893660.png

2.2.12 获取Header  

①先看用Servlet的方式获取: 
https://i-blog.csdnimg.cn/direct/ad29720fd5c440bfa35be0015912f373.png
https://i-blog.csdnimg.cn/direct/1df5ee26510e48db8d3ac6fc06e733b8.png
②通过注解获取:
 https://i-blog.csdnimg.cn/direct/dd88d3f52797464693295b91c2ee982a.png

2.3 响应 

2.3.1 返回静态页面

 https://i-blog.csdnimg.cn/direct/6100c0a5735941399c0e02cf202ab7fd.png
可以看到@RestController无法返回页面
   下面来学习@RestController与@Controller:
@Controller告诉Spring,帮我们管理这个代码,我们后续访问时,才华访问到.
https://i-blog.csdnimg.cn/direct/8a5674877ab3496bb8337d6668c7f7bf.png
https://i-blog.csdnimg.cn/direct/d3cca7fcf66346868b31fd0f635f5934.png

2.3.2 返回数据

 https://i-blog.csdnimg.cn/direct/f90da93614b84d709b85ca4424ebd4e2.png
 https://i-blog.csdnimg.cn/direct/272bc2fafc6a44a3ae7e416c4cd352df.png
   注:
@ResponseBody可以修饰类,也可以修饰方法.
修饰类的时候,表示这个类下的所有方法,返回的均为数据.
修饰方法的时候,表示该方法返回的是数据
如果一个类中的所有方法返回的都是数据,我们就把这个注解加在类上

2.3.3 返回html代码片段

https://i-blog.csdnimg.cn/direct/c5456278e93a427993304ad04919bcb4.png
 https://i-blog.csdnimg.cn/direct/e5127536945843a696a5a811873b799b.png

2.3.4 返回JSON

 https://i-blog.csdnimg.cn/direct/df4a1f220740412eb86a54a9d4174107.png
   注:
当我们的接口返回的是String时,content-Type是text/htmlhttps://i-blog.csdnimg.cn/direct/d752384c0a284137ada72b6af534a524.png
当当我们的接口返回的是对象或Map时,content-Type自动设置为application/JSON
 https://i-blog.csdnimg.cn/direct/592422a7f5a2434e86111a2c3151fea8.png
https://i-blog.csdnimg.cn/direct/3bb5a6abe8f04716a74dd17f35663484.png

2.3.5 设置状态码

 https://i-blog.csdnimg.cn/direct/7dde373578ea405fac2c1e90917f2319.png
HTTP状态码 
 https://i-blog.csdnimg.cn/direct/f42d4919486f4c55b368393851e2c080.png
状态码不影响页面展示 

2.3.6 设置Header(相识)



[*]value: 指定映射的URL
[*]method:指定请求的method范例,如GET,POST等
[*]consumes:限制处置惩罚请求(request)的提交内容范例(Content-Type),例如application/json,text/html 
[*]produces: 设置返回的内容范例,仅当request请求头中的(Accept)范例中包罗该指定范例才返回 
[*]Params:指定request中必须包罗某些参数值时,才让该⽅法处置惩罚
[*]headers: 指定request中必须包罗某些指定的header值,才华让该⽅法处置惩罚请求
https://i-blog.csdnimg.cn/direct/45e7aef45e204bf18233145ff09054b0.png
3. 练习

3.1 计算器

https://i-blog.csdnimg.cn/direct/6d7f483da62844f29bd3fb46a41a9154.png
https://i-blog.csdnimg.cn/direct/409d878d36f047d2a34c72f567a08212.png
3.2 登录 

https://i-blog.csdnimg.cn/direct/70f5c704717f463e9fe361c41624e819.png
@RequestMapping("/user")
@RestController
public class UserController {
    @RequestMapping("/login")
    public Boolean login(String userName, String password, HttpSession session){
      //校验参数的合法性
//      if (userName==null || userName.length()==0 || password ==null || password.length() ==0){
//            return false;
//      }

      if (!StringUtils.hasLength(userName) || !StringUtils.hasLength(password)){
            return false;
      }
      //进行用户名和密码的校验
      if ("admin".equals(userName) && "admin".equals(password)){
            //设置Session
            session.setAttribute("username","admin");
            return true;
      }
      return false;
    }

    @RequestMapping("/getUserInfo")
    public String getUserInfo(HttpServletRequest request){
      //从Session 获取登录用户
      HttpSession session = request.getSession(false);
      String userName = null;
      if (session!=null){
            userName = (String) session.getAttribute("username");
      }
      return userName;
    }
}



3.3 留言板

https://i-blog.csdnimg.cn/direct/b1ae0e6b7d714e0b8afc7817bd81e66d.png
https://i-blog.csdnimg.cn/direct/d49a081441ed4279b252469e03830490.png
@RequestMapping("/message")
@RestController
public class MessageController {
    private List<MessageInfo> messageInfos = new ArrayList<>();

    @RequestMapping("/publish")
    public Boolean publish(MessageInfo messageInfo){
      //进行参数校验//!.. = 为空
      if (!StringUtils.hasLength(messageInfo.getFrom())
                || !StringUtils.hasLength(messageInfo.getTo())
                || !StringUtils.hasLength(messageInfo.getMessage())){
            return false;
      }
      //添加留言
      messageInfos.add(messageInfo);
      return true;
    }

    @RequestMapping("/getMessageInfo")
    public List<MessageInfo> getMessageInfo(){
      return messageInfos;
    }

} @Data
public class MessageInfo {
    private String from;
    private String to;
    private String message;

}
   注:
这里补充一个依赖lombok,取代getter和setter   @Data
https://i-blog.csdnimg.cn/direct/c313d143c0ae4024834886fdc432e497.png
如果只想加到from上:
https://i-blog.csdnimg.cn/direct/f59d8c184bb94a209130631a52132f23.png
后端测试:
https://i-blog.csdnimg.cn/direct/e40757ed10734dd58807cc48b2c08b56.png
3.4 图书管理系统(简版,后续补充) 

https://i-blog.csdnimg.cn/direct/da7e7b7a35974b3680210c7b1aeb9218.png
@RequestMapping("/user")
@RestController
public class UserController {
    @RequestMapping("/login")
    public Boolean login(String userName, String password, HttpSession session){
      //校验
      if (!StringUtils.hasLength(userName) || !StringUtils.hasLength(password)){
            return false;
      }
      //验证是否正确
      if ("admin".equals(userName) && "123".equals(password)){
            session.setAttribute("userName",userName);
            return true;
      }
      return false;
    }
}
@RequestMapping("/getBookList")
    public List<BookInfo>getBookList(){
      //1.获取图书的数据
      //2.对图书的数据进行处理
      //3.返回数据

      //mock表示虚拟的假数据
      List<BookInfo> bookInfos = mockData();
      for(BookInfo bookInfo : bookInfos){
            if (bookInfo.getStatus() == 1){
                bookInfo.setStatusCN("可借阅");
            }else {
                bookInfo.setStatusCN("不可借阅");
            }
      }
      return bookInfos;
    }

    private List<BookInfo> mockData(){
      List<BookInfo> bookInfos = new ArrayList<>(15);
      for (int i = 0; i < 15; i++){
            BookInfo bookInfo = new BookInfo();
            bookInfo.setId(i);
            bookInfo.setBookName("图书"+i);
            bookInfo.setAuthor("作者"+i);
            bookInfo.setCount(new Random().nextInt(200));
            bookInfo.setPrice(new BigDecimal(new Random().nextInt(100)));
            bookInfo.setPublish("出版社"+i);
            bookInfo.setStatus(i%5==0?2:1);
            bookInfos.add(bookInfo);
      }
      return bookInfos;
    } @Data
public class BookInfo {
    private Integer id;
    private String bookName;
    private String author;
    private Integer count;
    private BigDecimal price;
    private String publish;
    private Integer status;//1-可借阅
    private String statusCN;

}  后端代码经测试无误
4. 应用分层

4.1 三层架构 



[*]体现层:担当请求,返回结果
[*]业务逻辑层:告急处置惩罚业务逻辑
[*]数据层:处置惩罚数据,包罗数据的存储,获取(增删改查)
可以结合下图理解:https://i-blog.csdnimg.cn/direct/148781bb93884c2e8d770a90deabebf1.png
以图书管理系统为例:
https://i-blog.csdnimg.cn/direct/7337033748ba482abba8c0bfbfad86fb.png

4.2 MVC与三层架构的区别与联系



[*]从概念上来讲,⼆者都是软件⼯程范畴中的架构模式.
[*]MVC架构模式由三部分组成,分别是:模子(Model),视图(View)和控制器(Controller).
[*]三层架构将业务应⽤划分为:体现层,业务逻辑层,数据访问层.
https://i-blog.csdnimg.cn/direct/82f3b07e91464526b0a9eccaa0bfeb02.png


[*]MVC模式夸大数据和视图分离,将数据展⽰和数据处置惩罚分开,通过控制器对两者进⾏组合.
[*]三层架构夸大不同维度数据处置惩罚的⾼内聚和低耦合,将交互界⾯,业务处置惩罚和数据库操作的逻辑分开.
[*]⻆度不同也就谈不上互相替换了,在⽇常的开辟中可以经常看到两种共存的情况.
[*]⼆者的⽬的是雷同的,都是"解耦,分层,代码复⽤"
4.3 高内聚,低耦合



[*]⾼内聚指的是:⼀个模块中各个元素之间的联系的紧密水平,如果各个元素(语句、程序段)之间的联系水平越⾼,则内聚性越⾼,即"⾼内聚"。
[*]低耦合指的是:软件中各个层、模块之间的依赖关联程序越低越好。
⽐如说:
邻⾥邻人,楼上漏⽔,楼下遭殃,就是耦合.
家庭⼀个成员⽣病,其他成员资助照顾,就叫内聚.
⼀个家庭内部的关系越紧密越好, ⼀个家庭尽可能少的影响另⼀个家庭,就是低耦合

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: Spring Web MVC