CLOVER🍀

That was when it all began.

Spring MVC、最初の一歩

Spring MVCを使ってOSGi Web Bundleを作成してみたいと思います。とりあえず、いろいろ準備が要りますが…用意したコードを列挙。

pom.xml

<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 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>my.web.bundle</groupId>
  <artifactId>my-web-bundle</artifactId>
  <packaging>war</packaging>
  <version>1.0.0</version>
  <name>my-web-bundle Maven Webapp</name>
  <url>http://maven.apache.org</url>
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
    <dependency>
		<groupId>org.springframework</groupId>
		<artifactId>org.springframework.spring-library</artifactId>
		<type>libd</type>
		<version>3.0.0.M3</version>
		<scope>provided</scope>
	</dependency>
	<dependency>
		<groupId>javax.servlet</groupId>
		<artifactId>com.springsource.javax.servlet.jsp.jstl</artifactId>
		<version>1.2.0</version>
		<scope>provided</scope>
	</dependency>
  </dependencies>
  <!--
  <build>
    <finalName>my-web-bundle</finalName>
  </build>
  -->
	<build>
	<plugins>
		<plugin>
			<artifactId>maven-war-plugin</artifactId>
			<version>2.1-beta-1</version>
			<configuration>
				<packagingExcludes>WEB-INF/lib/**</packagingExcludes>
			</configuration>
		</plugin>
	</plugins>
	</build>
	<repositories>
		<repository>
			<id>com.springsource.repository.bundle.external</id>
			<name>SpringSource Enterprise Bundle Repository - External Bundle Releases</name>
			<url>http://repository.springsource.com/maven/bundles/external</url>
		</repository>
		<repository>
			<id>com.springsource.repository.bundle.milestone</id>
		    <name>SpringSource Enterprise Bundle Repository - SpringSource Bundle Milestones</name>
			<url>http://repository.springsource.com/maven/bundles/milestone</url>
		</repository>
		<repository>
		    <id>com.springsource.repository.libraries.milestone</id>
		    <name>SpringSource Enterprise Bundle Repository - Milestone Library Releases</name>
		    <url>http://repository.springsource.com/maven/libraries/milestone</url>
		</repository>
	</repositories>
</project>

基本はgreenpages.webのpom.xmlを参考に作っていますが、SpringSourceのリポジトリの場所やSpringのバージョンは、greenpages.parentプロジェクトから引っ張ってきました。リポジトリは、全部コピーしたわけではありませんが、とりあえずこれだけあればコンパイルエラーなどにはならなくなりました。

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">

  <display-name>Archetype Created Web Application</display-name>

  <context-param>
    <param-name>contextClass</param-name>
    <param-value>org.eclipse.virgo.web.dm.ServerOsgiBundleXmlWebApplicationContext</param-value>
  </context-param>

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

  <servlet>
    <servlet-name>mywebbundle</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  </servlet>

  <servlet-mapping>
    <servlet-name>mywebbundle</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>
</web-app>

MavenのWebアプリケーション用プロジェクトが生成したものから、Servlet APIのバージョンを引き上げSpringのDispatcherServletを追加しています。

/WEB-INF/mywebbundle-servlet.xml

<?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/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">

	<bean class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping" />

	<!-- enable classpath scanning -->
	<context:component-scan base-package="my.web.bundle" />

	<!-- Configures the @Controller programming model -->
	<mvc:annotation-driven />

	<bean id="viewResolver"	class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<property name="prefix" value="/WEB-INF/jsp/" />
		<property name="suffix" value=".jsp" />
	</bean>
</beans>

greenpages.webから拝借しつつ、いくつか変更を加えました。

  • SpringのXML Schema定義が2.5を向いていたので、3.0に引き上げ
  • コンポーネントスキャンするパッケージは、「my.web.bundle」
  • ViewをJSPを使用するように変更
  • URLのルールにControllerClassNameHandlerMappingクラスを採用

基本的にはgreenpages.webを見ていますが、Spring MVCのサンプルプロジェクトである、以下のソースを併せて読んで設定しています。
https://src.springframework.org/svn/spring-samples/mvc-basic/trunk/

/WEB-INF/applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:osgi="http://www.springframework.org/schema/osgi"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
		http://www.springframework.org/schema/osgi http://www.springframework.org/schema/osgi/spring-osgi.xsd">
	
	<!-- import a service from OSGi implementing the Directory interface and make available as a bean called directory -->
	<!-- <osgi:reference id="directory" interface="greenpages.Directory" /> -->

</beans>

これはまだするべきことはありません。greenpages.webから持ってきましたが、コメントアウトしたのと、Springのスキーマバージョンが2.5を向いていたので引き上げておきました。

MANIFEST.MF

Manifest-Version: 1.0
Bundle-SymbolicName: my.web.bundle
Bundle-Version: 1.0.0
Bundle-Name: My Web Bundle
Web-ContextPath: my-web-bundle
Import-Library: org.springframework.spring;version="[3.0,3.1)"
Import-Bundle: com.springsource.org.apache.taglibs.standard;version="[
 1.1.2,1.3)"
Import-Package: org.eclipse.virgo.web.dm;version="[2.0.0,3.0.0)",
 org.springframework.beans.factory.annotation;version="[3.0,3.1)",
 org.springframework.core.io;version="[3.0,3.1)",
 org.springframework.stereotype;version="[3.0,3.1)",
 org.springframework.web.bind.annotation;version="[3.0,3.1)",
 org.springframework.web.context;version="[3.0,3.1)",
 org.springframework.web.servlet;version="[3.0,3.1)",
 org.springframework.web.servlet.mvc.annotation;version="[3.0,3.1)"

Import-Packageは、正直Springのものはどれが必要/不要なのかよくわかりません…。greenpages.webのMANIFEST.MFから持ってきつつ、FreeMaker系のライブラリは削りました。JSTLの依存関係が書いてあるのは、ちょっと遊んでいたからです。

Controllerのサンプル

package my.web.bundle;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
// @RequestMapping("/hello")
public class HelloController {
	private int count;
	
	@RequestMapping("/index")
	public String index() {
		return "index";
	}
}

URLのルールにControllerClassNameHandlerMappingクラスを利用したので、ControllerにRequestMappingアノテーションを付けなくても「/hello」でアクセスされるようになっています。メソッドをひとつ定義してあり、「/hello/index」でアクセスされると「WEB-INF/jsp/index.jsp」を見に行くようになっています。

/WEB-INF/jsp/index.jsp

<html>
<body>
<h2>Hello Spring MVC</h2>
</body>
</html>

何の変哲もない、ただのJSPです。

あと、src/main/resourcesは不要だったので削除しました。

ここまでやったら、STSでVirgo Web Serverを起動して以下のURLにアクセス。
http://localhost:8080/my-web-bundle/hello/index

とりあえず、動作しましたよっと。