スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

Spring MVC ファイルアップロードを実装する[DB参照編]

前回、アップロードした画像ファイルをDBに登録したので、今回は画面に表示させてみる。

ファイルアップロードは対応すべき内容が多いので、記事を3回に分けて掲載する。
 ①[DB登録編]Book情報の作成にあたって、タイトル、価格に加えて画像ファイルもDBに登録する
  ⇒Spring MVC ファイルアップロードを実装する[DB登録編]
 ②[DB参照編]登録した画像ファイルを画面に表示させる
  ⇒本記事
 ③[入力チェック編]ファイルサイズに上限を設け、オーバーした場合は入力チェックエラーとする
  ⇒次回掲載予定

◎動作検証にあたっての各バージョンは以下の通り
  • SpringFramework 3.2.8.RELEASE
  • Java 1.7
  • Tomcat 7.0

1.result.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib uri="http://www.springframework.org/tags" prefix="spring"%>
<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
<link href="<c:url value="/css/bootstrap.min.css" />" rel="stylesheet">
<link href="<c:url value="/css/bootstrap-theme.min.css" />" rel="stylesheet">
<script src="<c:url value="/js/bootstrap.min.js" />"></script>
<title>result</title>
</head>
<body>
<spring:url value="/book/cover" var="varBookCoverUrl"/>
<spring:message code="bookId" var="varBookId"/>
<spring:message code="bookName" var="varBookName"/>
<spring:message code="price" var="varPrice"/>
<spring:message code="cover" var="varCover"/>

<div class="container-fluid">
<table class="table table-striped table-borderd">
<tr>
<td>${varBookId}</td>
<td>${book.bookId}</td>
</tr>
<tr>
<td>${varBookName}</td>
<td>${book.bookName}</td>
</tr>
<tr>
<td>${varPrice}</td>
<td>${book.price}</td>
</tr>
<tr>
<td>${varCover}</td>
<td><img src="${varBookCoverUrl}/${book.bookId}"/></td>




</tr>
</table>
</div>
</body>
</html>

登録完了画面に画像ファイルを表示させるにあたり、ポイントは2点。spring:url タグを使って、「/book/cover」を変数varBookCoverUrlに代入している点と、imgタグを使って、URLを組み立てている点になる。
まず、spring:url タグについては、コメント化した内容を見てもらえれば分かると思うが、単純に「/book/cover」を保持しているのではなく、「http://~」を補完してくれるようだ。また、imgタグのsrc属性には、URLの最後にbookIdを付与して、bookIdに対応する画像ファイルを取得するようにしている。ちなみにimgタグを使わず、他の項目と同じように${book.cover}とした場合、意味不明な文字列が表示される。
補足として${varBookId}や${varCover}などは国際化対応により、日本語と英語でラベルを切り替えるようにしている。過去の記事を参考にしてほしい。
■国際化対応に関する過去の記事
Spring MVC メッセージの国際化に対応する

2.BookController.java(関連箇所のみ掲載)

@Controller
@RequestMapping("/book")
public class BookController {

//省略

@RequestMapping(value = "/cover/{id}", method = RequestMethod.GET)
@ResponseBody
public byte[] getCover (@PathVariable("id") long bookId) {
logger.info("getCover start");
BookEntity entity = bookService.findById(bookId);
return entity.getCover();
}
}

「1.result.jsp」にて、imgタグのsrc属性にURLを設定したが、コントローラ側もそれにあわせる。 @RequestMappingアノテーションのvalue属性「/cover/{id}」の{id}は変数を表しており、getCoverメソッドの@PathVariableアノテーションを使って、idとbookIdを紐づけている。@ResponseBodyアノテーションについては、通常コントローラのメソッドはView名などを返すのだが、@ResponseBodyアノテーションを使うと任意の型を返却できる。今回の場合、「/book/cover/{id}」のURLが呼ばれると、バイト配列のcoverを返す。bookService.findByIdについては、その名の通り、bookIdよりエンティティを取得するメソッドとなる。

3.BookService.java/BookServiceImpl.java/BookDao.java
BookServiceインターフェースに、「T findById(long id);」を追加している。
BookServiceインターフェースを実装したBookServiceImplについては、「return dao.findById(id);」として、処理をDAOに委譲している。
BookDaoインターフェースには、「T findById(long id);」を追加している。
ソースのイメージについては、過去の記事を参考にしてほしい。
Spring MVC Spring Data JPAを使って登録する

4.BookDaoImpl.java(関連箇所のみ掲載)

@Repository
@Transactional
public class BookDaoImpl implements BookDao<BookEntity> {

@PersistenceContext
private EntityManager manager;

@Override
public void addEntity(BookEntity entity) {
logger.info("addEntity start");
manager.persist(entity);
}

@Override
@Transactional(readOnly=true)
public BookEntity findById(long id) {
logger.info("findById start");
return manager.find(BookEntity.class,id);
//下記の記述でもOK
//Query query = manager.createQuery("from BookEntity where bookId = " + id );
//return (BookEntity) query.getSingleResult();
}

//他のメソッドについては省略
}

今回追加したfindByIdメソッドの実装方法については、コメント化した方法でも可能であるが、1レコード取得するのであれば、findメソッドが使える。引数には、エンティティクラスとキーを渡せばよい。保守性の観点よりこちらの方法が良いかと思う。

5.BookEntity.java(関連箇所のみ掲載)

@Entity
@Table(name="Book")
public class BookEntity implements Serializable{

private static final long serialVersionUID = 1L;

@Id
@Column(name="book_id")
@GeneratedValue(strategy = GenerationType.AUTO)
private long bookId;

@Column(name="book_name", length=50, nullable=false)
private String bookName;

@Column(nullable=false)
private int price;

private byte[] cover;

//getter・setterは省略

エンティティについて改めて触れておく。bookIdについては、Bookテーブルの主キーとなる「book_id」とマッピングし、また、「@GeneratedValue(strategy = GenerationType.AUTO)」を付与して自動インクリメントに対応している。今回JPAのメリットだと感じたのが、この@GeneratedValueアノテーションで、「strategy = GenerationType.AUTO」とすることで、未入力の値を自動的に保管してくれる。具体的には、「bookService.addEntity(entity);」(前回の記事BookController.java参照)にて、bookIdが保管される。そのため、result.jspから${book.bookId}で参照しても、問題なく値を取得できる。同じことをSpring JDBCを使い、insert文を発行して実装した場合、自動インクリメントされたbook_idをどう取得するのか別途考慮する必要があるかと思う。この点が今回JPAを選択する理由の一つになった。

6.登録完了画面
ファイルアップロード表示

無事、アップロードした画像ファイルを表示することができた。
今回の実装にあたり、@ResponseBodyや@PathVariableなど、今まででてこなかったアノテーションを使用する良い機会となった。次回は、ファイルサイズの入力チェックを実装したいと思う。

■過去のSpring関連記事
Spring関連記事 Index

スポンサーサイト

コメントの投稿

非公開コメント

プロフィール

bookmount8

Author:bookmount8
システムエンジニア。サーバーサイドでjavaを扱うことが多い。最近は、ミドルやフロント周りも関心あり。

最新記事
カテゴリ
検索フォーム
最新コメント
月別アーカイブ
これまでの訪問者数
ブロとも申請フォーム

この人とブロともになる

RSSリンクの表示
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。