百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术教程 > 正文

最全的SpringMVC教程,终于让我找到了

suiw9 2025-02-19 13:53 17 浏览 0 评论

1. 为啥要学 SpringMVC?

1.1 SpringMVC 简介

在学习 SpringMVC 之前我们先看看在使用 Servlet 的时候我们是如何处理用户请求的:

  1. 配置web.xml



    
    
        userServlet 
        com.xxl.controller.UserServlet
    
    
        userServlet
        /user  
    
  1. 继承 HttpServlet,实现 doGet 和 doPost 方法
public class UserServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
       // 这里用来处理用户的 get 请求
       System.out.println("哈哈哈哈哈哈我头上有注解");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 这里用来处理用户的 post 请求
        System.out.println("接收到用户的 post 请求");
    }
}
  1. 获取请求参数

String name = request.getParameter("name");

String age = request.getParameter("age");
....

一顿操作下来,我们发现用 Servlet 处理用户的请求也太麻烦了吧。

每个 Servlet 都要继承 HttpServlet、重写两个方法,我们需要写一堆 getParameter() 方法来获取请求参数,而且还要做数据类型的转换。

那有没有一个别人封装好的工具或者是框架让我少写这些重复性的代码呢?

SpringMVC闪亮登场。

SpringMVC 是一种轻量级的、基于 MVC 的 Web 层应用框架,它属于 Spring 框架的一部分。SpringMVC 说白了就是对 Servlet 进行了封装,方便大家使用。

1.2 SpringMVC 优点

  • 天生与 Spring 集成
  • 支持 Restful 风格开发
  • 便于与其他视图技术集成,例如 theamleaf、freemarker等
  • 强大的异常处理
  • 对静态资源的支持

总之就是好用!


2. HelloWorld

这里我们先来开发一个基于 SpringMVC 的程序,感受一下 SpringMVC 的迷人特性。

  • 开发工具:IDEA
  • 构建工具:Maven

2.1 新建基于 Maven 的 web 项目


2.2 加入依赖



    javax.servlet
    javax.servlet-api
    4.0.1



    org.springframework
    spring-webmvc
    5.2.8.RELEASE



    junit
    junit
    4.11
    test

2.3 创建中央调度器

DispatcherServlet 是 SpringMVC 的中央调度器,它主要负责加载 SpringMVC 的配置。

从它的名字来看,他也属于一个 Servlet,遵守 Servlet 规范。所以我们需要在 web.xml 中创建 DispatcherServlet。

web.xml



    
    
        SpringMVC
        org.springframework.web.servlet.DispatcherServlet
        
            contextConfigLocation
            classpath:springmvc.xml
        
        1
    
    
        SpringMVC
        /
    


2.4 创建 SpringMVC 的配置文件

这里我们在 src/resources 资源目录下创建 SpringMVC的配置文件 springmvc.xml,该文件名字可以任意命名。

springmvc.xml:





2.5 创建处理请求的处理器

TestController:

/**
* @Desc: 处理器
* @Author: 知否技术
* @date: 下午7:39 2022/4/29
*/
@Controller
public class TestController {
  @RequestMapping("/hello")
  public ModelAndView sayHello() {
      ModelAndView mv = new ModelAndView();
      mv.addObject("msg", "你好啊,李银河,我是王小波。");
      mv.setViewName("/hello.jsp");
      return mv;
  }
}

2.6 声明组件扫描器

我们在 springmvc.xml 中注册组件扫描器,


base-package="com.zhifou">


2.7 创建 jsp 页面


2.8 配置视图解析器

我们需要在 springmvc.xml 中配置请求文件的路径和文件后缀。



  
  


2.9 修改处理器请求文件路径

因为我们指定了请求文件的后缀是 .jsp,所以这里可以省略。


2.10 配置 tomcat,启动项目测试






3. 请求

3.1 @RequestMapping

@RequestMapping 注解用来指定处理哪些 URL 请求。

3.1.1 注解常用属性

  1. value

value 用来表示请求的 url,可以省略不写

@RequestMapping(value = "/hello")

简写

@RequestMapping("/hello")
  1. method

method 用来表示请求方式,不写的话默认是 GET 请求。常用的请求方式:

POST、GET、PUT、DELETE

如果使用 method 属性,不能省略 value 属性。

@RequestMapping(value = "/hello",method = RequestMethod.GET)
  public ModelAndView sayHello() {
      ModelAndView mv = new ModelAndView();
      mv.addObject("message", "你好啊,李银河,我是王小波。");
      mv.setViewName("/hello");
      return mv;
}

3.1.2 标记位置

  1. 标记在类上面

一个系统包含很多模块,例如用户、商品、订单等模块。

我们需要为不同的模块定义不同的类,然后在类上面添加 @RequestMapping 注解,表示这个模块下面统一的请求路径:例如:

// 用户操作控制器
@Controller
@RequestMapping("/user")
public class UserController {

}
// 订单操作控制器
@Controller
@RequestMapping("/order")
public class OrderController {

}
...
  1. 标记在方法上面

每个模块都有很多方法,例如增删改查等。所以我们一般会在相应的方法上面添加 @RequestMapping 注解,表示请求这个模块下的某个方法,例如:

@Controller
@RequestMapping("/user")
public class UserController {
 @RequestMapping("/list")
    public Object list() {
      return null;
    }
    @RequestMapping(value = "/add",method = RequestMethod.POST)
    public Object add() {
        return null;
    }
    @RequestMapping(value = "/update",method = RequestMethod.POST)
    public Object update() {
        return null;
    }
    @RequestMapping(value = "/delete",method = RequestMethod.DELETE)
    public Object delete() {
        return null;
    }
}

所以当我们获取用户列表信息时,我们请求的后台接口的 url 就是:

ip地址:端口号/项目名/uset/list
//例如:
localhost:8080/ems/user/list

3.1.3 @RequestMapping 的缩写注解

方法上关于不同请求方式的注解都比较长,例如:

 @RequestMapping(value = "/add",method = RequestMethod.POST)

SpringMVC 为我们提供了简化写法:

GET请求:

@GetMapping("/list")

POST 请求:

@PostMapping("/login")

DELETE 请求:

@DeleteMapping("/delete/{id}")

PUT 请求

@PutMapping("/update")

3.2 接收请求参数

3.2.1 接收多个参数

@PostMapping("/login") public Result login(String username,String password) { User user = userService.login(username, password); return Result.success(user); }

3.2.2 实体类作为参数

Spring MVC 会按请求参数名和 POJO 属性名进行自动匹配,自动为该对象填充属性值。

@PostMapping("/login") public Result login(User user){ User user = userService.login(user.getUsername(), user.getPassword); return Result.success(user); }

3.2.3 @RequestParam 注解

使用 @RequestParam 可以把请求参数传递给请求方法。

属性:

  1. value:参数名
  2. required:是否必须。默认为 true, 表示请求参数中必须包含对应的参数,若不存在,将抛出异常
  3. defaultValue: 默认值,当没有传递参数时使用该值
@PostMapping("/login")
public Result login(@RequestParam String username, @RequestParam String password) {
    User user = userService.login(username, password);
    return Result.success(user);
}

3.2.4 @PathVariable 注解

通过 @PathVariable 可以将 URL 中占位符参数绑定到控制器处理方法的入参中。

URL 中的 {xxx} 占位符可以通过 @PathVariable("xxx")绑定到操作方法的入参中。

@DeleteMapping(value = "/delete/{id}")
public Result delete(@PathVariable("id") int id) {
    userService.remove(id);
    return Result.success();
}

3.3 解决中文乱码

请求参数如果含有中文,会出现中文乱码问题。我们可以通过在 web.xml 中配置字符过滤器来解决中文乱码问题。


   encodingFilter
   org.springframework.web.filter.CharacterEncodingFilter
   
            encoding
            UTF-8
   
   
            forceEncoding
            true
   


   encodingFilter
   /*

注:filter 标签要在 servlet 标签之上

4. 响应

SpringMVC 提供了以下几种方式处理响应数据。

4.1 返回 String

  1. SpringMVC 的视图解析器将返回的字符串转换为视图(页面)。
@GetMapping("/hello")
public String toHello() {
    return "/hello";
}
  1. 重定向:

使用 redirect 关键字可以重定向到其他页面。

@GetMapping("/hello")
public String toHello() {
    return "redirect:/hello";
}

4.2 返回 ModelAndView

控制器在处理完用户的请求之后,如果既想跳转页面,又想传递数据,可以使用 ModelAndView 对象。

@RequestMapping(value = "/hello",method = RequestMethod.GET)
  public ModelAndView sayHello() {
      ModelAndView mv = new ModelAndView();
      mv.addObject("message", "你好啊,李银河,我是王小波。");
      mv.setViewName("/hello");
      return mv;
}

4.3 返回 Model

Mode 对象也可以在跳转页面的时候传递数据。

@GetMapping("/print")
public String print(Model model) {
    model.addAttribute("msg", "祝大家五一快乐!");
    return "/hello";
}

4.4 返回 json

  1. 控制器的方法也可以返回 Object 对象,但返回的对象不是作为视图出现的,而是作为页面上显示的数据。

返回对象,需要使用 @ResponseBody 注解将对象转换为 json 格式的数据响应给浏览器。

@GetMapping(value = "/print", produces = "application/json;charset=utf8")
@ResponseBody
public Object print() {
    User user = new User(11111L, "张无忌", 12);
    String json = JSONUtil.toJsonStr(user);
    return json;
}



如果遇到中文乱码的问题,我们可以在 @GetMapping 注解里面设置 produces 属性。

  1. @RestController 注解

@RestController 注解是 @Controller 和 @ResponseBody 注解的组合注解,表示这个控制器中所有的方法全都返回 json 格式的数据。

4.5 返回 void

有时候我们不需要跳转页面,也不需要转发数据,我们只是希望浏览器能够渲染数据(例如后台向前台输出验证码)。这时候可以使用 HttpServletResponse 向浏览器输出数据。

@GetMapping("/print")
public void print(HttpServletResponse response) throws IOException {
    /*解决响应数据中文乱码问题*/
    response.setContentType("text/html;charset=utf8");
    PrintWriter writer = response.getWriter();
    writer.print("祝大家五一快乐");
    writer.flush();
    writer.close();
}

5. 访问静态

我们在 web.xml 中配置 url-pattern 为 /,当我们请求项目的静态资源的时候,SpringMVC 的中央调度器会先根据处理器映射器寻找相应的处理器,结果没找到,所以请求静态资源会报 404。

我们可以使用 mvc:resources 标签来解决无法访问静态资源的问题。

但是 DispatcherServlet 的映射路径为 /,而 Tomcat 默认的 Servlet 的映射路径也为/,所以 DispatcherServlet 会覆盖 Tomcat 中默认的 Servlet,去处理除 jsp 之外的所有资源,导致静态资源无法被访问。

所以这里还需要结合另外一个标签使用:



这里我们测试访问项目中的照片:

@GetMapping("/hello")
public String toHello() {
    return "/hello";
}



6. 全局异常处理

在开发过程中我们会遇到各种各样的异常,我们会有两种处理方式:

  1. try-catch 捕获
  2. throws 抛出异常

但是用户不希望看到一堆异常信息:

即便是程序出错了,他们也希望看到一些看得懂的错误信息,例如:

{
  code: 500,
  message: '该商品信息不存在,请联系管理员'
}

所以我们需要搞一个全局异常处理器先捕获这些错误信息,然后返回给用户统一的结果信息。

  1. 创建全局异常处理器
@RestControllerAdvice
public class GlobalExceptionHandler {
    //自定义异常处理器
    @ExceptionHandler(CustomException.class)
    public Result CustomExceptionHandler(Exception e) {
        
        return Result.fail(500,e.getMessage());
    }
}

@RestControllerAdvice:表示这个类是全局异常处理器,返回的格式是 json 格式。

@ExceptionHandler:捕获的异常类型

  1. 创建自定义异常
/**
 * @Desc: 自定义异常
 * @Author: 知否技术
 * @date: 下午8:05 2022/5/3
 */
public class CustomException  extends  RuntimeException{

    public CustomException(String message) {
        super(message);
    }
}

因为大部分异常是运行时异常,所以这里自定义的异常继承了运行时异常。

  1. 封装返回的统一结果类
/**
 * @Desc: 统一结果类
 * @Author: 知否技术
 * @date: 下午9:02 2022/5/3
 */
public class Result implements Serializable {

    private int code;

    private String message;

    private Object data;

    private Result(String message) {
        this.code = 200;
        this.message = message;
    }

    private Result(String message, Object data) {
        this.code = 200;
        this.message = message;
        this.data = data;
    }

    private Result(int code, String message) {
        this.code = code;
        this.message = message;
    }

    public static Result success(String message) {
        return new Result(message);
    }

    public static Result success(String message, Object data) {
        return new Result(message, data);
    }

    public static Result fail(int code, String message) {
        return new Result(code, message);
    }

    public int getCode() {
        return code;
    }

    public void setCode(int code) {
        this.code = code;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public Object getData() {
        return data;
    }

    public void setData(Object data) {
        this.data = data;
    }
}

4.测试

@GetMapping("/hello")
@ResponseBody
public Result toHello() {
    throw new CustomException("卧槽!!出错了");
}

SpringMVC 中的拦截器主要是用来拦截用户的请求,并进行相关的处理。

实现拦截器:

  1. 创建拦截器
/**
 * @Desc:
 * @Author: 知否技术
 * @date: 下午2:09 2022/5/3
 */
public class MyInterceptor implements HandlerInterceptor {

    // 在处理器中方法执行之前执行
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
       
        return false;
    }
    // 在处理器中方法执行之后执行
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

    }
}
  1. 配置拦截器


    
        
        
        
        
        
    

测试:


8. SpringMVC 执行流程


1.Tomcat 服务器启动的时候会立即创建 DispatcherServlet(中央调度器),同时会创建 SpringMVC 容器。

2.SpringMVC 容器初始化的时候会先根据配置文件中的组件扫描器先扫描一下哪些类上面有 @Controller 注解,并将这些类作为处理器类。

然后通过 @RequestMapping 注解生成对应的映射关系。这些对应关系由处理器映射器管理。

3.当收到用户的请求,中央调度器将请求转发给处理器映射器。

4.处理器映射器根据用户请求的 URL 从映射关系中找到处理该请求的处理器,然后封装成处理器执行链返回给中央处理器。

5.中央调度器根据处理器执行链中的处理器,找到能够执行该处理器的处理器适配器,处理器适配器调用执行处理器。

6.处理器将处理结果及要跳转的视图封装到 ModelAndView 中,并将其返回给处理器适配器。

7.处理器适配器直接将结果返回给中央调度器,中央调度器调用视图解析器,将 ModelAndView 中的视图名称封装为视图对象。

8.视图解析器将封装了的视图对象返回给中央调度器,中央调度器调用视图对象,填充数据,生成响应对象。

9.中央调度器将结果响应给浏览器。

原文链接:
https://juejin.cn/post/7093670296888016933

相关推荐

俄罗斯的 HTTPS 也要被废了?(俄罗斯网站关闭)

发布该推文的ScottHelme是一名黑客,SecurityHeaders和ReportUri的创始人、Pluralsight作者、BBC常驻黑客。他表示,CAs现在似乎正在停止为俄罗斯域名颁发...

如何强制所有流量使用 HTTPS一网上用户

如何强制所有流量使用HTTPS一网上用户使用.htaccess强制流量到https的最常见方法可能是使用.htaccess重定向请求。.htaccess是一个简单的文本文件,简称为“.h...

https和http的区别(https和http有何区别)

“HTTPS和HTTP都是数据传输的应用层协议,区别在于HTTPS比HTTP安全”。区别在哪里,我们接着往下看:...

快码住!带你十分钟搞懂HTTP与HTTPS协议及请求的区别

什么是协议?网络协议是计算机之间为了实现网络通信从而达成的一种“约定”或“规则”,正是因为这个“规则”的存在,不同厂商的生产设备、及不同操作系统组成的计算机之间,才可以实现通信。简单来说,计算机与网络...

简述HTTPS工作原理(简述https原理,以及与http的区别)

https是在http协议的基础上加了一层SSL(由网景公司开发),加密由ssl实现,它的目的是为用户提供对网站服务器的身份认证(需要CA),以至于保护交换数据的隐私和完整性,原理如图示。1、客户端发...

21、HTTPS 有几次握手和挥手?HTTPS 的原理什么是(高薪 常问)

HTTPS是3次握手和4次挥手,和HTTP是一样的。HTTPS的原理...

一次安全可靠的通信——HTTPS原理

为什么HTTPS协议就比HTTP安全呢?一次安全可靠的通信应该包含什么东西呢,这篇文章我会尝试讲清楚这些细节。Alice与Bob的通信...

为什么有的网站没有使用https(为什么有的网站点不开)

有的网站没有使用HTTPS的原因可能涉及多个方面,以下是.com、.top域名的一些见解:服务器性能限制:HTTPS使用公钥加密和私钥解密技术,这要求服务器具备足够的计算能力来处理加解密操作。如果服务...

HTTPS是什么?加密原理和证书。SSL/TLS握手过程

秘钥的产生过程非对称加密...

图解HTTPS「转」(图解http 完整版 彩色版 pdf)

我们都知道HTTPS能够加密信息,以免敏感信息被第三方获取。所以很多银行网站或电子邮箱等等安全级别较高的服务都会采用HTTPS协议。...

HTTP 和 HTTPS 有何不同?一文带你全面了解

随着互联网时代的高速发展,Web服务器和客户端之间的安全通信需求也越来越高。HTTP和HTTPS是两种广泛使用的Web通信协议。本文将介绍HTTP和HTTPS的区别,并探讨为什么HTTPS已成为We...

HTTP与HTTPS的区别,详细介绍(http与https有什么区别)

HTTP与HTTPS介绍超文本传输协议HTTP协议被用于在Web浏览器和网站服务器之间传递信息,HTTP协议以明文方式发送内容,不提供任何方式的数据加密,如果攻击者截取了Web浏览器和网站服务器之间的...

一文让你轻松掌握 HTTPS(https详解)

一文让你轻松掌握HTTPS原文作者:UC国际研发泽原写在最前:欢迎你来到“UC国际技术”公众号,我们将为大家提供与客户端、服务端、算法、测试、数据、前端等相关的高质量技术文章,不限于原创与翻译。...

如何在Spring Boot应用程序上启用HTTPS?

HTTPS是HTTP的安全版本,旨在提供传输层安全性(TLS)[安全套接字层(SSL)的后继产品],这是地址栏中的挂锁图标,用于在Web服务器和浏览器之间建立加密连接。HTTPS加密每个数据包以安全方...

一文彻底搞明白Http以及Https(http0)

早期以信息发布为主的Web1.0时代,HTTP已可以满足绝大部分需要。证书费用、服务器的计算资源都比较昂贵,作为HTTP安全扩展的HTTPS,通常只应用在登录、交易等少数环境中。但随着越来越多的重要...

取消回复欢迎 发表评论: