一文让你轻松拿捏 Spring MVC

news/2024/10/21 15:30:23/

博主介绍: ✌博主从事应用安全和大数据领域,有8年研发经验,5年面试官经验,Java技术专家✌

Java知识图谱点击链接:体系化学习Java(Java面试专题)
💕💕 感兴趣的同学可以收藏关注下不然下次找不到哟💕💕

在这里插入图片描述

文章目录

  • 1、什么是 MVC
  • 2、什么是 Spring MVC
  • 3、Spring MVC 的请求流程
  • 4、Spring MVC 的五大组件
    • 4.1、前端控制器(DispatcherServlet)
    • 4.2、处理器映射(HandlerMapping)
    • 4.3、 处理器适配器(HandlerAdapter)
    • 4.4、 视图解析器(ViewResolver)
    • 4.5、视图(View)
  • 5、Spring MVC 的代码案例

1、什么是 MVC

MVC是一种软件架构模式,它将应用程序分为三个主要组成部分:模型(Model)、视图(View)和控制器(Controller)。MVC模式的目的是将应用程序的业务逻辑与用户界面分离,以便更好地管理和维护应用程序。

模型(Model):模型是应用程序的核心组件,它包含应用程序的数据和业务逻辑。模型通常包括数据访问、数据验证和数据处理等方面的逻辑。

视图(View):视图是应用程序的用户界面,它负责显示数据和与用户交互。视图通常包括用户界面的设计、布局和样式等方面的逻辑。

控制器(Controller):控制器是应用程序的逻辑处理部分,它负责协调模型和视图之间的交互。控制器通常包括用户输入的处理、业务逻辑的处理和视图的更新等方面的逻辑。

MVC模式的好处是它可以使应用程序更易于管理和维护,因为它将应用程序分为不同的组件,使每个组件都可以独立地进行开发和测试。此外,MVC模式还可以提高应用程序的可扩展性和可重用性,因为它可以使应用程序的各个组件更加松散耦合。

在这里插入图片描述

2、什么是 Spring MVC

Spring MVC是一种基于MVC模式的Web框架,它是Spring Framework的一部分。它提供了一种简单的方式来开发Web应用程序,并且可以轻松地与其他Spring组件集成。Spring MVC框架的核心是一个前端控制器(Front Controller)Servlet,它负责将请求分派到适当的控制器(Controller)和视图(View)。

Spring MVC框架的核心组件包括以下内容:

  1. 前端控制器(Front Controller)Servlet:它是Spring MVC框架的核心,负责将请求分派到适当的控制器(Controller)和视图(View)。

  2. 控制器(Controller):它处理来自前端控制器的请求,并将请求转发给适当的服务层组件进行处理。控制器通常是一个Java类,它可以使用注解或XML配置进行配置。

  3. 视图(View):它负责呈现模型数据,并将其显示给用户。视图通常是一个JSP页面或HTML模板,它可以使用表达式语言(EL)或模板引擎进行渲染。

  4. 模型(Model):它是应用程序的业务逻辑和数据访问层。模型通常是一个Java类,它可以使用Spring的数据访问组件进行访问。

Spring MVC框架的好处是它可以帮助开发人员快速地构建Web应用程序,并且可以轻松地与其他Spring组件集成。此外,Spring MVC框架还提供了一些有用的功能,如表单处理、数据绑定、校验和国际化等。

3、Spring MVC 的请求流程

在这里插入图片描述
Spring MVC的请求流程如下:

  1. 客户端向服务器发送请求,请求被DispatcherServlet接收。

  2. DispatcherServlet根据请求的URL和HandlerMapping找到对应的处理器(Handler)。

  3. 处理器执行业务逻辑,并将处理结果封装成一个ModelAndView对象。

  4. 处理器将ModelAndView对象返回给DispatcherServlet。

  5. DispatcherServlet根据ViewResolver找到对应的视图(View)。

  6. 视图将ModelAndView中的模型数据渲染成HTML或其他格式的响应。

  7. 响应被发送回客户端,请求结束。

在请求流程中,HandlerMapping和ViewResolver是两个重要的组件。HandlerMapping负责将请求映射到具体的处理器(Handler),而ViewResolver负责将逻辑视图名称解析为具体的视图实现。这两个组件都可以根据需要进行自定义配置。

4、Spring MVC 的五大组件

Spring MVC的五大组件包括:

  1. 前端控制器(DispatcherServlet):它是Spring MVC框架的核心,负责将请求分发到不同的处理器(Handler)和视图(View)进行处理。

  2. 处理器映射(HandlerMapping):它负责将请求映射到具体的处理器(Handler),根据不同的映射规则,可以将请求映射到不同的处理器。

  3. 处理器适配器(HandlerAdapter):它负责将不同类型的处理器适配成统一的处理器接口,以便DispatcherServlet可以调用它们。

  4. 视图解析器(ViewResolver):它负责将逻辑视图名称解析为具体的视图实现,根据不同的解析规则,可以将逻辑视图名称解析为不同的视图实现。

  5. 视图(View):它负责将模型数据渲染成HTML或其他格式的响应,根据不同的视图实现,可以将模型数据渲染成不同的响应格式。

4.1、前端控制器(DispatcherServlet)

DispatcherServlet的工作原理可以通过以下代码说明:

public class DispatcherServlet extends HttpServlet {// 处理器映射器private List<HandlerMapping> handlerMappings;// 处理器适配器private List<HandlerAdapter> handlerAdapters;// 视图解析器private List<ViewResolver> viewResolvers;// 初始化方法@Overridepublic void init(ServletConfig config) throws ServletException {// 初始化处理器映射器handlerMappings = new ArrayList<>();handlerMappings.add(new BeanNameUrlHandlerMapping());// 初始化处理器适配器handlerAdapters = new ArrayList<>();handlerAdapters.add(new HttpRequestHandlerAdapter());// 初始化视图解析器viewResolvers = new ArrayList<>();viewResolvers.add(new InternalResourceViewResolver());}// 处理请求方法@Overrideprotected void service(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {// 根据请求URL和处理器映射器找到对应的处理器Object handler = getHandler(request);if (handler == null) {// 如果找不到处理器,则返回404错误response.sendError(HttpServletResponse.SC_NOT_FOUND);return;}// 根据处理器和处理器适配器执行业务逻辑HandlerAdapter handlerAdapter = getHandlerAdapter(handler);ModelAndView modelAndView = handlerAdapter.handle(request, response, handler);// 根据ModelAndView和视图解析器找到对应的视图View view = getView(modelAndView);if (view == null) {// 如果找不到视图,则返回500错误response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);return;}// 渲染视图,生成响应view.render(modelAndView.getModel(), request, response);}// 根据请求URL和处理器映射器找到对应的处理器private Object getHandler(HttpServletRequest request) {for (HandlerMapping handlerMapping : handlerMappings) {Object handler = handlerMapping.getHandler(request);if (handler != null) {return handler;}}return null;}// 根据处理器和处理器适配器执行业务逻辑private HandlerAdapter getHandlerAdapter(Object handler) {for (HandlerAdapter handlerAdapter : handlerAdapters) {if (handlerAdapter.supports(handler)) {return handlerAdapter;}}return null;}// 根据ModelAndView和视图解析器找到对应的视图private View getView(ModelAndView modelAndView) {String viewName = modelAndView.getViewName();for (ViewResolver viewResolver : viewResolvers) {View view = viewResolver.resolveViewName(viewName);if (view != null) {return view;}}return null;}
}

在上面的代码中,DispatcherServlet继承自HttpServlet,它是一个Servlet,负责处理HTTP请求。在初始化方法中,DispatcherServlet初始化了处理器映射器、处理器适配器和视图解析器等组件。在处理请求方法中,DispatcherServlet根据请求URL和处理器映射器找到对应的处理器,然后根据处理器和处理器适配器执行业务逻辑,最后根据ModelAndView和视图解析器找到对应的视图,渲染视图,生成响应。

4.2、处理器映射(HandlerMapping)

HandlerMapping的工作原理可以通过以下代码说明:

public interface HandlerMapping {Object getHandler(HttpServletRequest request);
}public class BeanNameUrlHandlerMapping implements HandlerMapping {private Map<String, Object> handlerMap = new HashMap<>();public void registerHandler(String url, Object handler) {handlerMap.put(url, handler);}@Overridepublic Object getHandler(HttpServletRequest request) {String url = request.getRequestURI();Object handler = handlerMap.get(url);return handler;}
}

在上面的代码中,HandlerMapping是一个接口,定义了获取处理器的方法。BeanNameUrlHandlerMapping是HandlerMapping的一个实现类,它通过URL和处理器的映射关系来获取处理器。

BeanNameUrlHandlerMapping维护了一个handlerMap,用于存储URL和处理器的映射关系。通过registerHandler方法,可以将一个URL和对应的处理器注册到handlerMap中。

在getHandler方法中,BeanNameUrlHandlerMapping首先通过HttpServletRequest获取请求的URL。然后从handlerMap中根据URL获取对应的处理器。如果找不到对应的处理器,则返回null。

通过这样的方式,BeanNameUrlHandlerMapping实现了根据URL获取处理器的功能。其他的HandlerMapping实现类可能会使用不同的方式来获取处理器,但都需要实现HandlerMapping接口中的getHandler方法。

4.3、 处理器适配器(HandlerAdapter)

处理器适配器(HandlerAdapter)是一个桥梁,用于将处理器(Handler)适配到处理器映射(HandlerMapping)机制中。不同类型的处理器需要不同的适配器来适配到处理器映射机制中。

以下是一个示例代码,用于说明处理器适配器的工作原理:

public interface HandlerAdapter {boolean supports(Object handler);ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;
}public class SimpleControllerHandlerAdapter implements HandlerAdapter {@Overridepublic boolean supports(Object handler) {return handler instanceof SimpleController;}@Overridepublic ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {SimpleController controller = (SimpleController) handler;return controller.handleRequest(request, response);}
}

在上面的代码中,HandlerAdapter是一个接口,定义了两个方法:supports和handle。supports方法用于判断一个处理器是否支持当前的适配器。handle方法用于执行处理器的业务逻辑,并返回ModelAndView对象。

SimpleControllerHandlerAdapter是HandlerAdapter的一个实现类,用于适配SimpleController类型的处理器。在supports方法中,SimpleControllerHandlerAdapter判断传入的处理器是否是SimpleController类型的实例。如果是,则返回true,表示当前适配器可以处理该类型的处理器。如果不是,则返回false,表示当前适配器无法处理该类型的处理器。

在handle方法中,SimpleControllerHandlerAdapter将传入的处理器强制转换为SimpleController类型,并调用其handleRequest方法来执行业务逻辑。handleRequest方法返回一个ModelAndView对象,SimpleControllerHandlerAdapter将其返回给调用者。

通过这样的方式,SimpleControllerHandlerAdapter实现了将SimpleController类型的处理器适配到处理器映射机制中的功能。其他类型的处理器适配器也可以通过实现HandlerAdapter接口来实现适配器的功能。

4.4、 视图解析器(ViewResolver)

视图解析器(ViewResolver)是将逻辑视图名(如"home")解析为实际视图(如"/WEB-INF/views/home.html")的机制。以下是一个示例代码,用于说明视图解析器的工作原理:

public interface ViewResolver {View resolveViewName(String viewName, Locale locale) throws Exception;
}public class InternalResourceViewResolver implements ViewResolver {private String prefix = "/WEB-INF/views/";private String suffix = ".html";@Overridepublic View resolveViewName(String viewName, Locale locale) throws Exception {String viewPath = prefix + viewName + suffix;InternalResourceView view = new InternalResourceView(viewPath);return view;}
}

在上面的代码中,ViewResolver是一个接口,定义了一个方法resolveViewName,用于将逻辑视图名解析为实际视图。

InternalResourceViewResolver是ViewResolver的一个实现类,用于将逻辑视图名解析为HTML视图。在InternalResourceViewResolver中,我们定义了prefix和suffix两个属性,用于指定HTML视图的路径前缀和后缀。在resolveViewName方法中,我们将逻辑视图名和前缀、后缀拼接起来,得到实际的HTML视图路径。然后创建一个InternalResourceView对象,将实际视图路径作为参数传入。最后返回这个InternalResourceView对象。

通过这样的方式,InternalResourceViewResolver实现了将逻辑视图名解析为HTML视图的功能。其他类型的视图解析器也可以通过实现ViewResolver接口来实现解析器的功能。

4.5、视图(View)

视图(View)是用户界面的一部分,用于呈现模型数据。以下是一个示例代码,用于说明视图的工作原理:

public interface View {void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response) throws Exception;
}public class HtmlView implements View {private String viewName;public HtmlView (String viewName) {this.viewName = viewName;}@Overridepublic void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response) throws Exception {request.setAttribute("model", model);request.getRequestDispatcher(viewName).forward(request, response);}
}

在上面的代码中,View是一个接口,定义了一个方法render,用于呈现模型数据。HtmlView是View的一个实现类,用于呈现JSP视图。在HtmlView中,我们定义了一个viewName属性,表示HTML视图的名称。在render方法中,我们将模型数据和request对象绑定,然后调用request.getRequestDispatcher方法获取HTML视图的请求转发器,最后将request和response对象传递给请求转发器的forward方法,将HTML视图呈现给用户。

通过这样的方式,HtmlView实现了将模型数据呈现为HTML视图的功能。其他类型的视图也可以通过实现View接口来实现视图的功能。

5、Spring MVC 的代码案例

以下是一个简单的Spring MVC代码案例,用于展示如何创建一个简单的控制器和视图,并将它们组合在一起来实现一个完整的Web应用程序。

首先,我们需要创建一个控制器类,用于处理来自客户端的HTTP请求。在这个示例中,我们将创建一个名为HelloController的控制器,它将处理来自客户端的"/hello"请求,并返回一个简单的问候语。

package com.pany.camp.spring;import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;/**** @description:  hello* @copyright: @Copyright (c) 2022 * @company: Aiocloud* @author: pany* @version: 1.0.0 * @createTime: 2023-06-12 21:55 */
@Controller
public class HelloController {@RequestMapping("/hello")public String hello(Model model) {model.addAttribute("message", "Hello, World!");return "hello";}
}

在上面的代码中,我们使用@Controller注解将HelloController类标记为Spring MVC控制器。我们还使用@RequestMapping注解将"/hello"请求映射到hello()方法。在hello()方法中,我们使用Model对象将一个名为"message"的属性添加到模型中,并将视图名称"hello"返回。

接下来,我们需要创建一个视图来呈现模型数据。在这个示例中,我们将创建一个名为hello.html的HTML视图,它将显示一个简单的问候语。


<!DOCTYPE html>
<html>
<head><title>Hello</title>
</head>
<body><h1 th:text="${message}"></h1>
</body>
</html>

在上面的代码中,我们使用Thymeleaf模板引擎的th:text属性将模型中的"message"属性绑定到页面上的 h1元素。

最后,我们需要配置Spring MVC框架以使用我们的控制器和视图。在这个示例中,我们将使用Java配置来配置Spring MVC。

package com.pany.camp.spring;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.view.InternalResourceViewResolver;/**** @description:  MVC Config* @copyright: @Copyright (c) 2022 * @company: Aiocloud* @author: pany* @version: 1.0.0 * @createTime: 2023-06-12 21:55 */
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "com.pany.camp.spring")
public class AppConfig implements WebMvcConfigurer {@Beanpublic ViewResolver viewResolver() {InternalResourceViewResolver resolver = new InternalResourceViewResolver();resolver.setPrefix("classpath:templates/");resolver.setSuffix(".html");return resolver;}
}

在上面的代码中,我们使用@Configuration注解将AppConfig类标记为Spring配置类。我们还使用@EnableWebMvc注解启用Spring MVC框架,并使用@ComponentScan注解扫描我们的控制器类。在viewResolver()方法中,我们创建了一个InternalResourceViewResolver对象,并将视图的前缀设置为"/WEB-INF/views/“,将后缀设置为”.html",以便Spring MVC可以将逻辑视图名解析为HTML视图。

现在我们已经创建了控制器、视图和配置类,我们可以将它们组合在一起来创建一个完整的Web应用程序。我们可以使用Spring Boot框架来快速创建一个可执行的Web应用程序。

@SpringBootApplication
public class Application {public static void main(String[] args) {SpringApplication.run(Application.class, args);}
}

在上面的代码中,我们使用@SpringBootApplication注解将Application类标记为Spring Boot应用程序,并在main()方法中使用SpringApplication.run()方法启动应用程序。

在这里插入图片描述

参考我的静态文件的目录结构,因为我这边设置了 context-path: /console-service,端口设置的是port: 19096,所以在浏览器中访问 http://localhost:19096/console-service/hello,应该会看到一个包含"Hello,World!"的标题的页面。

在这里插入图片描述

在这里插入图片描述

💕💕 本文由激流原创,首发于CSDN博客,博客主页 https://blog.csdn.net/qq_37967783?spm=1010.2135.3001.5421
💕💕喜欢的话记得点赞收藏啊


http://www.ppmy.cn/news/351215.html

相关文章

DPDK下X710网卡丢包

环境 - 处理器&#xff1a;Intel Xeon Gold 5122 CPU 3.60GHz 4核8线程 DPDK&#xff1a; v20.05 测试&#xff1a; 4对接口双向对打流量&#xff0c;报文长度1518字节。 发现有接口丢包&#xff0c;打印出来接口的统计信息&#xff0c;其中rte_eth_stats->imissed字段有…

DPDK X710 DDP PPPoE 实践

DPDK X710 DDP PPPoE 实践 DPDK version: 21.08 X710 firmware-version: 6.80 0x80003cc1 1.1747.0 DDP PPPoE profile version: 1.0.0.0 # lspci |grep Ethernet |grep X710 04:00.0 Ethernet controller: Intel Corporation Ethernet Controller X710 for 10GbE SFP (rev…

虚拟化部署ESXI6.7+intel x710-da4万兆网卡

为什么要部署服务器虚拟化&#xff1f; 1、减少硬件投资成本 &#xff08;1&#xff09;传统的服务器平台 传统的服务器一般做完阵列raid后&#xff0c;只安装一套操作系统&#xff0c;提供服务时&#xff0c;具有一定的局限性&#xff0c;多服务同时运行&#xff0c;有可能导…

【CMake 入门与进阶(6)】 CMakeLists.txt 部分常用变量(附使用代码)

变量也是 cmake 中的一个重头戏&#xff0c;cmake 提供了很多内置变量&#xff0c;每一个变量都有它自己的含义&#xff0c;通过这个链接地址cmake-variables(7) — CMake 3.5.2 Documentation可以查询到所有的内置变量及其相应的介绍&#xff0c;如下所示&#xff1a; 在这一份…

携手京东发力“互联网+手机”,能否成为飞利浦的新起点?

群雄逐鹿&#xff0c;手机品牌急需特色与创新 近年来&#xff0c;中国的智能手机市场竞争之激烈&#xff0c;堪比一场白热化的武林争霸赛。各大手机品牌纷纷使出浑身解数&#xff0c;在群雄逐鹿之下&#xff0c;几乎每隔几年市场格局都会进行一次重新分配。 历经几番厮杀之后&a…

手机显示java_手机自带的显示基站命令

安卓手机自带快捷指令显示当前的网络信息&#xff0c;不过手机厂商不同&#xff0c;命令也不一样。每次要用时总想不起来命令&#xff0c;记网络 安卓手机自带快捷指令显示当前的网络信息&#xff0c;不过手机厂商不同&#xff0c;命令也不一样。每次要用时总想不起来命令&…

利用基站定位手机

利用基站定位手机 在手机拨号键盘处输入以下各机型对应的命令&#xff0c;点拨号&#xff0c;然后选择 “手机信息”&#xff0c;能查看手机的如基站CELLID&#xff0c;LAC等GSM信息。通过基站的CELLID&#xff0c;附近CELLID、LAC、信号强度等信息反查推算就能精确到十几米级地…

利用微信平台作为飞利浦手机产品客服渠道的可行性调查

(by Li.zhu) 1 背景 微信公众号主要面向名人、政府、媒体、企业等机构推出的合作推广业务。在这里可以通过微信渠道将品牌推广给上亿的微信用户&#xff0c;减少宣传成本&#xff0c;提高品牌知名度&#xff0c;打造更具影响力的品牌形象。 根据腾讯公布的财报显示&…