読者です 読者をやめる 読者になる 読者になる

感謝のプログラミング 10000時間

たどり着いた結果(さき)は、感謝でした。

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

<スポンサーリンク>

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