インタビュアー:SpringMVCの起動プロセスについて教えてください!

ここに画像の説明を挿入

サーブレットの仕様とコンテナ

一般的に使用されているSpringMVCはサーブレット仕様に基づいて実装されているため、最初にサーブレット関連のコンテンツを確認しましょう。

ここに画像の説明を挿入

サーブレットを直接使用してWebアプリケーションを開発する場合は、HttpServletを継承してサービスメソッドを実装するだけで済みます。HttpServletはサーブレットから継承します。サーブレットで一般的に使用されるメソッドは次のとおりです。

public interface Servlet {
    
    

	// 初始化,只会被调用一次,在service方法调用之前完成
    void init(ServletConfig config) throws ServletException;
    
    ServletConfig getServletConfig();
    
    // 处理请求
    void service(ServletRequest req, ServletResponse res)throws ServletException, IOException;
    
    String getServletInfo();
    
    // 销毁
    void destroy();
}

各サーブレットには、サーブレットに関連する構成を格納するために使用されるServletConfigがあります。
各Webアプリケーションには、コンテナに関連する構成を格納するために使用されるServletContextがあります。

多くの小さなパートナーがサーブレットの多くの使用法に慣れていない可能性があることを考慮して、サーブレットを簡単に紹介し、xml構成を使用しましょう。もちろん、JavaConfigを使用してサーブレットを変更できます。

プロジェクト構成は以下のとおりです。
ここに画像の説明を挿入

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_3_1.xsd"
         version="3.1">

  <context-param>
    <param-name>configLocation</param-name>
    <param-value>test</param-value>
  </context-param>

  <servlet>
    <servlet-name>userServlet</servlet-name>
    <servlet-class>com.javashitang.controller.UserServlet</servlet-class>
    <init-param>
      <param-name>helloWord</param-name>
      <param-value>hello sir</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>

  <servlet-mapping>
    <servlet-name>userServlet</servlet-name>
    <url-pattern>/user.do</url-pattern>
  </servlet-mapping>

  <listener>
    <listener-class>com.javashitang.listener.MyServletContextListener</listener-class>
  </listener>

</web-app>
public class UserServlet extends HttpServlet {
    
    

    private String helloWord;

    @Override
    public void init(ServletConfig config) throws ServletException {
    
    
        this.helloWord = config.getInitParameter("helloWord");
    }

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
        resp.setContentType("text/html");
        PrintWriter out = resp.getWriter();
        String userId = req.getParameter("userId");
        out.println(helloWord + " " + userId);
    }
}

xml構成ファイルでは、init-paramタグを使用してサーブレットのいくつかの構成を設定してから、initメソッドでServletConfigを使用してこれらの構成を取得し、初期化を行うことができます。

访问
http://localhost:8080/user.do?userId=1
返回
hello sir 1

このサーブレットの起動時ロードラベルも構成されていることがわかります。このラベルの用途は何ですか。

Load-on-startupは、コンテナの起動時にサーブレットが初期化されることを意味します。配列が小さいほど、起動の優先度が高くなります。このタグが設定されていない場合、サーブレットは最初のリクエストが到着したときに初期化されます。

context-paramタグはコンテナーの初期構成であり、コンテナーのgetInitParameterメソッドを呼び出して属性値を取得できます。

リスナーは、Webアプリケーションの開始時または停止時にさまざまなイベントを送信する拡張メカニズムであり、リスナーを使用してこれらのイベントを監視し、初期化作業を行うことができます。データベース接続を初期化するための起動イベントの監視など。

私のデモでは、構成ファイルの場所を取得して印刷しました。

public class MyServletContextListener implements ServletContextListener {
    
    

	// 容器启动
    public void contextInitialized(ServletContextEvent sce) {
    
    
        ServletContext sc = sce.getServletContext();
        String location = sc.getInitParameter("configLocation");
        System.out.println(location);
    }

	// 容器销毁
    public void contextDestroyed(ServletContextEvent sce) {
    
    

    }
}

SpringMVCアプリケーションを作成する

xmlに基づいてSpringMVCアプリケーションを作成し、このアプリケーションに基づいて分析します。プロジェクトの構造は次のとおりです
ここに画像の説明を挿入
。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_3_1.xsd"
		 version="3.1">
		 
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>classpath:spring-context.xml</param-value>
	</context-param>

	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>

	<servlet>
		<servlet-name>dispatcher</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>classpath:spring-mvc.xml</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>

	<servlet-mapping>
		<servlet-name>dispatcher</servlet-name>
		<url-pattern>/</url-pattern>
	</servlet-mapping>

</web-app>

spring-context.xml(構成サービス、daoレイヤー)

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	   xmlns:context="http://www.springframework.org/schema/context"
	   xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

	<context:component-scan base-package="com.javashitang.service"/>

</beans>

spring-mvc.xml(構成およびSpring MVC関連の構成)

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	   xmlns:context="http://www.springframework.org/schema/context"
	   xmlns:mvc="http://www.springframework.org/schema/mvc"
	   xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd  http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">

	<context:component-scan base-package="com.javashitang.controller"/>
	<mvc:annotation-driven/>

</beans>
@RestController
public class UserController implements ApplicationContextAware {
    
    

	@Resource
	private UserService userService;
	private ApplicationContext context;

	@RequestMapping("user")
	public String index(@RequestParam("userId") String userId) {
    
    
		return userService.getUsername(userId);
	}

	@Override
	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
    
    
		this.context = applicationContext;
		System.out.println("UserController " + context.getId());
	}
}
public interface UserService {
    
    

	String getUsername(String userId);
}
@Service
public class UserServiceImpl implements UserService, ApplicationContextAware {
    
    

	private ApplicationContext context;

	@Override
	public String getUsername(String userId) {
    
    
		return userId;
	}

	@Override
	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
    
    
		this.context = applicationContext;
		System.out.println("UserServiceImpl " + context.getId());
	}
}

2つの構成ファイルを使用する必要がある理由は、SpringMVCに2つのコンテナーがあるためです。

親コンテナーはContextLoaderListenerによって初期化され、通常はいくつかのdaoレイヤーを格納するために使用されます。サービスレイヤーBean
サブコンテナーは、DispatcherServletによって初期化されます。

プロジェクト開始後の印刷値から、サービスとコントローラーは2つのコンテナーから取得されていることがわかります。

UserServiceImpl org.springframework.web.context.WebApplicationContext:
UserController org.springframework.web.context.WebApplicationContext:/dispatcher

子コンテナーは親コンテナー内のBeanにアクセスでき、親コンテナーは子コンテナー内のBeanにアクセスできません。対応するBeanが子コンテナから見つからない場合は、親コンテナから見つかります。

親コンテナの開始

親コンテナはContextLoaderListenerによって初期化されます。Tomcatが起動すると、起動イベントが公開され、ContextLoaderListener#contextInitializedメソッドが呼び出されてから、initWebApplicationContextメソッドが呼び出されます。

ここに画像の説明を挿入

子コンテナ開始

サブコンテナの開始は、DispatcherServlet#initメソッドにあります

DispatcherServletはinitメソッドをオーバーライドしなかったため、親クラスにあります。HttpServletBeanはinitメソッドをオーバーライドします。
ここに画像の説明を挿入
フローチャートを使用してプロセスを要約します

ここに画像の説明を挿入
親コンテナが役に立たないと思う場合は、すべてのBeanを子コンテナに入れることができます

リファレンスブログ

おすすめ

転載: blog.csdn.net/zzti_erlie/article/details/115190719