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

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

レガシーなMVCアプリケーションを構築してみる

<スポンサーリンク>

今回はレガシーな(Spring2.5以前の)Spring MVCの開発方法について見ていきます。
フォルダ体系は以下のようになっています。

f:id:sho322:20140521191533j:plain
f:id:sho322:20140521191540j:plain


今回は、以下のような画面を表示するために、SpringMVCをどうやって書いていけばいいかを見ていきます。

f:id:sho322:20140521191601j:plain
f:id:sho322:20140521191607j: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">

    <display-name>springweb</display-name>
    
   <!--
		- Location of the XML file that defines the root application context.
		- Applied by ContextLoaderListener.
	-->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring/application-config.xml</param-value>
    </context-param>

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    
    
    <!--
		- Servlet that dispatches request to registered handlers (Controller implementations).
	-->
    <servlet>
        <servlet-name>springmvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!--  自分でconfiguration fileを設定する場合
        <init-param>
        	<param-name>contextConfigLocation</param-name>
        	<param-value>/WEB-INF/config/sample-config.xml</param-value>
        </init-param>
        -->
        <load-on-startup>1</load-on-startup>
    </servlet>
    
    <servlet-mapping>
    	<servlet-name>springmvc</servlet-name>
    	<url-pattern>/</url-pattern>
    </servlet-mapping>

</web-app>

「load-on-startup」エレメントはオプション設定です。
入れても入れなくても構いません。
このload-on-startupが存在すると、アプリケーションがスタートした時にサーブレットを読み込み、initメソッドを実行します。

load-on-startupがない場合は、サーブレットは初めてのリクエストがあったときに読み込まれます。

「servlet-name」エレメントにはサーブレットの名前を入れます。
このservlet-nameに指定した名前と一致するXMLファイルをWEB-INF以下に配置する必要があります。
具体的には、

<servlet-name>springmvc</servlet-name>

とした場合は、
springmvc-servlet.xml
というファイルをWEB-INF直下に作成します。

■springmvc-servlet.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans     
        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/mvc 
        http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
        http://www.springframework.org/schema/context 
        http://www.springframework.org/schema/context/spring-context-3.0.xsd">
 
    <bean name="/friend_input.action" class="controller.InputFriendController"/>
    <bean name="/friend_save.action" class="controller.SaveFriendController"/>

    <mvc:resources mapping="/resources/**" location="/resources/theme/" />

</beans>

このspringmvc-servlet.xmlには2つのコントローラークラスを定義します。
それぞれを、リクエストURLにマッピングします。

ちなみにもし、アプリケーションディレクトリの任意の場所にconfiguration file(設定ファイル)を配置したい場合は、
dispatcher servletの記述にinit-paramを設定します。
具体的には、以下のように書きます。

<servlet>
    <servlet-name>springmvc</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
    	<param-name>contextConfigLocation</param-name>
    	<param-value>/WEB-INF/config/sample-config.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

■Controller
Spring2.5以前のバージョンでは、controllerは「org.springframework.web.servlet.mvc.Controller」インターフェースをimplementsします。
(現在はアノテーションを使って便利に開発できます)

Spring MVCの開発を行うには、spring-webmvc-x.y.z.jarが必要なので、存在しない場合はダウンロードしましょう。
STSでSpring web projectを作ったときは、Maven Dependenciesに追加されています。

<!-- Spring MVC -->
<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-webmvc</artifactId>
	<version>${spring-framework.version}</version>
</dependency>

以下に具体的なコントローラーを見ていきます。
■SaveFriendController.java

package controller;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;

import domain.Friend;
import form.FriendForm;

public class SaveFriendController implements Controller {
    
    private static final Log logger = LogFactory.getLog(SaveFriendController.class);
    
    public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) 
                                throws Exception {
        logger.info("SaveFriendController called");
        
        FriendForm friendForm = new FriendForm();
        friendForm.setName(request.getParameter("name"));
        friendForm.setAge(request.getParameter("age"));
        friendForm.setHeight(request.getParameter("height"));
        
        Friend friend = new Friend();
        friend.setName(friendForm.getName());
        friend.setAge(Integer.parseInt(friendForm.getAge()));
        friend.setHeight(Float.parseFloat(friendForm.getHeight()));
        
        return new ModelAndView("/WEB-INF/jsp/FriendDetails.jsp","friend",friend);
    }
    
}

ここではリクエストパラメータを使って、FriendFormオブジェクトを作っています。
必要なものをパースしてFriendオブジェクトに詰め込んでいます。

返り値で返すModelAndViewというのは、viewへのパスを含んでいます。
「friend」というモデルをviewに渡す枠割を果たします。

■InputFriendController.java

package controller;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;

public class InputFriendController implements Controller {
    
    private static final Log logger = LogFactory.getLog(InputFriendController.class);
    
    public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response)
                        throws Exception {
        logger.info("InputFriendController called");
        
        return new ModelAndView("/WEB-INF/jsp/FriendForm.jsp");
    }

}

では、このコントローラーで振り分けたVIEWにあたる、JSPについてみてみます。
■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 href="<c:url value="/resources/css/main.css" />" rel="stylesheet">
</head>
<body>

<div id="global">
<form action="friend_save.action" 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"%>
<!DOCTYPE HTML>
<html>
<head>
<title>Save Product</title>
<link href="<c:url value="/resources/css/main.css" />" rel="stylesheet">
</head>
<body>
<div id="global">
    <h4>友達を登録しました</h4>
    <p>
        <h5>詳細は以下のとおりです:</h5>
         名前: ${friend.name}<br/>
                   年齢: ${friend.age}<br/>
                   身長: $${friend.height}
    </p>
</div>
</body>
</html>


■Maven Build - invalid LOC header (bad signature)
MavenでBuildしているときに、

invalid LOC header (bad signature)

というエラーが出た、そのときは、該当するファイルを削除すれば解決した。


■Spring-MVCでcssを読み込む方法
1.springmvc-servlet.xmlに以下の記載を追加する。

<mvc:resources mapping="/resources/**" location="/resources/theme/" />

このspringmvc-servlet.xmlは、WEB-INFの直下に置くもので、
web.xmlの

<servlet-name>springmvc</servlet-name>

で定義した[servlet-name]-servlet.xmlとなっている。

2.webapp以下にresourcesフォルダを作成する。
resources以下を見るようにmappingしているので、
webapp/resources/theme/css/main.cssのように、ファイルを配置する。

JavaScriptを置きたいときは、
webapp/resources/theme/js/hoge.js
のようにする。


3.JSPで読み込む。
headタグの中に、以下の記述を追加して、CSSを読み込む

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

taglibの設定も忘れずに。

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>