SEチャンネル

ITについてできる限り書くメモ

Spring+MongoDBでWebアプリケーション入門(3/3)

Spring Framework + MongoDBでアンケートWebアプリケーションを作る最終回。今回は管理者用のページを作成し、アンケートの結果一覧を見られるようにする。前回まででSpring+MongoDBの基本的な使い方については解説済みで、今回はほぼSpring Securityの使い方となる。

View

管理者用のログイン画面と、アンケート結果一覧の画面を用意する。

adminlogin.jsp

<body>
<div id="login">
    <form action="<c:url value='j_spring_security_check' />"
        method="post">
        username:<input type="text" name="username" maxlength="20" size="20" /><br/>
        password:<input type="password" name="password" maxlength="20" size="20" /><br/>
        <input type="submit" value="Login" />
    </form>
</div>
</body>

ログイン画面はusernameとpasswordを入力するフォームが2つだけあるシンプルな構成にする。

adminview.jsp

<body>
<table border="1">
    <tr>
        <th>userid</th>
        <th>Date</th>
        <th>question1answer</th>
        <th>question2answer</th>
    </tr>
    <c:forEach items="${allAnswers}" var="answer">
        <tr>
            <td><c:out value="${answer[0]}" /></td>
            <td><c:out value="${answer[1]}" /></td>
            <td><c:out value="${answer[2]}" /></td>
            <td><c:out value="${answer[3]}" /></td>
        </tr>
    </c:forEach>
</table>
</body>

アンケート結果は前回作成したSurveyAnswerEntityクラスのメンバuserid、Date、question1answer、question2answerをテーブル構造で表示する。ビジネスロジックからはallAnswersという変数で渡ってくる想定(もちろんすぐあとで作成する)。

sponsor

設定ファイル

今回、認証・認可の実装にはSpring Securityを使用する。まずはそのための設定ファイルを用意する。重要なファイルなので全て記載しておく。

<?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:sec="http://www.springframework.org/schema/security"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/security
      http://www.springframework.org/schema/security/spring-security.xsd
      http://www.springframework.org/schema/beans
      http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
      http://www.springframework.org/schema/context
      http://www.springframework.org/schema/context/spring-context.xsd">
    <sec:http auto-config="true" use-expressions="true">
        <sec:csrf disabled="true"/>
        <sec:intercept-url pattern="/admin/**" access="hasRole('ROLE_ADMIN')" />
        <sec:form-login
            login-page="/adminlogin"
            default-target-url="/admin/view"
            authentication-failure-url="/err"
            login-processing-url="/j_spring_security_check"/>
    </sec:http>
    <sec:authentication-manager>
        <sec:authentication-provider>
            <sec:user-service>
                <sec:user name="loginname"
                        password="pazzword"
                        authorities="ROLE_ADMIN" />
            </sec:user-service>
        </sec:authentication-provider>
    </sec:authentication-manager>
</beans>

intercept-urlが認可の設定を行うタグである。今回は/admin/配下のすべてのページはROLE_ADMIN権限でログインしていないと見れない設定になっている。

form-loginがログインフォームの設定である。login-pageでログインの画面を/adminloginに設定している。このログイン画面はログイン前に表示しないといけないため、/admin/配下に配置することはできない。default-target-urlでログイン後に遷移するページ、authentication-failure-urlでログイン失敗後に遷移するページを設定する。

認証認可のユーザはDBから取得することが一般的だが、Spring Securityでは設定ファイル内に記述することもできる。loginname/pazzwordでROLE_ADMINログインを設定ファイルに記載すると上の通りとなる。

pom.xml

<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-core</artifactId>
    <version>4.0.0.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-web</artifactId>
    <version>4.0.0.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-config</artifactId>
    <version>4.0.0.RELEASE</version>
</dependency>

pom.xmlにはSpring Securityのライブラリを追加する。

Controller

管理者用のコントローラを作成する。マッピングは先ほど作成したログイン画面と一覧表示画面を設定する。

AdminController.java

@Controller
public class AdminController {

    @Autowired
    private SurveyService surveyService;
    
    @RequestMapping(value="/adminlogin")
    public String adminlogin() {
        return "adminlogin";
    }
    
    @RequestMapping(value="/admin/view")
    public ModelAndView view() {
        ModelAndView model = new ModelAndView("adminview");
        List<String[]> allAnswers = surveyService.getAllAnswers();
        if (allAnswers.size() > 0)
            model.addObject("allAnswers", allAnswers);
        return model;
    }
}

一覧表示画面は/admin/viewにマッピングしていることに注意する。これは設定ファイルのところで説明したが、/admin/配下のページはすべてログインしていないと見れない設定にしているからである。処理はSurveyService#getAllAnswerで回答の一覧を取得して、allAnswersとしてviewに渡しているだけだ。

Service

public class SurveyService {
    (略)
    public List<String[]> getAllAnswers(){
        List<SurveyAnswerEntity> list = surveyAnswerRepo.selectAll();
        return Lists.transform(list, new Function<SurveyAnswerEntity, String[]>() {
            @Override
            public String[] apply(SurveyAnswerEntity arg0) {
                return new String[] {
                        arg0.getUserid(),
                        arg0.getDate(),
                        arg0.getSurvey1answer(),
                        arg0.getSurvey2answer()
                };
            }
        });
    }
}

先ほどControllelr側から呼び出したSurveyService#getAllAnswerのビジネスロジックを定義している。とはいってもSurveryAnswerRepository#selectAllでDB上のすべてのエントリを取得し(このメソッドも後ほど実態を定義する)、List<String[]>に詰めなおしているだけだ。変換はGoogleの有名なライブラリGoogle Guavaを使用している。もちろんJava8から用意されたラムダ式を使えばもっと簡素に書くことができる。

Repository

SurveyAnswerRepository.java

public interface SurveyAnswerRepository {

    public List<SurveyAnswerEntity> selectByUserid(String userid);
    public boolean insertEntity(SurveyAnswerEntity entity);   
    public List<SurveyAnswerEntity> selectAll();
}

インターフェース定義。先ほど使用したselectAllメソッドを追加している。

SurveyAnswerRepository.java

public class SurveyAnswerRepoMongoDBImpl implements SurveyAnswerRepository {
    
    @Autowired
    private MongoOperations mongoOperations;

    (略)

    @Override
    public List<SurveyAnswerEntity> selectAll() {
        Query q = new Query();
        return mongoOperations.find(q, SurveyAnswerEntity.class);
    }
}

MongoDBを使用した実装。全データを取得する場合はnew Query()をそのまま実行すればOK。

実行

ここまででやっと管理者用の画面を見ることができる。MongoDBを起動したままアプリを立ち上げれば、http://localhost:8080/SurveyApp/admin/viewにアクセスすればまず管理者用のログインページが表示される。

f:id:tkmtys:20151009001450p:plain

loginname/pazzwordでログインすればアンケートの回答一覧が表示されるはずである。

f:id:tkmtys:20151009001447p:plain

これでアンケートWebアプリのロジック部分は作成完了である。あとは必要に応じてアンケート項目の追加やスタイルシートの編集を行えばよい。

sponsor