SpringMVC探秘: 实现MVC模式的Web应用

1. SpringMVC概述

1.1. 什么是SpringMVC?

Spring Web MVC (Model View Controller)是基于 Servlet API 构建的原始 Web 框架,从一开始就包含在 Spring Framework 中。正式名称“Spring Web MVC”来自其源模块的名称(spring-webmvc),但它通常被称为“Spring MVC”。

1.1.1. MVC与SpringMVC

MVC 是 Model View Controller 的缩写,它是软件工程中的一种软件架构模式,它把软件系统分为模型、视图和控制器三个基本部分。

img

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

🎯MVC 执行流程:

  1. 用户(客户端)向发送的请求首先到服务器端的 Controller。
  2. Controller 将请求继续转发给 Model。
  3. Model 处理业务并将数据结果返回给 Controller。
  4. Controller 会将数据交给 View 引擎。
  5. View 会将数据进行转换渲染生成最终的页面给用户(客户端)。

🎯MVC与Spring MVC之间的区别?
MVC 是一种思想,而 Spring MVC 是对 MVC 思想的具体实现。
Spring MVC 是⼀个实现了 MVC 模式,并继承了 Servlet API 的 Web 框架,当⽤户在浏览器中输⼊了 URL 之后,我们的 Spring MVC 项目就可以感知到用户的请求。

1.2. SpringMVC项目的优势

现在绝大部分的 Java 项目都是基于 Spring(或 Spring Boot)的,而 Spring 的核心就是 Spring MVC;也就是说 Spring MVC 是 Spring 框架的核心模块,而 Spring Boot 是 Spring 的脚手架,因此我们可以推断出,现在市面上绝大部分的 Java 项目基本上都是 Spring MVC 项目,这也是我们要学 Spring MVC 的原因。

学习SpringMVC项目,主要学习的是三个功能:

  1. 连接:将用户(浏览器)和 Java 程序连接起来,也就是访问⼀个地址(URL)能够调用到我们的
    Spring 程序。
  2. 获取参数:用户访问的时候会携带⼀些参数数据,在程序中要能够获取到这些参数。
  3. 输出数据:执行了业务逻辑之后,要把程序执行的结果返回给用户。

2. SpringMVC项目的创建与使用

2.1. 创建SpringMVC项目

首先,我们需要新建 SpringBoot 项目。

img

要注意,在添加依赖的时候,一定要添加 Web 模块,它其实就是 SpringMVC 的依赖。

img

2.2. 设置路由

设置路由可以实现程序与用户之间的映射(路由映射),也就是当用户访问某一个 URL 时,会将用户的请求对应到程序中的某个类的某个方法中,实现浏览器连接程序的作用,设置路由可以使用@RequestMapping注解实现,注意要实现路由访问,必须使用 @Controller 将对象储存到 Spring 中。

package com.example.demo.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller // 让 spring 框架启动时, 加载
@ResponseBody // 返回⾮⻚⾯数据
@RequestMapping("/user") // 一级路由
@Slf4j // 日志框架
public class UserController {
    @RequestMapping("/hi") // 二级路由
    public String sayHi() {
        return "<h1>Hi, Spring MVC.</h1>";
    }
}

其中,访问方法所返回数据或页面的 URL 为http://IP:端口号/类上的路由地址/方法上加的路由地址,这样就能访问到每个方法所返回的页面或者数据了,也可以只在方法上设置路由地址;且当类中只有一个方法时,类上/方法上也可以不设置路由地址(挑一个设置即可),此时直接使用一级路由就能直接访问了。

由于历史原因,方法返回默认是一个静态页面,如果要设置返回一个页面数据,需要搭配使用 @ResponseBody注解,放在类上,类里面所有的方法都会默认放回的是页面数据,而不是一个静态页面,放到方法上生效的只是当前方法。

启动程序,我们去浏览器通过访问http://127.0.0.1:8080/user/hi地址,观察结果。
img

@RequestMapping默认情况下,同时支持 GET 和 POST 等其他请求方式;而如果我们想要仅支持一种请求方式,需要做一些配置。

我们需要设置 @RequestMapping 的method属性为RequestMethod.xxx,RequestMethod 其实是一个枚举,里面储存了多种的请求方式。
img

我们这里设置一个 POST 请求。

@Controller
@ResponseBody
@Slf4j
@RequestMapping("/user")
public class UserController {
    @RequestMapping(method = RequestMethod.POST, value = "/onlypost")
    public String func1() {
        return "post";
    }
}

我们使用 postman 构造 GET 与 POST 请求看看能不能进行处理。

首先我们来试一试GET请求,
img
通过抓包,可以看到返回给用户的结果是405,出错了,这就表示该方法是不支持 GET 请求的,我们再来试一试POST请求。

img
构造 POST 请求:
img
返回结果:
img
返回了一个post数据,与我们预期相同,所以像上面那样进行配置,可以使一个方法只支持 GET 或 POST 一种请求格式。

当然还有另外的方法,如果只支持 POST 请求,我们还可以使用@PostMapping注解来实现。

@PostMapping("/hello")
public String func2() {
    return "hello";
}

img

img

同理,如果需要只支持 GET 请求我们也可以使用@GetMapping注解来进行实现。

2.3. 获取参数

在 MVC 项目中,因为 SpringMVC 是基于 Servlet 的,所以使用 Servlet 那一套操作也是可以的,只不过有点繁琐,Spring 中就有了更方便获取参数的方式。

2.3.1. 获取一个参数

假设有一个类User,客户端会传一个用户id到后端,我们需要返回一个User对象。

package com.example.demo.model;

import lombok.Data;

@Data
public class User {
    private int id;
    private String name;
    private String password;
}

根据 id 查询 User 对象,这里主要是示范 Spring Web API 的使用,就不添加数据库查询了,这里直接构造相应 id 的对象,返回即可,重点是模拟数据的传入与传出。

我们直接在方法中加上一个形参(要与前端传入的参数名相同),访问路径时就会后会自动根据形参的名字以前端传来参数的 key 进行匹配,如果能够对应,后端就能成功接收参数。

@RequestMapping("/getuserbyid")
public User getUserById(Integer id) {
    User user = new User();
    user.setId(id);
    user.setName("张三");
    user.setPassword("zs12345678");
    return user;
}

我们再通过 postman 来构造一个 id 参数,并获取到一个 User 对象。

Spring 会根据响应的返回值,决定返回数据的类型,比如你返回一个对象或 Map,就会返回一个 json 格式的数据,你返回一个页面,那它返回的就是页面类型的数据。

img

因为 SpringMVC 是基于 Servlet 的,所以 Servlet 中的那一套 API 在这里也适用,在MVC中,方法中的HttpServletRequest 与 HttpServletResponse 参数默认是隐藏的,如果想要使用,需要显示地进行声明,获取请求参数时需要通过 HttpServeletRequest 对象手动获取,我们只声明一个即可,相较来看写法上就比较繁琐了。

@RequestMapping("/getUserById2")
public User getUserById2(HttpServletRequest request) {
    User user = new User();
    user.setId(Integer.parseInt(request.getParameter("id")));
    user.setName("李四");
    user.setPassword("ls12345678");
    return user;
}

img

还需要知道默认情况下,前端多传或者少传参数都是可以的,少传参数的情况下,结果就是 null,而多传参数并不会被 SpringMVC 读取。

2.3.2. 获取多个参数

我们还可以获取多个参数,此时可以给方法设置多个参数,也可以设置一个对象参数直接获取多个前端传来的参数。

比如,一个登录的逻辑,需要用户传来账户名与密码,这里就不实现一个登录逻辑了,我们直接将获取到的账户名与密码作为响应返回出去。

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

我们从前端传入同名的键值对,后端就能够自动获取到。
img
当然,我们也可以使用对象来进行接收前端的参数,后端会根据 key 与对象中的属性名自动地进行匹配。

@RequestMapping("/object")
public String getObject(User user) {
    return user.toString();
}

User 中的属性有 id,name 和 password,我们直接从前端传递三个对应名称的键值对,SpringMVC 会自动进行对象的初始化(参数映射)。

img

除此之外,我们还可以接收form表单的形式的参数,可以使用是 GET/POST 请求方式。
img

2.3.3. 获取日期参数

使用@DateTimeFormat注解完成日期参数格式转换,该注解有个pattern的属性,值为我们所传递的日期参数的格式即可。

@RequestMapping("/dateParam")
public String dateParam(@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime updateTime) {
    return updateTime.toString();
}

img

2.3.4. 参数重命名@RequestParam

如果后端方法形参名和与客户端请求参数名不匹配时,就会出现参数接收不到的情况,这种情况,我们可以使用@RequestParam来重命名后端的参数值(后端参数映射)。

其中@RequestParam里面的参数为前端传来的参数名字,它可以自动匹配到注解所在的形参中。

@RequestMapping("/rename")
public String getNameAndPass(@RequestParam("name") String username, 
                             @RequestParam("pass") String password) {
    return "用户名:" + username + "密码:" + password;
}

img
还需要注意,使用 @RequestParam 注解修饰的参数,默认情况下,参数是必传,如果不传或少传就会报 400 请求错误。
img
这个情况是因为 @RequestParam 注解里面还有一个属性required,默认情况下值为true,这个属性的意思是是否是必须参数,所以参数重命名后,重命名的参数默认情况下不能缺少,如果不想将参数设置成必须,但是想重命名,那么就需要额外设置required属性值为false

@RequestMapping("/rename")
public String getNameAndPass(@RequestParam(name = "name", required = false) String username, 
                             @RequestParam(name = "pass", required = false) String password) {
    return "用户名:" + username + " 密码:" + password;
}

img

2.3.5. 获取json字符串

如果我们想要获取 json 格式的参数,需要使用@RequestBody注解修饰参数(声明了这个参数接收 json 数据)。

@RequestMapping("/object2")
public String getObject2(@RequestBody User user) {
    return user.toString();
}

像上面这样,我们能够获取到 json 格式的参数了。
img
但这样设置后,就不能接收其他格式的数据了。

2.3.6. 获取URL中的参数

这里所说的从 URL 获取参数,并不是获取查询字符串部分的参数,而是直接拿 URL 地址中的参数,简单来说,就是从 URL 中?前面的字段中获取参数;这种方式的优点是搜索引擎抓取关键字权重更高,有利于提高曝光度,且让 URL 更简洁。

获取方法:使用特定 URL 格式和在参数前加上注解@PathVariable

@RequestMapping("/hero/{id}/{name}")
public String geuURL(@PathVariable Integer id, @PathVariable String name) {
    return "id:" + id + "  name:" + name;
}

我们访问http://127.0.0.1:8080/user/hero/1234/梧桐网页就能够获取到如下内容:
img
其中hero表示二级目录地址,后面使用{}的就表示参数。
img

2.3.7. 上传文件

文件的上传,我们需要使用到@RequestPart注解和MultipartFile,我们写方法形参定义的时候,需要一个MultipartFile变量来接收前端传递的文件参数,并设置@RequestPart的属性来表示接收前端参数的名字。

//上传文件
@RequestMapping("/upimg")
public boolean updateImg(@RequestPart("img") MultipartFile file) {
    boolean result = false;
    try {
        //将图片保存
        file.transferTo(new File("D:\\image\\yan.jpg"));
        result = true;
    } catch (IOException e) {
        log.error("图片上传失败!" + e.getMessage());
    }
    return result;
}

我们使用 postman 构造一个请求,给服务器端发送一个图片,我们来看看目标目录下是否得到了我们上传的文件。
img
目标目录:
img
在上面的代码中是将保存文件的路径写死的了,但是,在实际开发到上线的过程当中,是涉及到至少三个环境的(开发,测试,生产),所以,保存的文件路径并不会写死,而是将保存文件的路径放在配置文件当中,然后读取配置环境中的保存图片路径。

还要注意, 一次上传文件大小默认是1MB,一次请求上传文件大小默认是10MB,可以在配置文件中进行修改。

# 设置一次上传文件大小(默认是1MB)
spring.servlet.multipart.max-file-size=100MB
# 设置一次请求上传文件大小(默认是10MB)
spring.servlet.multipart.max-request-size=100MB

这里我们来实现一个小案例,就是实现一下上传头像的功能,那这个功能的实现有如下过程:

  1. 配置保存的路径,并获取
  2. 设置不会重名的图片名称(UUID)
  3. 获取图片格式,得到文件的格式
  4. 将随机 UUID 与图片格式拼接得到完整的图片文件名
  5. 储存图片

对于不重名文件名的设定,我们可以使用 UUID,UUID 可以自动生成一个唯一的标识序列,简单理解就是 UUID 可以生成一个全球唯一 id,它由MAC + 随机种子 + 加密算法得出。

# 设置文件保存路径
img.path=D:\\image\\
//获取配置文件的保存路径
@Value("${img.path}")
private String path;

@RequestMapping("/upload")
public String upLoad(@RequestPart("img") MultipartFile file) throws IOException {
    // 1.生成一个唯一的 id
    String name = UUID.randomUUID().toString().replace("-", "");
    // 2. 得到源文件的后缀名, 和 id 组合成新的文件名
    name += (file.getOriginalFilename().
            substring(file.getOriginalFilename().lastIndexOf(".")));
    // 保存文件
    System.out.println(path);
    path += name;
    file.transferTo(new File(path));
    return path;
}

img

img

2.3.8. 获取Cookie

一般用户是不会传递这种参数的,基本上都是浏览器构造发过来的,Cookie 和 Session 通常配合使用在登录验证的场景下。

这里同样可以使用 Servlet 那一套 API 获取。

@RequestMapping("/servlet")
public void get(HttpServletRequest req, HttpServletResponse resp) {
    //...
}

🍂使用 Servlet 方式获取 Cookie:

@RequestMapping("/cookie")
public void getCookie(HttpServletRequest req) {
    //获取请求中全部的 ookie
    Cookie[] cookies = req.getCookies();
    for (Cookie c : cookies) {
        log.info("CookieKey : " + c.getName() + "   CookieValue : " + c.getValue());
    }
}

我们可以在浏览器随便加上一些 Cookie。

img

此时我们访问http://127.0.0.1:8080/user/cookie,来看看控制台是否有输出我们所传的 Cookie。
img
有记录,就说明我们成功获取到了 Cookie。

🍂简洁地获取Cookie,使用@CookieValue注解,所传参数为你需要获取 Cookie 的 key,使用该注解修饰一个变量,变量里面就会自动获取对应的value值。

@RequestMapping("/cookie2")
public String getCookie2(@CookieValue("zhangsan") String cookie) {
    return "zhangsan : " + cookie;
}

img
如果需要多个 Cookie 值,就写多个 CookieValue 修饰变量就行。

2.3.9. 获取Header

Header 用的比较多的就是获取用户的浏览器的一些基本信息了。

🍂使用 Servlet 获取 Header

@RequestMapping("/getua")
public String getUA(HttpServletRequest req) {
    return "用户设备信息User-Agent : " + req.getHeader("User-Agent");
}

img
🍂更简单地获取 Header,使用 @RequestHeader 注解

和前面使用注解 @CookieValue 用法类似,也是设置一个 key 来获取对应的 value。

@RequestMapping("/getua2")
public String getUA2(@RequestHeader("User-Agent") String ua) {
    return "用户设备信息User-Agent : " + ua;
}

img

2.3.10. 存储和获取Session

在登录逻辑中,我们需要存储 Session 对象,这一步存储操作,SpringMVC 与 Servlet 操作是一样的,获取方式则有两种方式。

🍂存储Session对象:

@RequestMapping("/setsession")
public boolean setSession(HttpServletRequest req) {
    boolean result = false;
    //1. 获取Session
    HttpSession session = req.getSession(true);
    //2. 设置Session里面的内容
    session.setAttribute("sunli", "sl1213456");
    result = true;
    return result;
}

访问路径,当新建一个Session对象后,后端会返回一个 Cookie 给前端,根据这个 Cookie 下次验证的时候就能自动登录,不用再次输入账号密码登录了。
img
🍂使用 Servlet 获取 Session**:**

@RequestMapping("/getsession")
public String getSession(HttpServletRequest req) {
    String result = "";
    //1.获取Session
    HttpSession session = req.getSession(false);
    //2.验证
    if (session != null && session.getAttribute("sunli") != null) {
        result = (String) session.getAttribute("sunli");
    }
    return result;
}

img
🍂更加简洁获取 Session,使用@SessionAttribute
该注解有两个属性,value表示需要获取 Session 对象里面内容的 key 值,还有一个require表示修饰的参数是否必须,一般需要设置为false,如果设置成true,没有获取到对应的value就会返回一个400的页面。

@RequestMapping("/getsession2")
public String getSession2(@SessionAttribute(value = "sunli", required = false) String session) {
    return session;
}

img

2.4. 返回数据

2.4.1. 返回普通的text文本/静态页面

SpringMVC/SpringBoot 默认返回的是视图(xxx.html),这是历史原因了,在方法中返回的数据默认是一个静态页面,如果没有找到这个静态页面,就会显示404。

@Controller
public class TestController {

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

页面访问结果:

img
我们再简单写一个静态页面,放入static目录,来验证一下是否能够获取到。
img

访问页面结果:

img

而如果想要返回一个 text 文本数据,则需要使用注解@ResponseBody修饰对应的方法或者修饰类才能实现。

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

img

@ResponseBody既可以修饰类,也可以修饰方法;修饰类时,类中所有方法都会返回一个非静态页面数据;修饰方法时,只有被修饰的方法返回的是一个非静态页面的数据;返回的值如果是字符会就转换为 text/html,如果返回的是对象会转换成 application/json 返回给前端。

组合注解:@RestController = @Controller + @ResponseBody

🍂小案例,实现一个加法计数器。

前端页面:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>calc</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>

后端处理代码,返回计算结果:

package com.example.demo.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

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

前端输入数据:
img
后端返回结果:
img

2.4.2. 返回JSON对象

要将指定数据构造成 JSON 格式返回,直接返回一个HashMap<String, Object>对象即可,SpringMVC会自动处理成 JSON 对象。

@RequestMapping("/getjson")
public HashMap<String, String> method_8() {
    HashMap<String, String> map = new HashMap<>();
    map.put("Java", "Java Value");
    map.put("MySQL", "MySQL Value");
    map.put("Redis", "Redis Value");
    return map;
}

img

🍂小案例,实现登录功能。

前端代码如下,实现的功能大致是发送含有账号与密码参数的请求,等待后端验证是否登录成功,给出简单的提示。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <script src="https://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
  <title>login</title>
  <script>
    function mysub() {
      let username = jQuery("#username").val();
      let password = jQuery("#password").val();
      jQuery.getJSON("/login",
            {
              "username":username,
              "password":password
            },
            function (result) {
              if(result.succ==200){
                alert("返回结果:"+result.msg);
              }else{
                alert("操作失败,请重试。");
              }
            });
    }
  </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>

在后端,我们首先需要接收账号与密码参数,然后对这些参数进行确认,为了方便起见,我们将账号与密码写死,即账号是zhangsan密码是123才能登录成功。

我们返回一个 json 格式的数据给前端,里面包含是否登录成功msg,状态码succ,将这两种参数以键值对的形式储存到哈希表中返回即可。

package com.example.demo.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;

@RestController
public class LoginController {
    @RequestMapping(value = "/login")
    public HashMap<String, Object> login(String username, String password){
        HashMap<String, Object> res = new HashMap<>();
        int succ = 200;
        if(username != null && password != null &&
                username.equals("zhangsan") && password.equals("123")){
            res.put("msg","登录成功");
        }else{
            res.put("msg","登录失败");
        }
        res.put("succ",succ);
        return res;
    }
}

实现效果:

img

2.4.3. 实现请求转发与重定向

return 不但可以返回一个视图,还可以实现跳转,跳转的方式分别为两种:

  1. forward:请求转发
  2. redirect:请求重定向

🎯请求转发是服务器端的行为,不管几次转发都是只发生服务器端,经过多次转发拿到数据后发送给浏览器。

请求转发实现方式1:

@RequestMapping("/fw")
    public String myForward() {
        //转发 html 静态页面
        return "forward:/hello.html";
    }

这种方式其实forward:/是可以省略的,因为我们知道默认情况下,返回的就是一个静态页面。

img

转发是发生在服务器内,所以,浏览器中的路由地址自始至终是不会发生改变的
请求转发实现方式2:

@RequestMapping("/fw2")
public void myForward2(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    req.getRequestDispatcher("hello.html").forward(req, resp);
}

效果是一样的:
img

🎯请求重定向其实是多次客户端和浏览器的交互,是浏览器和服务器共同的行为,浏览器发送请求后,服务端只是发送一个重定向响应,告诉浏览器要继续访问哪个 URL,浏览器收到服务器的重定向响应后,就会去访问目标地址。

请求重定向的实现方式1: 与请求转发类似,只不过将forward改为redirect

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

效果图:
rd路径跳转到hello.html页面了,重定向浏览器中的路由地址是会发生改变的。

img

请求重定向的实现方式2:

@RequestMapping("/rd2")
public void myRedirect2(HttpServletResponse resp) throws IOException {
    resp.sendRedirect("hello.html");
}

效果和上面一样的,就不添效果图了。

🍂请求转发(forward)与请求重定向(redirect)之间的区别:

  • 定义不同:请求转发发生在服务端程序内部,当服务器端收到一个客户端的请求之后,会先将请求,转发给目标地址,再将目标地址返回的结果转发给客户端;请求重定向指的是服务器端接收到客户端的请求之后,会给客户端返回了一个临时响应头,这个临时响应头中记录了客户端需要再次发送请求(重定向)的 URL 地址,客户端再收到了地址之后,会将请求发送到新的地址上。
  • 请求方不同:请求转发是服务器端的行为,是服务器提出请求去获取资源,而请求重定向是客户端的行为,服务器只是告诉客户端去哪里拿资源,实际上是客户端提出请求去获取资源。
  • 数据共享不同,请求转发是服务器端实现的,所以整个执行流程中,客户端(浏览器)只需要发送一次请求,因此整个交互过程中使用的都是同一个 Request 请求对象和一个 Response 响应对象,所以整个请求过程中,请求和返回的数据是共享的;而请求重定向客户端发送两次完全不同的请求,所以两次请求中的数据是不同的,是不共享的。
  • 最终URL地址不同:请求转发是服务器端代为请求,再将结果返回给客户端的,所以整个请求的过程中 URL 地址是不变的;而请求重定向是服务器端告诉客户端去另外一个地方,于是客户端会再次发送一个请求,因此客户端最终访问的 URL 会发生变化,不是最初的那个URL。
  • 代码实现是不同的,写法上类似,但还是有区别,看上面的代码。
  • 77
    点赞
  • 75
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 74
    评论
1.0.5 从web项目迁移成maven项目 1.0.6 增加菜单框架ext实现,类路径调整 1.0.7 增加http工具类,demo例子 1.0.8 socket工具类,权限组件,菜单组件,jdbc分页支持多种数据库,ant路径工具类,增加jquery easyUI 1.0.9 版本管理,服务根路径工具类,文件上传工具类 1.0.10 集成ueditor在线编辑器 1.0.11 地址联动 1.0.12 Excel工具类 Word工具类 Java NIO实现socket工具类 分布式session jdk升级到1.7 嵌入式redis服务(只支持linux) 1.0.13 修改默认的beanName生成策略,controller参数扩展 1.0.14 分布式session使用zookeeper 1.0.15 zookeeper工具类优化 增加工具类 1.0.16 页面html标志修改 httpclient中文支持 工具类增强(zip,reflect,thread) 1.0.17 ftp服务端和客户端工具类,配置文件maven和web项目路径统一 1.1.0 soapui工具类(web版本) properties等工具类 1.1.1 工具类数据校验 jsp自定义标签 Spring自定义注解 默认requestMapping 1.1.2 代码生成器 1.1.3 首页修改 dateformat.js 时间参数转换 SpringMVC配置文件集中 快递参数接口 1.1.4 des加解密字符串和文件 1.1.5 redis 加锁,redis升级成2.8.2 freemarker工具类 1.1.6 spring websocket 实现在线聊天 maven升级jdk1.8 jetty9.2.4 web升级jdk1.7 tomcat7 1.1.7(maven only) 包名修改 从此不再支持web版本,只支持maven版本 1.1.8 jquery 图片预览插件 图片滚动显示插件 1.1.9 jquery实现鼠标在按钮上显示窗口,离开窗口和按钮时消失 1.1.10 rabbitMQ集成 视频截图 图片缩略图旋转 集成Mybatis 使用数据库连接池druid dubbo使用
# demoWeb 一个基于SpringMVCweb框架 1.0.5 从web项目迁移成maven项目 1.0.6 增加菜单框架ext实现,类路径调整 1.0.7 增加http工具类,demo例子 1.0.8 socket工具类,权限组件,菜单组件,jdbc分页支持多种数据库,ant路径工具类,增加jquery easyUI 1.0.9 版本管理,服务根路径工具类,文件上传工具类 1.0.10 集成ueditor在线编辑器 1.0.11 地址联动 1.0.12 Excel工具类 Word工具类 Java NIO实现socket工具类 分布式session jdk升级到1.7 嵌入式redis服务(只支持linux) 1.0.13 修改默认的beanName生成策略,controller参数扩展 1.0.14 分布式session使用zookeeper 1.0.15 zookeeper工具类优化 增加工具类 1.0.16 页面html标志修改 httpclient中文支持 工具类增强(zip,reflect,thread) 1.0.17 ftp服务端和客户端工具类,配置文件maven和web项目路径统一 1.1.0 soapui工具类(web版本) properties等工具类 1.1.1 工具类数据校验 jsp自定义标签 Spring自定义注解 默认requestMapping 1.1.2 代码生成器 1.1.3 首页修改 dateformat.js 时间参数转换 SpringMVC配置文件集中 快递参数接口 1.1.4 des加解密字符串和文件 1.1.5 redis 加锁,redis升级成2.8.2 freemarker工具类 1.1.6 spring websocket 实现在线聊天 maven升级jdk1.8 jetty9.2.4 web升级jdk1.7 tomcat7 1.1.7(maven only) 包名修改 从此不再支持web版本,只支持maven版本 1.1.8 jquery 图片预览插件 图片滚动显示插件 1.1.9 jquery实现鼠标在按钮上显示窗口,离开窗口和按钮时消失 1.1.10 rabbitMQ集成 视频截图 图片缩略图旋转 集成Mybatis 使用数据库连接池druid dubbo使用 1.1.11 集成Spring Cache,FastJson Spring Cache增加redis缓存实现 Mybatis使用二级缓存,增加redis实现 增加reactJs 增加Mybatis插件pageHelper,Mapper 1.1.12 使用draft富文本编辑器 增加ant design 代码生成器功能增强
# demoWeb 一个基于SpringMVCweb框架 1.0.5 从web项目迁移成maven项目 1.0.6 增加菜单框架ext实现,类路径调整 1.0.7 增加http工具类,demo例子 1.0.8 socket工具类,权限组件,菜单组件,jdbc分页支持多种数据库,ant路径工具类,增加jquery easyUI 1.0.9 版本管理,服务根路径工具类,文件上传工具类 1.0.10 集成ueditor在线编辑器 1.0.11 地址联动 1.0.12 Excel工具类 Word工具类 Java NIO实现socket工具类 分布式session jdk升级到1.7 嵌入式redis服务(只支持linux) 1.0.13 修改默认的beanName生成策略,controller参数扩展 1.0.14 分布式session使用zookeeper 1.0.15 zookeeper工具类优化 增加工具类 1.0.16 页面html标志修改 httpclient中文支持 工具类增强(zip,reflect,thread) 1.0.17 ftp服务端和客户端工具类,配置文件maven和web项目路径统一 1.1.0 soapui工具类(web版本) properties等工具类 1.1.1 工具类数据校验 jsp自定义标签 Spring自定义注解 默认requestMapping 1.1.2 代码生成器 1.1.3 首页修改 dateformat.js 时间参数转换 SpringMVC配置文件集中 快递参数接口 1.1.4 des加解密字符串和文件 1.1.5 redis 加锁,redis升级成2.8.2 freemarker工具类 1.1.6 spring websocket 实现在线聊天 maven升级jdk1.8 jetty9.2.4 web升级jdk1.7 tomcat7 1.1.7(maven only) 包名修改 从此不再支持web版本,只支持maven版本 1.1.8 jquery 图片预览插件 图片滚动显示插件 1.1.9 jquery实现鼠标在按钮上显示窗口,离开窗口和按钮时消失 1.1.10 rabbitMQ集成 视频截图 图片缩略图旋转 集成Mybatis 使用数据库连接池druid dubbo使用 1.1.11 集成Spring Cache,FastJson Spring Cache增加redis缓存实现 Mybatis使用二级缓存,增加redis实现 增加reactJs 增加Mybatis插件pageHelper,Mapper 1.1.12 使用draft富文本编辑器 增加ant design 代码生成器功能增强
Spring MVC是一个基于JavaWeb应用框架,它是Spring框架的一部分,用于开发和管理Web应用程序。而MVC(Model-View-Controller)是一种设计模式,用于将应用程序分为三个主要部分:数据模型(Model)、视图层(View)和控制器(Controller)。 在Spring MVC中,MVC设计模式应用得非常彻底。它将应用程序的不同功能模块进行了解耦,使得开发者可以更好地组织和管理代码。具体来说,Spring MVC框架提供了以下核心组件: 1. 控制器(Controller):负责处理用户请求并调度其他组件来处理请求。它接收用户输入并根据输入选择合适的处理逻辑。 2. 视图(View):负责展示数据给用户。通常使用HTML或JSP等模板技术来生成动态页面。 3. 模型(Model):代表应用程序的数据和业务逻辑。它与数据库交互获取数据,并将数据传递给控制器和视图。 4. 处理器映射器(Handler Mapping):根据请求的URL和其他条件,将请求映射到相应的控制器。 5. 视图解析器(View Resolver):根据控制器返回的视图名称,解析出真正的视图对象。 6. 数据绑定和验证器(Data Binding & Validator):将请求参数绑定到方法参数或模型对象,并进行数据验证。 通过将应用程序的不同部分分离,Spring MVC使得开发者可以更加灵活地开发和调试Web应用程序。它提供了各种便利的功能,如请求映射、数据绑定、拦截器、异常处理等,帮助开发者更高效地构建可扩展和易于维护的Web应用程序

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 74
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

韵秋梧桐

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值