在 UI 相关的开发领域,通过控制实现模型与视图解耦
M 模型:实体、业务逻辑
V 视图:用户接口(Web、桌面、移动端)
C 控制器:Servlet、Action、Controller
MVC 架构模式相关的:MVVM(移动端、Vue、React)
MVC / MVVM : 模型与视图的解耦
ORM – OOP :语言 & RDBMS 之间的映射
IoC / DI : 依赖注入
Servlet : 通过继承 HttpServlet定义大量的 Servlet
JSP/JSTL
Filter:对特定路径的请求执行前置或后置的过滤(加入功能)
Listener: 对应用程序(全局)、用户会话、HTTP 请求的生命周期或特定时刻进行监听,注册回调函数
启动顺序:
Filter 早于 Servlet
关于 Filter 和Listener的具体作用:(接下来用代码演示)
工程目录:
AuthFilter.java
package com.newer.mvc.web.filter; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.annotation.WebFilter; import javax.servlet.http.HttpServletRequest; /** * Servlet Filter implementation class AuthListener */ @WebFilter(value = {"/admin/*","/api/*","/other"}) public class AuthFilter implements Filter { /** * Default constructor. */ public AuthFilter() { System.out.println("AuthListener 创建"); } /** * @see Filter#destroy() */ public void destroy() { // TODO Auto-generated method stub } /** * @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain) */ public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest req=(HttpServletRequest) request; System.out.println("鉴权"+req.getRequestURI()); chain.doFilter(request, response); } /** * @see Filter#init(FilterConfig) */ public void init(FilterConfig fConfig) throws ServletException { // TODO Auto-generated method stub } }
EncodingFilter.java
package com.newer.mvc.web.filter; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.annotation.WebFilter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * 过滤器 */ @WebFilter("/*") public class EncodingFilter implements Filter { /** * Default constructor. */ public EncodingFilter() { System.out.println("创建EncodingFilter"); } /** * @see Filter#destroy() */ public void destroy() { // TODO Auto-generated method stub } /** * @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain) */ public void doFilter( ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { // 执行前 // 应用场景:编码设置,鉴权,图片加水印。。。 HttpServletRequest req=(HttpServletRequest) request; HttpServletResponse res=(HttpServletResponse) response; req.setCharacterEncoding("UTF-8"); res.setCharacterEncoding("UTF-8"); String path=req.getRequestURI(); System.out.println("EncodingFilter doFilter:"+path); if(path.equals("/mvc/admin")) { // 鉴权 System.out.println("需要鉴权"); } // 执行后续的正常流程 chain.doFilter(request, response); // 执行后 // 如果是图片 if(res.getContentType().equals("image/*")){ System.out.println("加水印"); } } /** * @see Filter#init(FilterConfig) */ public void init(FilterConfig fConfig) throws ServletException { System.out.println("EncodingFilter 初始化。。。。。。"); } }
AppContextListener.java
package com.newer.mvc.web.listener; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; import javax.servlet.annotation.WebListener; /** * 监听器 * 不是你去调用的 * 该监听器关注的事件发生时,回调特定的方法 * * @author Admin * */ @WebListener public class AppContextListener implements ServletContextListener { /** * Default constructor. */ public AppContextListener() { System.out.println("ServletContextListener 创建"); } /** * @see ServletContextListener#contextDestroyed(ServletContextEvent) */ public void contextDestroyed(ServletContextEvent sce) { System.out.println("ServletContextListener 准备销毁。。。"); System.out.println("ServletContextListener 释放资源,如关闭数据库的连接池,"); System.out.println("ServletContextListener 销毁完毕。。。"); } /** * @see ServletContextListener#contextInitialized(ServletContextEvent) */ public void contextInitialized(ServletContextEvent sce) { System.out.println("ServletContextListener 初始化。。。"); System.out.println("ServletContextListener 加载资源,如创建数据库的连接池,装配依赖的资源"); } }
RequestListener.java
package com.newer.mvc.web.listener; import javax.servlet.ServletRequestEvent; import javax.servlet.ServletRequestListener; import javax.servlet.annotation.WebListener; import javax.servlet.http.HttpServletRequest; /** *监听一个Http请求的生命周期 * */ @WebListener public class RequestListener implements ServletRequestListener { /** * Default constructor. */ public RequestListener() { System.out.println("RequestListener"); } /** * @see ServletRequestListener#requestDestroyed(ServletRequestEvent) */ public void requestDestroyed(ServletRequestEvent sre) { HttpServletRequest req=(HttpServletRequest) sre.getServletRequest(); System.out.printf("RequestListener:销毁为%s使用过的数据库连接n",req.getRequestURI()); } /** * @see ServletRequestListener#requestInitialized(ServletRequestEvent) */ public void requestInitialized(ServletRequestEvent sre) { HttpServletRequest req=(HttpServletRequest) sre.getServletRequest(); System.out.printf("RequestListener:为%s从数据库连接池 创建一个数据库连接n",req.getRequestURI()); } }
程序运行后,控制台输出为:
4月 17, 2020 5:25:56 下午 org.apache.catalina.startup.VersionLoggerListener log 信息: Server.服务器版本: Apache Tomcat/9.0.34 4月 17, 2020 5:25:56 下午 org.apache.catalina.startup.VersionLoggerListener log 信息: 服务器构建: Apr 3 2020 12:02:52 UTC 4月 17, 2020 5:25:56 下午 org.apache.catalina.startup.VersionLoggerListener log 信息: 服务器版本号(:9.0.34.0 4月 17, 2020 5:25:56 下午 org.apache.catalina.startup.VersionLoggerListener log 信息: OS Name: Windows 10 4月 17, 2020 5:25:56 下午 org.apache.catalina.startup.VersionLoggerListener log 信息: OS.版本: 10.0 4月 17, 2020 5:25:56 下午 org.apache.catalina.startup.VersionLoggerListener log 信息: 架构: amd64 4月 17, 2020 5:25:56 下午 org.apache.catalina.startup.VersionLoggerListener log 信息: Java 环境变量: C:Program FilesJavajdk-14 4月 17, 2020 5:25:56 下午 org.apache.catalina.startup.VersionLoggerListener log 信息: JVM 版本: 14+36-1461 4月 17, 2020 5:25:56 下午 org.apache.catalina.startup.VersionLoggerListener log 信息: JVM.供应商: Oracle Corporation 4月 17, 2020 5:25:56 下午 org.apache.catalina.startup.VersionLoggerListener log 信息: CATALINA_BASE:[D:springbootproject.metadata.pluginsorg.eclipse.wst.server.coretmp0] 4月 17, 2020 5:25:56 下午 org.apache.catalina.startup.VersionLoggerListener log 信息: CATALINA_HOME: D:Spring Bootapache-tomcat-9.0.34 4月 17, 2020 5:25:56 下午 org.apache.catalina.startup.VersionLoggerListener log 信息: 命令行参数:[-Dcatalina.base=D:springbootproject.metadata.pluginsorg.eclipse.wst.server.coretmp0] 4月 17, 2020 5:25:56 下午 org.apache.catalina.startup.VersionLoggerListener log 信息: 命令行参数:[-Dcatalina.home=D:Spring Bootapache-tomcat-9.0.34] 4月 17, 2020 5:25:56 下午 org.apache.catalina.startup.VersionLoggerListener log 信息: 命令行参数:[-Dwtp.deploy=D:springbootproject.metadata.pluginsorg.eclipse.wst.server.coretmp0wtpwebapps] 4月 17, 2020 5:25:56 下午 org.apache.catalina.startup.VersionLoggerListener log 信息: 命令行参数:[-Dfile.encoding=UTF-8] 4月 17, 2020 5:25:56 下午 org.apache.catalina.core.AprLifecycleListener lifecycleEvent 信息: The APR based Apache Tomcat Native library which allows optimal performance in production environments was not found on the java.library.path: [C:Program FilesJavajdk-14bin;C:WINDOWSSunJavabin;C:WINDOWSsystem32;C:WINDOWS;C:/Program Files/Java/jdk-14/bin/server;C:/Program Files/Java/jdk-14/bin;C:Program FilesJavajdk-14bin;C:Program FilesJavajdk1.8.0_131bin;C:WINDOWSsystem32;C:WINDOWS;C:WINDOWSSystem32Wbem;C:WINDOWSSystem32WindowsPowerShellv1.0;D:mysqlmysql-8.0.18-winx64bin;C:WINDOWSSystem32OpenSSH;C:UsersAdmin;C:Program FilesMySQLMySQL Server 6.0bin;C:Program Filesnodejs;C:UsersAdminAppDataLocalMicrosoftWindowsApps;;C:UsersAdminAppDataRoamingnpm;D:Spring Bootsts-4.5.1.RELEASEsts-4.5.1.RELEASE;;.] 4月 17, 2020 5:25:57 下午 org.apache.coyote.AbstractProtocol init 信息: 初始化协议处理器 ["http-nio-8080"] 4月 17, 2020 5:25:57 下午 org.apache.catalina.startup.Catalina load 信息: 服务器在[1,382]毫秒内初始化 4月 17, 2020 5:25:57 下午 org.apache.catalina.core.StandardService startInternal 信息: Starting service [Catalina] 4月 17, 2020 5:25:57 下午 org.apache.catalina.core.StandardEngine startInternal 信息: 正在启动 Servlet 引擎:[Apache Tomcat/9.0.34] ServletContextListener 创建 RequestListener ServletContextListener 初始化。。。 ServletContextListener 加载资源,如创建数据库的连接池,装配依赖的资源 AuthListener 创建 创建EncodingFilter EncodingFilter 初始化。。。。。。 DispatcherServlet 4月 17, 2020 5:25:58 下午 org.apache.coyote.AbstractProtocol start 信息: 开始协议处理句柄["http-nio-8080"] 4月 17, 2020 5:25:58 下午 org.apache.catalina.startup.Catalina start 信息: Server startup in [899] milliseconds RequestListener:为/mvc/从数据库连接池 创建一个数据库连接 EncodingFilter doFilter:/mvc/ GET:/mvc/ RequestListener:销毁为/mvc/使用过的数据库连接 RequestListener:为/mvc/staff从数据库连接池 创建一个数据库连接 EncodingFilter doFilter:/mvc/staff staff GET:/mvc/staff RequestListener:销毁为/mvc/staff使用过的数据库连接 RequestListener:为/mvc/dept从数据库连接池 创建一个数据库连接 EncodingFilter doFilter:/mvc/dept dept GET:/mvc/dept RequestListener:销毁为/mvc/dept使用过的数据库连接 RequestListener:为/mvc/other从数据库连接池 创建一个数据库连接 鉴权/mvc/other EncodingFilter doFilter:/mvc/other GET:/mvc/other RequestListener:销毁为/mvc/other使用过的数据库连接
以上就是 Filter 和Listener的具体作用。
DispatcherServlet(分发器): 拦截所有请求
HandlerMapping:映射请求 url 到控制器中的特定方法名
ViewResolver:解析控制器返回的视图名
ViewResolver:根据视图类型具体视图分发
DispatcherServlet: 返回特定视图
Handler:处理一个 HTTP 请求(HTTP 方法加 URL)的控制器中的特定方法
HandlerInterceptor:把 HTTP 请求头中数据拦截封装成了控制器方法中的请求参数、路径参数、或是对象
两种创建和注册DispatcherServlet的方式:
// 创建和注册 DispatcherServlet DispatcherServlet servlet = new DispatcherServlet(ac); ServletRegistration.Dynamic registration = servletCxt.addServlet("app", servlet); // 预实例化和初始化 registration.setLoadOnStartup(1); // 路径映射:接收 `*` 所有请求 registration.addMapping("/app/*");
<!-- 创建和注册 DispatcherServlet --> <servlet> <servlet-name>app</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value></param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>app</servlet-name> <url-pattern>/app/*</url-pattern> </servlet-mapping>
为了更好的了解 Spring Web MVC 启动过程,接下来用代码进行演示:
工程目录:
pom.xml(工程所需的依赖)
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="https://maven.apache.org/POM/4.0.0" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.2.5.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.newer</groupId> <artifactId>smvc</artifactId> <version>0.1</version> <name>smvc</name> <description>Demo project for Spring Boot</description> <properties> <java.version>11</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
application.properties(配置)
logging.level.web=debug spring.http.log-request-details=true
SmvcApplication.java(这个工程会自动生成)
package com.newer.smvc; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class SmvcApplication { public static void main(String[] args) { SpringApplication.run(SmvcApplication.class, args); } }
HomeController.java
package com.newer.smvc; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.ResponseBody; @Controller public class HomeController { @GetMapping("/") public String home() { // 视图名 return "index.html"; } @ResponseBody @GetMapping("/hello") public String hello() { // 数据或资源 return "hello"; } }
工程运行,控制台输出:
接下来分析 Spring Web MVC 启动过程
1.在 ContextLoaderListener监听器中初始化 WebApplicationContext
2. 初始化 characterEncodingFilter 过滤器
3. 初始化 dispatcherServlet 前端控制器
4. 初始化线程池
5. 初始化 RequestMappingHandlerAdapter处理器适配器
6. 初始化 RequestMappingHandlerMapping处理器映射
DispatcherServlet : GET "/", parameters={} RequestMappingHandlerMapping : Mapped to com.newer.smvc.HomeController#home()
o.s.web.servlet.DispatcherServlet : GET "/", parameters={} s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped to com.newer.smvc.HomeController#home() o.s.w.s.v.ContentNegotiatingViewResolver : Selected 'text/html' given [text/html, application/xhtml+xml, image/webp, image/apng, application/xml;q=0.9, application/signed-exchange;v=b3;q=0.9, */*;q=0.8] o.s.w.servlet.view.InternalResourceView : View name 'index.html', model {} o.s.w.servlet.view.InternalResourceView : Forwarding to [index.html] o.s.web.servlet.DispatcherServlet : "FORWARD" dispatch for GET "/index.html", parameters={} o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped to ResourceHttpRequestHandler ["classpath:/META-INF/resources/", "classpath:/resources/", "classpath:/static/", "classpath:/public/", "/"] o.s.web.servlet.DispatcherServlet : Exiting from "FORWARD" dispatch, status 200 o.s.web.servlet.DispatcherServlet : Completed 200 OK
关于Spring MVC的 架构模式就到这里结束了,重要的是理解,理解,理解!!!有问题的小伙伴,欢迎留言!!!
本网页所有视频内容由 imoviebox边看边下-网页视频下载, iurlBox网页地址收藏管理器 下载并得到。
ImovieBox网页视频下载器 下载地址: ImovieBox网页视频下载器-最新版本下载
本文章由: imapbox邮箱云存储,邮箱网盘,ImageBox 图片批量下载器,网页图片批量下载专家,网页图片批量下载器,获取到文章图片,imoviebox网页视频批量下载器,下载视频内容,为您提供.
阅读和此文章类似的: 全球云计算