【Webアプリ開発】root-context.xmlの解説

#はじめに
DreamHanksの松下です。今回はroot-context.xmlの解説をしていきます。

データベースはMySql
DBアクセスはMyBatisというオープンソースのO/Rマッピングツールを使っています。

[連載記事まとめ](https://qiita.com/DreamHanks/items/7df703a509ef22f64d2c)



#contextファイルとは
Springフレームワークを使ってアプリ開発をする際のプロジェクトの構成ファイルです。

ビルドするときにcontextファイルの中のbeanオブジェクトを使い
そのオブジェクト内に設定されているvalue値から、何かと何かを参照できるようにする（繋げる）役割があります。

具体例としては以下のものが挙げられます。
・データベースの参照・接続
・Serviceクラスからdaoのインターフェースメソッドを呼んだ際に
　Mapperクラスの記述されているsql文を参照する。
・ControllerクラスとJSPファイルの参照


#root-context.xmlとservlet-context.xmlの違いとは
root-context.xmlはビジネスロジックに関連するものを定義するためのものです。
例）データベースの参照・接続にかかわるもの

servlet-context.xmlはViewに関連するものを定義するためのものです。
例）ControllerクラスとJSPファイルの参照

>ビジネスロジックとは
 　計算ロジックやDBとのやり取りをするソースコードです。
>>実際に開発をするときはServiceクラスというものを用意し、そこに計算ロジックやDBとのやり取りをするメソッドを共通部品のように作成します。
>>そしてそれらをControllerクラスで呼び出すというようにView側とビジネスロジック側で分けて開発していきます



#root-context.xmlの詳しい解説

```php
<?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:aop="http://www.springframework.org/schema/aop"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:jdbc="http://www.springframework.org/schema/jdbc"
	xmlns:mybatis-spring="http://mybatis.org/schema/mybatis-spring"
	xsi:schemaLocation="http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.1.xsd
http://mybatis.org/schema/mybatis-spring http://mybatis.org/schema/mybatis-spring-1.2.xsd
http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd">

	<!-- Root Context: defines shared resources visible to all other web components -->
	<context:component-scan
		base-package="com.dreamhanks" />


	<!-- MySQL dataSource -->
	<bean id="dataSource"
		class="org.springframework.jdbc.datasource.DriverManagerDataSource">
		<property name="driverClassName"
			value="net.sf.log4jdbc.sql.jdbcapi.DriverSpy"></property>
		<property name="url"
			value="jdbc:log4jdbc:mysql://localhost:3306/work_db?useSSL=false&amp;serverTimezone=UTC"></property>
		<property name="username" value="root"></property>
		<property name="password" value="Daiki8863"></property>
	</bean>

	<!-- mybatis SqlSessionFactoryBean -->
	<bean id="sqlSessionFactory"
		class="org.mybatis.spring.SqlSessionFactoryBean">
		<property name="dataSource" ref="dataSource"></property>
		<property name="configLocation"
			value="classpath:/mybatis-config.xml"></property>
		<property name="mapperLocations"
			value="classpath:mappers/**/*Mapper.xml"></property>
	</bean>

	<!-- memberMapper -->
	<bean id="memberMapper"
		class="org.mybatis.spring.mapper.MapperFactoryBean">
		<property name="mapperInterface"
			value="com.dreamhanks.dao.MemberMapper" />
		<property name="sqlSessionFactory" ref="sqlSessionFactory" />
	</bean>

	<!-- worktimeMapper -->
	<bean id="worktimeMapper"
		class="org.mybatis.spring.mapper.MapperFactoryBean">
		<property name="mapperInterface"
			value="com.dreamhanks.dao.WorktimeMapper" />
		<property name="sqlSessionFactory" ref="sqlSessionFactory" />
	</bean>

	<!-- mybatis -->
	<bean id="sqlSession"
		class="org.mybatis.spring.SqlSessionTemplate"
		destroy-method="clearCache">
		<constructor-arg name="sqlSessionFactory"
			ref="sqlSessionFactory"></constructor-arg>
	</bean>

</beans>
```

上記のroot-context.xmlの記述について詳しく解説をしていきます。


##サーバーにスキャン（認識）させる
```php
	<context:component-scan
		base-package="com.dreamhanks" />
```

上記のソースコードは「com.dreamhanks」以下のソースコードをサーバーにスキャン（認識）させるための記述です。

####「com.dreamhanks」以下のソースコードに何があるのか？

下記の5つのモジュールがあります
・dao
・dto
・form
・service
・workmanager(コントローラ

![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/708649/a7bfd219-da6d-60d5-d398-1d6d299a2442.png)

「root-context.xmlとservlet-context.xmlの違いとは」で解説したように、
root-context.xmlではビジネスロジックに関連することを定義するためのものです。

したがって、formやworkmanager(コントローラ）は関係なく、下記のようにdto, dao, serviceのみを定義することもできます。


```php
<context:component-scan		
	base-package="com.dreamhanks.service" />	
<context:component-scan		
	base-package="com.dreamhanks.dao" />	
<context:component-scan		
	base-package="com.dreamhanks.dto" />	
```

>３つのみを定義することのメリットとは？

>モジュールが大きくなければ、すべてスキャンしても所要時間少なくて済みますが
>大きなモジュールの場合「com.dreamhanks」以下のソースコードを全てスキャンすることは
>form,  workmanager(コントローラ）の分もスキャンしてしまうので所要時間がその分多くかかります。

>よって３つのみを定義することは大きなモジュールの場合、有益に働きます。



####具体的に何を認識させるのか？
ソース内に記述されているアノテーションをスキャンすることで、サーバーに下記の事柄を認識させます。
・サーバーにどのクラスがサービスなのか？
・どのクラスが@AutowiredなどのDependency Injection（依存性の注入）があるのか？

>Dependency Injection（依存性の注入）についての詳しい解説は下記のリンクをご覧ください（2020/09/16工事中）

##コードとコードの連携の仕組み

<context:component-scan>タグから下の何かと何かの連携をさせるための記述について解説していきます。

###◆ソースコードとデータベースがどのような流れで繋がるのか？

![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/708649/5f789cb9-8cb1-6e36-eca5-2d0581602b53.png)




上記の図はroot-context.xmlの下記のbeanの定義によって
Serviceクラスでのメソッド呼び出しから、MySqlへのDB操作の連携の流れを表しております。
・<!-- MySQL dataSource -->
・<!-- mybatis SqlSessionFactoryBean -->
・<!-- memberMapper -->
・<!-- worktimeMapper -->
・<!-- mybatis -->


一つづつ順番に見ていきます


##①ServiceクラスとMapperクラスを繋げる
下記の記述はServiceクラスとMapperクラスを繋げるためのものです。

```php
    <!-- memberMapper -->
    <bean id="memberMapper"
        class="org.mybatis.spring.mapper.MapperFactoryBean">
        <property name="mapperInterface"
            value="com.dreamhanks.dao.MemberMapper" />
        <property name="sqlSessionFactory" ref="sqlSessionFactory" />
    </bean>

    <!-- worktimeMapper -->
    <bean id="worktimeMapper"
        class="org.mybatis.spring.mapper.MapperFactoryBean">
        <property name="mapperInterface"
            value="com.dreamhanks.dao.WorktimeMapper" />
        <property name="sqlSessionFactory" ref="sqlSessionFactory" />
    </bean>
```

各マッパーのbeanマッピングは、MyBatisジェネレータで作成したDao,Dto,Mapperの数分を記述します。

今回はmemberテーブルとworktimeテーブルをMyBatisジェネレートしたので、２つのマッピングを記述しました。

###★マッピング構造を理解する
マッピング構造を理解して、上記の記述がどのようにServiceクラスとMapperクラスを繋げているのかを解説します。

上記のマッピング構造をjavaソースに置き換えて解説すると下記のようになります。
![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/708649/c2df07c5-15ac-be0a-eb7f-a144ecbf6b25.png)


```php
    <bean id="memberMapper"
        class="org.mybatis.spring.mapper.MapperFactoryBean">
```

上記の記述は「継承クラス名：org.mybatis.spring.mapper.MapperFactoryBean」
を継承する「クラス名：memberMapper」オブジェクトとして扱うことができるようになります。


```php
        <property name="mapperInterface"
            value="com.dreamhanks.dao.WorktimeMapper" />
　　　　 <property name="sqlSessionFactory" ref="sqlSessionFactory" />
```
上記の記述は「変数名mapperInterface」で「値：com.dreamhanks.dao.MemberMapper」を持ち
「sqlSessionFactory」を参照するという意味です。


##②MapperクラスとMappersクラスを連動させる

```php
    <!-- mybatis -->
    <bean id="sqlSession"
        class="org.mybatis.spring.SqlSessionTemplate"
        destroy-method="clearCache">
        <constructor-arg name="sqlSessionFactory"
            ref="sqlSessionFactory"></constructor-arg>
    </bean>	
```

Mapperクラスにはインターフェースのメソッドが記述されています。
Mappersクラスには実際にSQL文がXML形式で記述されています。

上記の記述はメソッドとSQL文の架け橋をしてくれます。



##③各テーブルのマッピングと<!-- mybatis -->を連動させる

```php
    <!-- mybatis SqlSessionFactoryBean -->
    <bean id="sqlSessionFactory"
        class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"></property>
        <property name="configLocation"
            value="classpath:/mybatis-config.xml"></property>
        <property name="mapperLocations"
            value="classpath:mappers/**/*Mapper.xml"></property>
    </bean>	
```

この記述は下記の２つの役割があります。
①MySQLとMappperを連動させるため
②MySQLとMyBatisを連動させるため



```php
        <property name="dataSource" ref="dataSource"></property>
```
上記の記述は「dataSource」を参照するという意味です。
次の「MySQLとmybatis-config, mappaerを連動させる」ための記述です。


```php
        <property name="configLocation"
            value="classpath:/mybatis-config.xml"></property>
```

上記の記述はmybatisのconfigファイルの位置を示しています。
具体的にはMyBatisジェネレータを実行する際に、configファイルとDBを連動させるための記述です。


```php
        <property name="mapperLocations"
            value="classpath:mappers/**/*Mapper.xml"></property>
```
上記の記述は「Mapper.xml」の位置を示しています。
この記述が「各テーブルのマッピング」と「<!-- mybatis -->」が
「sqlSessionFactory（このマッピング）」を参照している理由です。


この記述によって「各テーブルのマッピング」と「<!-- mybatis -->」が紐づきます。


##④SpringフレームワークとMySqlを連動させる

ここではSpringフレームワークとMySQLを連動させるために下記の記述を書いています。


```php
    <!-- MySQL dataSource -->
    <bean id="dataSource"
        class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName"
            value="net.sf.log4jdbc.sql.jdbcapi.DriverSpy"></property>
        <property name="url"
            value="jdbc:log4jdbc:mysql://localhost:3306/work_db?useSSL=false&amp;serverTimezone=UTC"></property>
        <property name="username" value="root"></property>
        <property name="password" value="Daiki8863"></property>
    </bean>	

```


「各テーブルのマッピング」と「<!-- mybatis -->」が紐づきを記述している
「sqlSessionFactory」はこの「dataSource」を参照しています。


```php
        <property name="url"
            value="jdbc:log4jdbc:mysql://localhost:3306/work_db?useSSL=false&amp;serverTimezone=UTC"></property>
        <property name="username" value="root"></property>
        <property name="password" value="Daiki8863"></property>
    </bean>	

```
上記の記述は下記の定義をしています。
「url」　　　　⇒　DBの場所
「username」　⇒　DBのアカウント名
「password」　⇒　DBのpassword


この「dataSource」を参照することによって、最終的にDBとの接続を行えるようになります。

#最後に
最新内容については下記のリンク（DreamHanksのブログ）で確認することができます。
[DreamHanksブログ（Javaウェブアプリ開発）](http://blog.dreamhanks.com/java%e3%82%a6%e3%82%a7%e3%83%96%e3%82%a2%e3%83%97%e3%83%aa%e9%96%8b%e7%99%ba/)