Spring MVCアーキテクチャパターン

MVCアーキテクチャパターン

UI関連の開発分野では、制御を介してモデルとビューを分離する

Mモデル:エンティティ、ビジネスロジック

Vビュー:ユーザーインターフェイス(Web、デスクトップ、モバイル)

Cコントローラー:サーブレット、アクション、コントローラー

MVCアーキテクチャパターンに関連:MVVM(モバイル、Vue、React)


問題ドメイン(一般的、言語に関係なく、すべて直面する必要がある)

 MVC / MVVM:モデルとビューの分離

ORM-OOP:言語とRDBMS間のマッピング

IoC / DI:依存性注入


 Java EE技術仕様のWeb関連テクノロジー

 サーブレット: HttpServletを継承して多数の サーブレットを定義します

JSP / JSTL

フィルター:特定のパスの要求に対して事前または事後フィルタリングを実行します(関数を追加) 

リスナー:アプリケーション(グローバル)、ユーザーセッション、HTTPリクエストのライフサイクル、または特定の瞬間をリッスンし、コールバック関数を登録します

起動シーケンス:

  フィルターはサーブレットより前です


 フィルターとリスナーの特定の役割について:(次にコードを使用して説明)

プロジェクトディレクトリ:


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 Files\Java\jdk-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\.plugins\org.eclipse.wst.server.core\tmp0]
4月 17, 2020 5:25:56 下午 org.apache.catalina.startup.VersionLoggerListener log
信息: CATALINA_HOME:         D:\Spring Boot\apache-tomcat-9.0.34
4月 17, 2020 5:25:56 下午 org.apache.catalina.startup.VersionLoggerListener log
信息: 命令行参数:[-Dcatalina.base=D:\springbootproject\.metadata\.plugins\org.eclipse.wst.server.core\tmp0]
4月 17, 2020 5:25:56 下午 org.apache.catalina.startup.VersionLoggerListener log
信息: 命令行参数:[-Dcatalina.home=D:\Spring Boot\apache-tomcat-9.0.34]
4月 17, 2020 5:25:56 下午 org.apache.catalina.startup.VersionLoggerListener log
信息: 命令行参数:[-Dwtp.deploy=D:\springbootproject\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps]
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 Files\Java\jdk-14\bin;C:\WINDOWS\Sun\Java\bin;C:\WINDOWS\system32;C:\WINDOWS;C:/Program Files/Java/jdk-14/bin/server;C:/Program Files/Java/jdk-14/bin;C:\Program Files\Java\jdk-14\bin;C:\Program Files\Java\jdk1.8.0_131\bin;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\WINDOWS\System32\WindowsPowerShell\v1.0\;D:\mysql\mysql-8.0.18-winx64\bin;C:\WINDOWS\System32\OpenSSH\;C:\Users\Admin;C:\Program Files\MySQL\MySQL Server 6.0\bin;C:\Program Files\nodejs\;C:\Users\Admin\AppData\Local\Microsoft\WindowsApps;;C:\Users\Admin\AppData\Roaming\npm;D:\Spring Boot\sts-4.5.1.RELEASE\sts-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使用过的数据库连接

上記は   フィルターとリスナーの特定の役割です。


春MVC

DispatcherServlet(ディスパッチャー):すべてのリクエストをインターセプトします

HandlerMapping:リクエストURLをコントローラーの特定のメソッド名にマッピングする

ViewResolver:コントローラから返されたビュー名を解決します

ViewResolver:ビューの種類に応じた特定のビューの分布

DispatcherServlet:特定のビューに戻る

 

ハンドラー:HTTPリクエストを処理するコントローラー内の特定のメソッド(HTTPメソッドとURL)

HandlerInterceptor:HTTPリクエストヘッダーのデータインターセプトを、リクエストメソッド、パスパラメーター、またはコントローラーメソッドのオブジェクトにカプセル化します。

DispatcherServletを作成して登録する2つの方法: 

// 创建和注册 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起動プロセス


Spring Web MVC起動プロセスをよりよく理解するために、次のコードを使用してデモを行います。

プロジェクトディレクトリ:


pom.xml(プロジェクトによって異なります)

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://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. dispatcherServle tフロントコントローラーを初期化します。 

4.スレッドプールを初期化する

5. RequestMappingHandlerAdapterプロセッサアダプタを初期化し  ます

6. RequestMappingHandlerMappingプロセッサマッピングを初期化  する


DispatcherServlet            : GET "/", parameters={}
RequestMappingHandlerMapping : Mapped to com.newer.smvc.HomeController#home()

 


コントローラメソッドが「@ ResponseBody」を返す場合、ViewResolverビューは解決されません

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のアーキテクチャパターンはここにあります。重要なことは、理解、理解、理解することです!質問があればメッセージを残してください!

元の記事を134件公開しました 賞賛されました348 再生回数20,000回以上

おすすめ

転載: blog.csdn.net/weixin_44364444/article/details/105584699