intra-mart Accel Platform TERASOLUNA Server Framework for Java (5.x) プログラミングガイド 第20版 2025-10-01

実装例:一覧画面を作る

この項では、TODO登録画面で登録したTODOをスマートフォンで一覧表示する画面の実装例を紹介します。

前提条件

  • intra-mart Accel Platform をインストールし、初期設定までが完了していること。

  • ベースモジュールに TERASOLUNA Server Framework for Java (5.x) for Accel Platform 、および、IM-Mobile Frameworkモジュールを含めて環境を作成してください。
    実行環境は単体テスト用で作成してください。
  • 実装例:登録画面を作る を参考に事前にテーブル作成、および、サンプル画面を作成しておいてください。

画面の用意

ソースの準備と配置

まず、以下2点のファイルを作成します。

  • jp.co.intra_mart.sample.spring.imsp.app.list.ListController

    package jp.co.intra_mart.sample.spring.imsp.app.list;
    
    import org.springframework.stereotype.Controller;
    import org.springframework.ui.Model;
    import org.springframework.web.bind.annotation.RequestMapping;
    
    @Controller
    @RequestMapping("sample/spring/sp/list")
    public class ListController {
        
        @RequestMapping({"", "/"})
        public String index(Model model) {
            return "sample/spring/imsp/list/index.jsp";
        }
    }
    
  • %CONTEXT_PATH%/WEB-INF/views/sample/spring/imsp/list/index.jsp

    <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
    <%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %>
    <%@ taglib prefix="imsp" uri="http://www.intra-mart.co.jp/taglib/imsp" %>
    <%@ taglib prefix="imui" uri="http://www.intra-mart.co.jp/taglib/imui" %>
    <imui:head>
      <title>TODO一覧</title>
    </imui:head>
    <div data-role="page" id="main" data-theme="a">
      <imsp:headerWithLink headerText="TODO一覧" />
      <div data-role="content">
      </div>
      <imsp:commonFooter dataPosition="fixed"/>
    </div>
    

メニューの設定

登録画面と同様に一覧画面をメニューに追加します。パスは”sample/spring/sp/list”とします。

../../../../../_images/menuitem.PNG

クライアントタイプをスマートフォンに切り替えグローバルナビ画面を表示します。

../../../../../_images/global_nav.PNG

TODO一覧を選択します。先ほど作ったブランク画面が表示されました。

../../../../../_images/blank.PNG

一覧表示部品を配置する

一覧表示を実現するには、<ul>タグ、および、<li>タグを使用します。

一覧のマークアップ例

例として見出し行、および、3行の一覧を表示してみます。
index.jspに以下の記述を追加します。
 <div data-role="content">
   <ul data-role="listview">
     <li data-role="list-divider">テストの一覧</li>
     <li>一行目です。</li>
     <li>二行目です。</li>
     <li>三行目です。</li>
   </ul>
 </div>

コラム

  • リスト表示する場合、ulタグにdata-role=”listview”属性を付加します。
  • liタグにdata-role=”list-divider”属性を付加することで強調表現として扱われます。
  • マークアップ結果。ulタグに囲まれたliタグが1行づつ表示されました。

    ../../../../../_images/list_first.PNG

それでは実際にTODO一覧を表示する処理を実装していきます。

検索処理の実装

前項で作成したリポジトリインタフェースに検索処理を追加します。

  • jp.co.intra_mart.sample.spring.imsp.domain.repository.MfwSampleRepository

    package jp.co.intra_mart.sample.spring.imsp.domain.repository;
    
    import java.util.List;
    
    import jp.co.intra_mart.sample.spring.imsp.domain.model.MfwSample;
    
    public interface MfwSampleRepository {
    
        void create(MfwSample entity);
    
        List<MfwSample> findAll();
    }
    

前項で作成したサービスクラスに検索処理を追加します。

  • jp.co.intra_mart.sample.spring.imsp.service.MfwSampleService

    package jp.co.intra_mart.sample.spring.imsp.service;
    
    import java.util.List;
    
    import jp.co.intra_mart.sample.spring.imsp.domain.model.MfwSample;
    
    public interface MfwSampleService {
        public void store(MfwSample entity);
        
        public List<MfwSample> findAll();
    }
    
  • jp.co.intra_mart.sample.spring.imsp.service.MfwSampleServiceImpl

    package jp.co.intra_mart.sample.spring.imsp.service;
    
    import java.util.List;
    
    import javax.inject.Inject;
    
    import org.springframework.stereotype.Service;
    
    import jp.co.intra_mart.sample.spring.imsp.domain.model.MfwSample;
    import jp.co.intra_mart.sample.spring.imsp.domain.repository.MfwSampleRepository;
    
    @Service
    public class MfwSampleServiceImpl implements MfwSampleService {
        
        @Inject
        MfwSampleRepository mfwSampleRepository;
        
        @Override
        public void store(MfwSample entity) {
            mfwSampleRepository.create(entity);
        }
    
        @Override
        public List<MfwSample> findAll() {
            return mfwSampleRepository.findAll();
        }
    }
    

ListControllerにサービスクラスをバインドし、検索処理を追加します。

@Inject
MfwSampleService mfwSampleService;

@RequestMapping({"", "/"})
public String index(Model model) {

    List<MfwSample> result = mfwSampleService.findAll();

    model.addAttribute("list", result);

    return "sample/spring/imsp/list/index.jsp";
}

前項で作成したマッピングファイルに検索処理で実行するクエリを追加します。

  • MfwSampleRepository.xml

    <select id="findAll" resultType="MfwSample">
        SELECT * FROM mfw_sample
    </select>
    

    コラム

    • データベースの詳細については データベース を参照してください。

index.jspのulタグの内部を修正します。

  <ul data-role="listview">
    <li data-role="list-divider">テストの一覧</li>
    <c:forEach var="record" items="${list}">
    <li><c:out value="${record.title}"/></li>
    </c:forEach>
  </ul>

マークアップ結果。登録されている全件のTODOのタイトルが表示されました。

../../../../../_images/repeat.PNG

コラム

この項目では、下記のポイントを確認しました。

  • 一覧表示するには<ul data-role=”listview”>を使用する
  • 行の表示は<li>タグを使用する

ページング処理を実装する

TODO一覧にページング処理を追加します。

ページ情報の定義

リポジトリインタフェースのfindAllメソッドを以下のように修正します。

  • jp.co.intra_mart.sample.spring.imsp.domain.repository.MfwSampleRepository

    import org.springframework.data.domain.Pageable;
    
    ...
    
    List<MfwSample> findAll(Pageable pageable);
    
    long count();
    

サービスクラスのfindAllメソッドを以下のように修正します。

  • jp.co.intra_mart.sample.spring.imsp.service.MfwSampleService

    import org.springframework.data.domain.Pageable;
    
    ...
    
    public List<MfwSample> findAll(Pageable pageable);
    
    ...
    
    public long count();
    
  • jp.co.intra_mart.sample.spring.imsp.service.MfwSampleServiceImpl

    import org.springframework.data.domain.Pageable;
    
    ...
    
    public List<MfwSample> findAll(Pageable pageable) {
        return mfwSampleRepository.findAll(pageable);
    }
    
    ...
    
    public long count() {
        return mfwSampleRepository.count();
    }
    

ListControllerクラスを以下のように修正します。

    import org.springframework.data.domain.PageRequest;
    import org.springframework.data.domain.Pageable;
    import org.springframework.data.domain.Sort.Direction;

    ...

    @RequestMapping({"", "/"})
    public String index(Model model, Integer currentPage) {

    currentPage = (currentPage == null)? 1 : currentPage;

    //ページング情報オブジェクト
    Pageable pageable = PageRequest.of(currentPage - 1, 5, Direction.ASC, "limit_date", "todo_id");

    List<MfwSample> result = mfwSampleService.findAll(pageable);

    model.addAttribute("currentPage", pageable.getPageNumber() + 1);
    model.addAttribute("pageLine", pageable.getPageSize());
    model.addAttribute("maxRecord", mfwSampleService.count());
    model.addAttribute("list", result);

    return "sample/spring/imsp/list/index.jsp";
}
マッピングファイルのクエリを修正します。
以下にPostgreSQLの例を示します。実際の運用では引数チェックやSQLインジェクション対策等を適切に実装してください。
<select id="findAll" resultType="MfwSample">
    SELECT * FROM mfw_sample
    ORDER BY
    <foreach collection="sort" item="order" separator=", ">
        ${order.property} ${order.direction}
    </foreach>
    LIMIT #{pageSize} OFFSET #{offset}
</select>

<select id="count" resultType="java.lang.Long">
    SELECT COUNT(*) FROM mfw_sample
</select>

ページング用タグの配置

  • index.jspのulタグの内部に<imsp:pagingButton>タグを表示します。 またページ送り用のフォームも設置します。

     <ul data-role="listview">
       <li data-role="list-divider">テストの一覧</li>
       <c:forEach var="record" items="${list}">
       <li><c:out value="${record.title}"/></li>
       </c:forEach>
       <imsp:pagingButton currentPage="${currentPage}" pageLine="${pageLine}" maxRecord="${maxRecord}" />
     </ul>
     <form id="pageForm" method="POST">
       <input type="hidden" name="currentPage" />
     </form>
    
    • 使用するタグについて

      jspタグ名 機能概要 マークアップ例
      pagingButton リストのページを移動するためのボタンを提供します。
      ../../../../../_images/spPagingButton.png

ページング処理の実装

  • 最後に、index.jspにページ遷移ボタン押下時の処理を追加します。

     <div data-role="page">
       <script>
         function onPageLinkFunc(page) {
           $("input[name=currentPage]").val(page);
           $("#pageForm").submit();
         }
       </script>
    

    コラム

    pagingButtonタグのページ遷移ボタンは未実装関数「onPageLinkFunc」を呼び出しますので
    必要に応じて実装してください。
  • マークアップ結果。一覧下部にページ遷移ボタンが表示され、一覧が5ページづつ表示されます。

    ../../../../../_images/paging-1.PNG
  • ページ遷移ボタン押下時。2ページ目が表示されました。

    ../../../../../_images/paging-2.PNG

コラム

この項目では、下記のポイントを確認しました。

  • ページング処理を実装するには<imsp:spPagingButton>タグを使用する

書式をカスタマイズする

より使いやすいレイアウトにするために、一覧表示の書式を修正します。

  • <ul>タグの内部を以下のように修正します。

     <ul data-role="listview">
       <li data-role="list-divider"><c:out value="${currentPage}" />ページ目</li>
       <c:forEach var="record" items="${list}">
         <li>
           <p class="ui-li-aside"><c:out value="${record.limitDate}"/></p>
           <h3><c:out value="${record.title}"/></h3>
           <p class="ui-li-desc"><c:out value="${record.comment}"/></p>
         </li>
       </c:forEach>
       <imsp:pagingButton currentPage="${currentPage}" pageLine="${pageLine}" maxRecord="${maxRecord}" />
     </ul>
    

    コラム

    <li>タグ内の<h>タグは主題として扱われます。
    <p class=”ui-li-aside”>は右端装飾部として表示されます。
    <p class=”ui-li-desc”>は副題として主題下部に表示されます。複数配置可能です。
  • マークアップ結果。日付とコメントが一覧に表示されるようになりました。

    ../../../../../_images/deco.PNG

最終結果

  • jp.co.intra_mart.sample.spring.imsp.app.list.ListController

    package jp.co.intra_mart.sample.spring.imsp.app.list;
    
    import java.util.List;
    
    import javax.inject.Inject;
    
    import jp.co.intra_mart.sample.spring.imsp.domain.model.MfwSample;
    import jp.co.intra_mart.sample.spring.imsp.service.MfwSampleService;
    
    import org.springframework.data.domain.PageRequest;
    import org.springframework.data.domain.Pageable;
    import org.springframework.data.domain.Sort.Direction;
    import org.springframework.stereotype.Controller;
    import org.springframework.ui.Model;
    import org.springframework.web.bind.annotation.RequestMapping;
    
    @Controller
    @RequestMapping("sample/spring/sp/list")
    public class ListController {
        
        @Inject
        MfwSampleService mfwSampleService;
        
        @RequestMapping({"", "/"})
        public String index(Model model, Integer currentPage) {
            
            currentPage = (currentPage == null)? 1 : currentPage;
            
            //ページング情報オブジェクト
            Pageable pageable = PageRequest.of(currentPage - 1, 5, Direction.ASC, "limit_date", "todo_id");
    
            List<MfwSample> result = mfwSampleService.findAll(pageable);
            
            model.addAttribute("currentPage", pageable.getPageNumber() + 1);
            model.addAttribute("pageLine", pageable.getPageSize());
            model.addAttribute("maxRecord", mfwSampleService.count());
            model.addAttribute("list", result);
            
            return "sample/spring/imsp/list/index.jsp";
        }
    }
    
  • %CONTEXT_PATH%/WEB-INF/views/sample/spring/imsp/list/index.jsp

    <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
    <%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %>
    <%@ taglib prefix="imsp" uri="http://www.intra-mart.co.jp/taglib/imsp" %>
    <%@ taglib prefix="imui" uri="http://www.intra-mart.co.jp/taglib/imui" %>
    <imui:head>
      <title>TODO一覧</title>
    </imui:head>
    <div data-role="page" id="main" data-theme="a">
      <script>
         function onPageLinkFunc(page) {
           $("input[name=currentPage]").val(page);
           $("#pageForm").submit();
         }
       </script>
      <imsp:headerWithLink headerText="TODO一覧" />
      <div data-role="content">
        <ul data-role="listview">
    	   <li data-role="list-divider"><c:out value="${currentPage}" />ページ目</li>
    	   <c:forEach var="record" items="${list}">
    	     <li>
    	       <p class="ui-li-aside"><c:out value="${record.limitDate}"/></p>
    	       <h3><c:out value="${record.title}"/></h3>
    	       <p class="ui-li-desc"><c:out value="${record.comment}"/></p>
    	     </li>
    	   </c:forEach>
    	   <imsp:pagingButton currentPage="${currentPage}" pageLine="${pageLine}" maxRecord="${maxRecord}" />
    	 </ul>
         <form id="pageForm" method="POST">
           <input type="hidden" name="currentPage" />
         </form>
      </div>
      <imsp:commonFooter dataPosition="fixed"/>
    </div>
    
  • jp.co.intra_mart.sample.spring.imsp.service.MfwSampleService

    package jp.co.intra_mart.sample.spring.imsp.service;
    
    import java.util.List;
    
    import org.springframework.data.domain.Pageable;
    
    import jp.co.intra_mart.sample.spring.imsp.domain.model.MfwSample;
    
    public interface MfwSampleService {
        public void store(MfwSample entity);
        
        public List<MfwSample> findAll(Pageable pageable);
        
        public long count();
    }
    
  • jp.co.intra_mart.sample.spring.imsp.service.MfwSampleServiceImpl

    package jp.co.intra_mart.sample.spring.imsp.service;
    
    import java.util.List;
    
    import javax.inject.Inject;
    
    import org.springframework.data.domain.Pageable;
    import org.springframework.stereotype.Service;
    
    import jp.co.intra_mart.sample.spring.imsp.domain.model.MfwSample;
    import jp.co.intra_mart.sample.spring.imsp.domain.repository.MfwSampleRepository;
    
    @Service
    public class MfwSampleServiceImpl implements MfwSampleService {
        
        @Inject
        MfwSampleRepository mfwSampleRepository;
        
        @Override
        public void store(MfwSample entity) {
            mfwSampleRepository.create(entity);
        }
    
        @Override
        public List<MfwSample> findAll(Pageable pageable) {
            return mfwSampleRepository.findAll(pageable);
        }
    
        @Override
        public long count() {
            return mfwSampleRepository.count();
        }
        
    }
    
  • jp.co.intra_mart.sample.spring.imsp.domain.repository.MfwSampleRepository

    package jp.co.intra_mart.sample.spring.imsp.domain.repository;
    
    import java.util.List;
    
    import org.springframework.data.domain.Pageable;
    
    import jp.co.intra_mart.sample.spring.imsp.domain.model.MfwSample;
    
    public interface MfwSampleRepository {
    
        void create(MfwSample entity);
    
        List<MfwSample> findAll(Pageable pageable);
    
        long count();
    }