アノテーションを使ってコントローラを作成する

Spring Frameworkではバージョン2.5からアノテーションを使ったコントローラの作成がサポートされています。
アノテーションベースでコントローラを作るメリットは以下のとおりです。

1.コントローラークラスが複数のアクションを処理できる
2.設定ファイルにいちいちマッピングを記述する必要がない

Springがアプリケーションのコントローラを見つけるために、設定ファイルに記述することは2つあります。

ひとつ目は、設定ファイルにspring-contextスキーマを宣言することです。

xmlns:context=~の部分です。
■application-config.xml
※これは、web.xmlで読み込む設定をした設定ファイルとなります。

<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context"

ふたつ目は、component-scanエレメントを設定ファイルに追加します。
デフォルトでは、以下のようにコメントアウトされているはず。

<!-- Uncomment and your base-package here:
     <context:component-scan
        base-package="org.springframework.samples.web"/>  -->

この例だと、「このアプリケーションのコントローラはすべて”org.springframework.samples.web”以下にありますよ」という意味になります。

すべてのコントローラをこのcomponent-scanエレメントに設定したパッケージに格納します。

以下にアノテーションをみていきます。

@Controllerアノテーションをつけたクラスは、Springに「このクラスはコントローラーですよ」と教えることになります。
@RequestMappingアノテーションはその名の通り、リクエストとメソッドを紐付けます。

たとえば、以下のように・・・

■FriendController.java

package controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class FriendController {
@RequestMapping(value = "/friend_input")
public String inputFriend() {
return "FriendForm";
}
}

@RequestMapping(value = “/friend_input”)と書かれた場合は、

http://domain(localhostとか)/contextroot(主にプロジェクト名)/friend_input

というURLにこのメソッドが紐付けられます。

@RequestMapping(“/friend_input”)
と書くこともできます。
もしRequestMappingのvalueが空の場合は、コンテキストルートのURLに紐付けられます。

@RequestMappingで、HTTPメソッドを指定したい場合。
たとえば、HTTP PUTかHTTP POSTだけ処理するように設定したい場合は、以下のようにmethod属性を指定します。

	@RequestMapping(value = "/friend_input", method={RequestMethod.POST, RequestMethod.PUT})
public String inputFriend() {
return "FriendForm";
}

method属性に何も指定しない場合は、全てのHTTPメソットを処理します。

RESTっぽくしたいなら、こんな感じで、コントローラクラスにURLを紐付けて、その下の階層で、そのクラスに対するアクションとURLを対応させるといいかと思います。

package controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@Controller
@RequestMapping(value="/user")
public class UserController {
@RequestMapping(value="/update",method={RequestMethod.POST, RequestMethod.PUT})
public String updateUser() {
return "update";
}
@RequestMapping(value="/delete",method={RequestMethod.POST, RequestMethod.PUT})
public String deleteUser() {
return "delete";
}
}

こうすると、Userを削除したい場合は

http://localhost/contextroot/user/delete

みたいなURLでリクエストを投げることになります。

リクエストを処理するメソッド(@RequestMappingで指定したメソッド)の引数に指定できるもの、返り値として返せるものはたくさんあるので、以下のサイトを参照してください。
http://docs.spring.io/spring/docs/3.0.0.M3/reference/html/ch16s11.html

サンプルアプリを作ってみます。
フォルダ構成はこんな感じになります。

f:id:sho322:20140530191027j:plain
f:id:sho322:20140530191032j:plain

■web.xml

<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns="http://java.sun.com/xml/ns/javaee"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
         id="WebApp_ID" version="2.5">
<!--
		- Servlet that dispatches request to registered handlers (Controller implementations).
	-->
<servlet>
<servlet-name>springweb</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/config/springmvc-config.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springweb</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>

上のweb.xmlでは、

<param-value>/WEB-INF/config/springmvc-config.xml</param-value>

のように、springmvc-config.xmlを読み込むように記述されているため、WEB-INF/config/以下にある、
springmvc-config.xmlを作成します。

■springmvc-config.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:p="http://www.springframework.org/schema/p"
	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="controller"/>
<mvc:annotation-driven/>
<!--  
	<mvc:resources mapping="/*.html" location="/" />
	<mvc:resources mapping="/css/**" location="/css/" />
	-->
<mvc:resources mapping="/resources/**" location="/WEB-INF/resources/" />
<bean id="viewResolver"
		class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
</beans>

component-scanはSpring MVCにスキャンするパッケージを知らせる役割を果たします。
resouceタグは、Spring MVCに固定的なリソースの場所を指定します。

resourceで定義した場所は、/WEB-INF/resoucesにmappingされているので、
CSSは/WEB-INF/resources/css/main.cssみたいに置いて、
それを読み込む側は、以下のように書けばOKです。

あとでソースコード全体を載せます。

<link rel="stylesheet" type="text/css" href="<c:url value='/resources/css/main.css'/>" />

■controller.FriendController

package controller;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import domain.Friend;
import form.FriendForm;
@Controller
public class FriendController {
private static final Log logger =
LogFactory.getLog(FriendController.class);
@RequestMapping(value="/friend_input")
public String inputFriend() {
logger.info("inputFriend called");
return "FriendForm";
}
@RequestMapping(value="/friend_save")
public String saveFriend(FriendForm friendForm, Model model) {
logger.info("saveFriend called");
Friend friend = new Friend();
friend.setName(friendForm.getName());
friend.setAge(Integer.parseInt(friendForm.getAge()));
friend.setHeight(Float.parseFloat(friendForm.getHeight()));
model.addAttribute("friend", friend);
return "FriendDetails";
}
}

■domain.Friend

package domain;
public class Friend {
private String name;
private int age;
private float height;
public Friend() {
}
public Friend(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public float getHeight() {
return height;
}
public void setHeight(float height) {
this.height = height;
}
}

■form.FriendForm

package form;
public class FriendForm {
private String name;
private String age;
private String height;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
public String getHeight() {
return height;
}
public void setHeight(String height) {
this.height = height;
}
}

■FriendForm.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html>
<html>
<head>
<title>友達入力</title>
<link rel="stylesheet" type="text/css" href="<c:url value='/resources/css/main.css'/>" />
</head>
<body>
<div id="global">
<form action="friend_save" method="post">
<fieldset>
<legend>友達を追加します</legend>
<label for="name">おなまえ:</label>
<input type="text" id="name" name="name" tabindex="1">
<label for="age">年齢:</label>
<input type="text" id="age" name="age" tabindex="2">
<label for="height">身長:</label>
<input type="text" id="height" name="height" tabindex="3">
<div id="buttons">
<input id="reset" type="reset" tabindex="4">
<input id="submit" type="submit" tabindex="5" 
                    value="友達を追加">
</div>
</fieldset>
</form>
</div>
</body>
</html>

■FriendDetails.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE HTML>
<html>
<head>
<title>友達詳細</title>
<link rel="stylesheet" type="text/css" href="<c:url value='/resources/css/main.css'/>" />
</head>
<body>
<div id="global">
<h4>友達を登録しました</h4>
<p>
<h5>詳細は以下のとおりです:</h5>
名前: ${friend.name}<br/>
年齢: ${friend.age}<br/>
身長: $${friend.height}
</p>
</div>
</body>
</html>

ブラウザに表示されるイメージは以下のようなものです。
f:id:sho322:20140530191048j:plain
f:id:sho322:20140530191055j:plain

<参考にした本>

Spring MVC/Rooプログラミング入門

Spring MVC/Rooプログラミング入門

Spring MVC: A Tutorial

Spring MVC: A Tutorial