IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> Spring MVC -> 正文阅读

[Java知识库]Spring MVC

什么是 MVC

Spring MVC 其实是 Spring Web MVC,是基于 Servlet API,所以 Servlet 是 Spring MVC 的 “父亲”。因此,Servlet 那一套编程方法,在 Spring MVC 中,也是可以使用的。但是 Spring MVC 比 servlet 要简单很多。

Spring MVC :一开始就在 Spring 框架当中。只是属于 Spring 中的一个 web 模块。

一个 web 项目,只做三件事

  1. 实现用户请求 到 程序 的 链接,就是用户请求可以被 程序接收到。
  2. 在前后端建立联系的情况下,拿到用户请求的参数。
  3. 拿到参数之后,进行业务处理,并将其结果返回给前端。
  4. 使用 Spring MVC 的话,只需要前后端的名称一样就行了。

MVC 定义

MVC 是 Model View Controller (模型视图控制器)的缩写,它是软件?程中的?种软件架构模式,它把软件系统分为模型、视图和控制器三个基本部分。
在这里插入图片描述

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

四者之间的关系如下
在这里插入图片描述

  1. 可以把 View,Controller,Model 看作是一个软件(项目)。
  2. 然后用户通过浏览器发送一个 HTTP 请求到 Controller ,然后 Controller 完成对数据的校验,校验数据的正确性和合法性。
  3. Controller 校验数据通过之后,就会将请求数据发送到 model,然后 model 对数据库进行处理之后,再把结果发给 Controller
  4. 然后 COntroller 在把得到的数据交给 View
  5. View 是服务器的视图层,然后和前端的模板相结合,再加上渲染,然后发给客户,客户就能看懂了。

MVC 和 Spring MVC 的关系

两者的关系,就像 IoC 和 DI 的关系。前者是思想,后者是实现。

Spring MVC 是?个实现了 MVC 模式,并继承了 Servlet API 的 Web 框架。因为是 Web 框架,所以?户在浏览器中输?了 url 之后,我们的 Spring MVC 项 ?就可以感知到?户的请求。

Spring MVC 的影响

现在绝大部分的 Java 项目都是基于 Spring(或 Spring Boot)的,而 Spring 的核心就是 Spring MVC。现在大部分的 Java 项目都是 Spring MVC 项目。

创建 Spring MVC 项目

创建项目和我们之前创建 Spring Boot 项目一样,只是在添加依赖的时候,选择 Spring web 就好了:
在这里插入图片描述
这样就完成了 Spring MVC 项目的创建了。

Spring MVC 作用

  1. 实现 用户 和 程序 的映射(在浏览器输入 URL 之后,能够在程序中匹配到相应的方法)
  2. 服务器端要得到用户的请求参数
  3. 服务器端要将结果返回给用户(前端)

实现用户 和 程序的映射

  1. 使用 @RequestMapping(“/xxx”) 映射,可以加在 类上面,就是一级目录,然后方法上面再加的话,就是二级目录:

    @Controller
    @ResponseBody
    @RequestMapping("/user")
    public class UserController {
    
        @RequestMapping("/sayhi")
        public String sayHi() {
            return "hello world";
        }
    }
    

    访问方法如下:
    在这里插入图片描述

    user 是一级目录,sayhi 是二级目录。默认是 GET 请求:
    在这里插入图片描述

  2. 使用 POST 请求来访问资源,通过 method 参数来设置:

    @Controller
    @ResponseBody
    @RequestMapping("/user")
    public class UserController {
    
        @RequestMapping(method = RequestMethod.POST, value = "/sayhi")
        public String sayHi() {
            return "hello world";
        }
    }
    

    访问结果如下:
    在这里插入图片描述
    就支持 POST 访问了。

  3. 使用 @PostMapping 来指定 POST 访问:

    @Controller
    @ResponseBody
    @RequestMapping("/user")
    public class UserController {
    
        @PostMapping("/sayhi")
        public String sayHi() {
            return "hello world";
        }
    }
    

    访问结果如下:
    在这里插入图片描述

  4. 通过 GetMapping 来进行 GET 访问:

    @Controller
    @ResponseBody
    @RequestMapping("/user")
    public class UserController {
    
        @GetMapping("/sayhi")
        public String sayHi() {
            return "hello world";
        }
    }
    

    访问结果如下:
    在这里插入图片描述

获取用户请求参数

获取单个参数

通过传入参数,然后返回对象:

@Controller
@ResponseBody
@RequestMapping("/user")
public class UserController {

    @GetMapping("/getuserbyid")
    public UserInfo getUserById(Integer id) {
        UserInfo userInfo = new UserInfo();
        userInfo.setId(id);
        userInfo.setUsername("zhangsan");
        userInfo.setAge(18);
        return userInfo;
    }
}

传入 id = 1,只要保证传入的参数和接收的参数一样就好了,运行结果如下:
在这里插入图片描述
使用 Integer 是可以接收 null 的。

获取多个参数

通过传多个参数来获取:

@Controller
@ResponseBody
@RequestMapping("/user")
public class UserController {

    @RequestMapping("/login")
    public String login(String username, String password) {
        return "用户名:" + username + " 密码:" + password;
    }
}

运行结果如下:
在这里插入图片描述
也就是获取多个参数和获取一个参数的方法是一样的,只需要传递多个参数就好了。

获取对象

如果有多个参数的时候,通过传对象可以让结果看的更简洁:

@Controller
@ResponseBody
@RequestMapping("/user")
public class UserController {

    @RequestMapping("/reg")
    public String login(UserInfo userInfo) {
        return "用户信息:" + userInfo;
    }
}

前端传这样的参数:

http://127.0.0.1:8080/user/reg?username=zhangsan&password=123&age=18

运行结果如下:
在这里插入图片描述

后端参数重命名

某些特殊情况下,前端传递的参数 key 和我们后端接收的 key 可能不一致比如前端传递了 name 之后,后端是用 username 来接收的,那么就会报错。通过 @RequestParam 来对存在念书重命名:

@Controller
@ResponseBody
@RequestMapping("/user")
public class UserController {

    @RequestMapping("/reg")
    public String login(@RequestParam("name") String username) {
        return "用户名:" + username;
    }
}

前端参数:

http://127.0.0.1:8080/user/reg?name=zhangsan

运行结果如下:

在这里插入图片描述
也就是当使用了这个注解之后,前端必须要传一个 name 参数。否则就报错。如果加了 required 之后,设置 required 的参数为 false,因为默认是 true,就不会报错了,会显示用户名是 null:

@Controller
@ResponseBody
@RequestMapping("/user")
public class UserController {

    @RequestMapping("/reg")
    public String login(@RequestParam(value = "name", required = false) String username) {
        return "用户名:" + username;
    }
}

运行结果如下:
在这里插入图片描述

接收 JSON 对象

使用 RequestBody 注解来完成对象的接收,后端代码如下:

@Controller
@ResponseBody
@RequestMapping("/user")
public class UserController {

    @RequestMapping("/reg")
    public String login(@RequestBody UserInfo userInfo) {
        return "用户信息:" + userInfo;
    }
}

然后通过 Postman 来模拟:
在这里插入图片描述

从 URL 地址当中获取参数

这里并不是从 URL 地址中的参数部分获取参数,而是从 / 来作为分隔符获取参数,通过 @PathVariable 注解来实现

@Controller
@ResponseBody
@RequestMapping("/user")
public class UserController {

    @RequestMapping("/info/{id}/{name}")
    public String getURLInfo(@PathVariable Integer id, @PathVariable String name) {
        return "ID:" + id + " name:" + name;
    }
}

前端 URL:

http://127.0.0.1:8080/user/info/2/zhangsan

运行结果如下:
在这里插入图片描述
在这里插入图片描述

上传文件

通过 @RequestPart 注解来实现对文件的上传,只需要对参数加上注解就好了。然后通过 Spring 的 MultipartFile 来接收文件就好了:

@Slf4j
@Controller
@ResponseBody
@RequestMapping("/user")
public class UserController {

    @RequestMapping("/upload")
    public boolean upImg(Integer id, @RequestPart("image") MultipartFile file) {
        boolean result = false;
        //保存图片到本地目录
        try {
            file.transferTo(new File("D:/img.png"));
        } catch (IOException e) {
            log.error("上传图片失败: " + e.getMessage());
        }
        return result;
    }
}

Postman 模拟如下:
在这里插入图片描述
D 盘的文件如下:
在这里插入图片描述
但是如果这样每次的名字都一样的话,就会导致文件覆盖。

配置文件保存路径

直接把路径放在配置文件当中,这样的话,如果项目上线也很容易修改,直接修改为线上环境就好了,application 是必不可少的,不过可以通过 - 在 application 后面 加上名称。通过 application.yml 来配置 配置文件的运行环境:

# 设置配置文件的运行平台
spring:
  profiles:
    active: dev

在这里插入图片描述
开发环境配置
在这里插入图片描述
生产环境如下
在这里插入图片描述
文件路径

@Controller
@ResponseBody
@RequestMapping("/user")
public class UserController {

    //从配置文件中读取图片的保存路径
    @Value("${img.path}")
    private String imgPath;

    @RequestMapping("/sayHi")
    public String sayHi() {

        return "文件路径:" + imgPath;
    }
}

访问结果如下:
在这里插入图片描述
这样就完成了对图片路径的访问。换成生产环境也一样可以。

图片名不能重复

让图片名不能重复,通过 UUID 来让图片永远不重复。UUID 是自动生成一个全球不同的一串数字。如果用时间戳的话,总会有两个人同时传数据,所以就会导致内容覆盖。

获取图片的格式

就是获取原图片的格式,不能向我们上面这样,改变图片的格式。从最后一个点,向后截取,就能获取到文件的后缀名了:

@Slf4j
@Controller
@ResponseBody
@RequestMapping("/user")
public class UserController {

    //从配置文件中读取图片的保存路径
    @Value("${img.path}")
    private String imgPath;

    @RequestMapping("/upload")
    public boolean upImg(Integer id, @RequestPart("image") MultipartFile file) {
        boolean result = false;
        //保存图片到本地目录

        String fileName = file.getOriginalFilename();
        fileName = fileName.substring(fileName.lastIndexOf("."));
        fileName = UUID.randomUUID().toString() + fileName;
        try {
            file.transferTo(new File(imgPath + fileName));
            result = true;
        } catch (IOException e) {
            log.error("上传图片失败: " + e.getMessage());
        }
        return result;
    }
}

Postman 模拟如下:
在这里插入图片描述
保存路径内容如下:
在这里插入图片描述

获取 Cookie/Session/header

获取 Request 和 Response 对象

web 程序里面都会有 Request 和 Response 参数,只需要在需要的时候,直接使用就好了:

@Controller
@ResponseBody
@RequestMapping("/user")
public class UserController {

    @RequestMapping("/sayhi")
    public String sayHi(HttpServletRequest request) {
        return "hello world " + request.getParameter("name");
    }
}

运行结果如下:
在这里插入图片描述

获取 Cookie

直接使用 @CookieValue 就好了,先设置好 Cookie:
在这里插入图片描述
然后输出:

@Controller
@ResponseBody
@RequestMapping("/user")
public class UserController {

    @RequestMapping("/cookie")
    public String getCookie(@CookieValue("lisi") String cookie) {
        return "Cookie Value" + cookie;
    }
}

运行结果如下:
在这里插入图片描述
如果要读取多个 cookie 的话,就设置多个 Cookie 参数。

获取 Header

直接通过 @RequestHeader 的注解来实现获取 Header,我们获取 Header 里面的 user-agent:

@Controller
@ResponseBody
@RequestMapping("/user")
public class UserController {

    @RequestMapping("/header")
    public String getCookie(@RequestHeader("User-Agent") String userAgent) {
        return "user-Agent: " + userAgent;
    }
}

运行结果如下:
在这里插入图片描述

存储和获取 Session

设置 Session

听过 HttpSession 来设置 session:

@Controller
@ResponseBody
@RequestMapping("/user")
public class UserController {

    @RequestMapping("/header")
    public boolean setSession(HttpServletRequest request) {
        boolean result = false;
        //得到 Session 
        HttpSession session = request.getSession(true);//true 是创建会话
        //使用 setAtt 设置值
        session.setAttribute("userinfo", "userinfo");
        return true;
    }
}

运行结果如下,设置 Session 就是多了一个 JSESSIONID :
在这里插入图片描述

获取 Session

Spring Boot 通过 @SessionAttribute 注解就可以获取到 Session 了:

@Controller
@ResponseBody
@RequestMapping("/user")
public class UserController {

    @RequestMapping("/getsession")
    public String getSession(@SessionAttribute(value = "userinfo",required = false) String userinfo) {
        return "会话:" + userinfo;
    }
}

访问结构如下:
在这里插入图片描述
加上 required 的时候,如果 session 当中没有 此属性 的时候,就不会报错了。

返回数据

如下代码:

@Controller
@RequestMapping("/user")
public class UserController {

    @RequestMapping("/sayhi")
    public String sayHi() {
        return "hello";
    }
}

这样返回的其实是一个 静态页面 的结果:
在这里插入图片描述
把代码当中换成 hello.html ,然后写一个页面,就可以了:

@Controller
public class UserController {

    @RequestMapping("/sayhi")
    public String sayHi() {
        return "hello.html";
    }
}

运行结果如下:
在这里插入图片描述
@ResponseBody,就表示返回非静态页面的数据。

使用 @RestController

通过 @RestController 注解,就可以直接返回非静态页面的数据了:

@RestController
public class UserController {

    @RequestMapping("/sayhi")
    public String sayHi() {
        return "hello.html";
    }
}

运行结果如下:
在这里插入图片描述

练习

form 表单

通过 MVC 和 form 表单来实现。前端代码:

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>add</title>
    </head>
    <body>
        <form action="/calc">
            <h1>计算器</h1>
            数字1:<input name="num1" type="text"><br>
            数字2:<input name="num2" type="text"><br>
            <input type="submit" value=" 点击相加 ">
        </form>
    </body>
</html>

后端接受的时候,路由也是 /calc 来接收,然后返回页面数据就好了:

@RestController
public class CalcController {

     @RequestMapping("/calc")
    public String calc(Integer num1, Integer num2) {
         if (num1 == null || num2 == null) {
             return "<h1>参数错误!</h1><a href='javascript:history.go(-1);'>返回</a>";
         }
         return "<h1>结果:" + (num1 + num2) + "</h1><a href='javascript:history.go(-1);'>返回</a>";
    }
}

后端返回的结果,这里写成了 h1 标签。运行结果如下:
在这里插入图片描述
点击之后效果如下:
在这里插入图片描述

Ajax

通过 Ajax 来完成用户的登录,通过模拟登录来实现用户交互,前端代码如下:

<!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">
    <script src="js/jquery-1.9.1.min.js"></script>
    <title>Document</title>
    <script>
      //ajax 提交
      function mysub(){
        //1.判空   也可以把 jQuery 符号换成 $
        var username = jQuery("#username");
        var password = jQuery("#password");
        //使用 trim 方法来去掉空格
        if(jQuery.trim(username.val())==""){
          alert("请先输入用户名!");
          //把光标重新放到元素上面
          username.focus();
          return;
        }
        if(jQuery.trim(password.val())==""){
          alert("请先输入密码!");
          password.focus(); //光标重制到此元素
          return;
        }
        jQuery.ajax({
          url:"/login",
          type:"POST",
          data:{"username":username.val(),
            "password":password.val()},
          success:function(result){
            alert(JSON.stringify(result));
          }
        });
      }
    </script>
  </head>
  <body>
    <div style="text-align: center;">
      <h1>登录</h1>
      用户:<input id="username">
      <br>
      密码:<input id="password" type="password">
      <br>
      <input type="button" value=" 提交 " onclick="mysub()" style="margin-top: 20px;margin-left: 50px;">
    </div>
  </body>
</html>

后端代码如下:

@RestController
public class UserController {

    @RequestMapping("/login")
    public HashMap<String, Object> login(String username, String password) {
        HashMap<String, Object> result = new HashMap<>();
        int state = 200;
        int data = -1;//等于 1 的话,就表述登陆成功
        String msg = "";
        if (StringUtils.hasLength(username) && StringUtils.hasLength(password)) {
            if (username.equals("admin") && password.equals("admin")) {
                data = 1;
                msg = "";
            }
        } else {
            msg = "非法参数";
        }
        result.put("state", state);
        result.put("data", data);
        result.put("msg", msg);
        return result;
    }
}

运行结果如下:
在这里插入图片描述
故意填错密码:
在这里插入图片描述
填对密码的时候,就和我们约定的结果一样了:
在这里插入图片描述

通过 JSON 来传输

通过 JSON 来传输数据的时候,后端就要通过 @RequeestBody 来接收了。然后前端也要指定为 JSON 格式发送。就是转化为 JSON 字符串就好了。前端代码如下:

<!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">
    <script src="js/jquery-1.9.1.min.js"></script>
    <title>Document</title>
    <script>
      //ajax 提交
      function mysub(){
        //1.判空   也可以把 jQuery 符号换成 $
        var username = jQuery("#username");
        var password = jQuery("#password");
        //使用 trim 方法来去掉空格
        if(jQuery.trim(username.val())==""){
          alert("请先输入用户名!");
          //把光标重新放到元素上面
          username.focus();
          return;
        }
        if(jQuery.trim(password.val())==""){
          alert("请先输入密码!");
          password.focus(); //光标重制到此元素
          return;
        }
        jQuery.ajax({
          url:"login",
          type:"POST",
          contentType:"application/json",
          data:JSON.stringify({"username":username.val(),
            "password":password.val()}),
          success:function(result){
            alert(JSON.stringify(result));
          }
        });
      }
    </script>
  </head>
  <body>
    <div style="text-align: center;">
      <h1>登录</h1>
      用户:<input id="username">
      <br>
      密码:<input id="password" type="password">
      <br>
      <input type="button" value=" 提交 " onclick="mysub()" style="margin-top: 20px;margin-left: 50px;">
    </div>
  </body>
</html>

后端代码如下:

@RestController
public class UserController {

    @RequestMapping("/login")
    public HashMap<String, Object> login(@RequestBody UserInfo userInfo) {
        HashMap<String, Object> result = new HashMap<>();
        int state = 200;
        int data = -1;//等于 1 的话,就表述登陆成功
        String msg = "";
        if (StringUtils.hasLength(userInfo.getUsername()) && StringUtils.hasLength(userInfo.getPassword())) {
            if (userInfo.getUsername().equals("admin") && userInfo.getPassword().equals("admin")) {
                data = 1;
                msg = "";
            } else {
                msg = "用户名或密码不正确";
            }
        } else {
            msg = "用户名或密码不正确";
        }
        result.put("state", state);
        result.put("data", data);
        result.put("msg", msg);
        return result;
    }
}

运行结果如下:
在这里插入图片描述

请求转发和请求重定向

请求转发是 forward,请求重定向是 redirect。

请求转发

通过 forward 来实现请求转发:

@Controller
public class UserController {

    @RequestMapping("/myforward")
    public String myForward() {
        return "forward:/hello.html";
    }
}

forward 后面加的是请求转发路径。运行结果如下:
在这里插入图片描述
直接到了 hello.html 页面了。

请求重定向

请求重定向是 redirect :

@Controller
public class UserController {

    @RequestMapping("/myredirect")
    public String myRedirect() {
        return "redirect:/hello.html";
    }
}

运行结果如下:
在这里插入图片描述
这里就是直接访问 hello.html 页面了。重定向是发生在客户端的行为,不会经过服务器端。

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-09-21 00:12:55  更:2022-09-21 00:16:02 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 10:01:53-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码