1. 为啥要学 SpringMVC?
1.1 SpringMVC 简介
在学习 SpringMVC 之前我们先看看在使用 Servlet 的时候我们是如何处理用户请求的:
- 配置web.xml
<?xml version="1.0" encoding="UTF-8"?><web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" version="4.0"> <!--将 Servlet接口实现类交给Tomcat管理--> <servlet> <servlet-name>userServlet</servlet-name> <!--Servlet接口实现类名称--> <servlet-class>com.xxl.controller.UserServlet</servlet-class><!--声明servlet接口实现类类路径--> </servlet> <servlet-mapping> <servlet-name>userServlet</servlet-name> <url-pattern>/user</url-pattern> <!--设置Servlet类的请求路径,必须以 / 开头--> </servlet-mapping></web-app>- 继承 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 请求"); }}- 获取请求参数
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.7 创建 jsp 页面
2.10 配置 tomcat,启动项目测试
6. 全局异常处理
在开发过程中我们会遇到各种各样的异常,我们会有两种处理方式:
- try-catch 捕获
- throws 抛出异常
但是用户不希望看到一堆异常信息:
即便是程序出错了,他们也希望看到一些看得懂的错误信息,例如:
{ code: 500, message: '该商品信息不存在,请联系管理员'}所以我们需要搞一个全局异常处理器先捕获这些错误信息,然后返回给用户统一的结果信息。
- 创建全局异常处理器
@RestControllerAdvicepublic class GlobalExceptionHandler { //自定义异常处理器 @ExceptionHandler(CustomException.class) public Result CustomExceptionHandler(Exception e) { return Result.fail(500,e.getMessage()); }}@RestControllerAdvice:表示这个类是全局异常处理器,返回的格式是 json 格式。
@ExceptionHandler:捕获的异常类型
- 创建自定义异常
public class CustomException extends RuntimeException{ public CustomException(String message) { super(message); }}因为大部分异常是运行时异常,所以这里自定义的异常继承了运行时异常。
- 封装返回的统一结果类
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")@ResponseBodypublic Result toHello() { throw new CustomException("卧槽!!出错了");}SpringMVC 中的拦截器主要是用来拦截用户的请求,并进行相关的处理。
实现拦截器:
- 创建拦截器
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 { }}- 配置拦截器
<!-- 配置拦截器 --><mvc:interceptors> <mvc:interceptor> <!--拦截所有请求--> <mvc:mapping path="/**"/> <!--排除请求--> <mvc:exclude-mapping path="/user/login"/> <bean class="com.zhifou.interceptor.MyInterceptor"></bean> </mvc:interceptor></mvc:interceptors>测试:
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
