①Spring 3入門―Javaフレームワーク・より良い設計とアーキテクチャ Spring MVCサンプル

MVC sample ( chapter 6 )

domain の定義 ( DTO とか Entityクラス とか Facade とか言われる )

package sample.customer.biz.domain;

import javax.validation.constraints.AssertFalse;
import javax.xml.bind.annotation.XmlRootElement;

import org.hibernate.validator.constraints.Email;
import org.hibernate.validator.constraints.Length;
import org.hibernate.validator.constraints.NotBlank;

@XmlRootElement
public class Customer implements java.io.Serializable {

private int id;

@NotBlank      /// バリデーションを定義する 
@Length(max = 20)
private String name;

@NotBlank
@Length(max = 100)
private String address;

@NotBlank
@Email
private String emailAddress;

public Customer(String name, String address, String emailAddress) {
this.name = name;
this.address = address;
this.emailAddress = emailAddress;
}

@AssertFalse(message = "{errors.ngemail}")
public boolean isNgEmail() {
// ドメイン名が「ng.foo.baz」であれば使用不可のアドレスと見なす
return emailAddress.matches(".*@ng.foo.baz$");
}

public boolean isFreeEmail() {
// ドメイン名が「free.foo.baz」であればフリーメールのアドレスと見なす
return emailAddress.matches(".*@free.foo.baz$");
}

public int getId() {
return id;
}

public String getName() {
return name;
}

public String getAddress() {
return address;
}

public String getEmailAddress() {
return emailAddress;
}

public Customer() {
}

public void setId(int id) {
this.id = id;
}

public void setName(String name) {
this.name = name;
}

public void setAddress(String address) {
this.address = address;
}

public void setEmailAddress(String emailAddress) {
this.emailAddress = emailAddress;
}

@Override
public String toString() {
return String.format(
"Customer [id=%s, name=%s, address=%s, emailAddress=%s]",
id, name, address, emailAddress);
}

private static final long serialVersionUID = 3428490997353904743L;
}

Service

package sample.customer.biz.service;

import sample.customer.biz.domain.Customer;

import java.util.List;

public interface CustomerService {
public List<Customer> findAll();

public Customer findById(int id) throws DataNotFoundException;

public Customer register(Customer customer);

public void update(Customer customer) throws DataNotFoundException;

public void delete(int id) throws DataNotFoundException;

public boolean isFreeEmailCustomer(Customer customer);
}

--------------- Service の定義 --------------------------------------

package sample.customer.biz.service;

public class DataNotFoundException extends Exception {

public DataNotFoundException() {
}

public DataNotFoundException(String msg) {
super(msg);
}

public DataNotFoundException(Throwable th) {
super(th);
}

public DataNotFoundException(String msg, Throwable th) {
super(msg, th);
}

private static final long serialVersionUID = 9046514570511590390L;
}

package sample.customer.biz.service;

import sample.customer.biz.domain.Customer;

import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

@Service("customerService")
public class MockCustomerService implements CustomerService {
// サンプル用のMock実装であるため、
// synchronized等の同期処理は一切おこなわない。
private Map<Integer, Customer> customerMap = new LinkedHashMap<Integer, Customer>();

private int nextId = 1;

private boolean isExists(int id) {
return customerMap.containsKey(id);
}

public List<Customer> findAll() {
return new ArrayList<Customer>(customerMap.values());
}

public Customer findById(int id) throws DataNotFoundException {
if (!isExists(id)) {
throw new DataNotFoundException();
}
return customerMap.get(id);
}

public Customer register(Customer customer) {
customer.setId(nextId++);
customerMap.put(customer.getId(), customer);

return customer;
}

public void update(Customer customer) throws DataNotFoundException {
if (!isExists(customer.getId())) {
throw new DataNotFoundException();
}
customerMap.put(customer.getId(), customer);
}

public void delete(int id) throws DataNotFoundException {
if (!isExists(id)) {
throw new DataNotFoundException();
}
customerMap.remove(id);
}

public boolean isFreeEmailCustomer(Customer customer) {
// この実装では、
// Customer#isFreeEmailを呼び出してその結果を返すだけ
return customer.isFreeEmail();
}

@PostConstruct
public void initCustomer() {
nextId = 1;

register(new Customer("太郎", "東京都新宿区", "taro@aa.bb.cc"));
register(new Customer("次郎", "東京都豊島区", "jiro@aa.bb.cc"));
register(new Customer("三郎", "東京都板橋区", "sabu@aa.bb.cc"));
}
}

----------- Controller ,  Struts がプレゼンテーションを行う場合、Actionクラス -- 

Controller

package sample.customer.web.controller;

import static org.springframework.web.bind.annotation.RequestMethod.GET;
import static org.springframework.web.bind.annotation.RequestMethod.POST;

import javax.validation.Valid;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.Errors;
import org.springframework.web.HttpSessionRequiredException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.SessionAttributes;
import org.springframework.web.bind.support.SessionStatus;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import sample.customer.biz.domain.Customer;
import sample.customer.biz.service.CustomerService;
import sample.customer.biz.service.DataNotFoundException;

@Controller
@RequestMapping("/customer/{customerId}")
@SessionAttributes("editCustomer")
public class CustomerEditController {

@Autowired
private CustomerService customerService;

@RequestMapping(value = "/edit", method = GET)
public String redirectToEntryForm(@PathVariable int customerId, Model model)
throws DataNotFoundException {
Customer customer = customerService.findById(customerId);
model.addAttribute("editCustomer", customer);

return "redirect:enter";
}

@RequestMapping(value = "/enter", method = GET)
public String showEntryForm(
@ModelAttribute("editCustomer") Customer customer) {
return "customer/edit/enter";
}

@RequestMapping(value = "/enter", params = "_event_proceed", method = POST)
public String verify(
@Valid @ModelAttribute("editCustomer") Customer customer,
Errors errors) {
if (errors.hasErrors()) {
return "customer/edit/enter";
}
return "redirect:review";
}

@RequestMapping(value = "/review", method = GET)
public String showReview(@ModelAttribute("editCustomer") Customer customer) {
return "customer/edit/review";
}

@RequestMapping(value = "/review", params = "_event_revise", method = POST)
public String revise() {
return "redirect:enter";
}

@RequestMapping(value = "/review", params = "_event_confirmed", method = POST)
public String edit(@ModelAttribute("editCustomer") Customer customer,
RedirectAttributes redirectAttributes, SessionStatus sessionStatus)
throws DataNotFoundException {
customerService.update(customer);

// retrun "redirect:edited";

redirectAttributes.addFlashAttribute("editedCustomer", customer);

sessionStatus.setComplete();

return "redirect:/customer";
}

@RequestMapping(value = "/edited", method = GET)
public String showEdited(
@ModelAttribute("editCustomer") Customer customer,
SessionStatus sessionStatus) {

sessionStatus.setComplete();

return "customer/edit/edited";
}

@ExceptionHandler
public String handleException(HttpSessionRequiredException e) {
return "redirect:/customer/{customerId}/edit";
}

@ExceptionHandler(DataNotFoundException.class)
public String handleException() {
return "customer/notfound";
}
}

package sample.customer.web.controller;

import static org.springframework.web.bind.annotation.RequestMethod.GET;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;

import sample.customer.biz.domain.Customer;
import sample.customer.biz.service.CustomerService;
import sample.customer.biz.service.DataNotFoundException;

@Controller
public class CustomerListController {

@Autowired
private CustomerService customerService;

@RequestMapping(value = "/", method = GET)
public String home() {
return "forward:/customer";
}

@RequestMapping(value = "/customer", method = GET)
public String showAllCustomers(Model model) {
List<Customer> customers = customerService.findAll();
model.addAttribute("customers", customers);
return "customer/list";
}

@RequestMapping(value = "/customer/{customerId}", method = GET)
public String showCustomerDetail(@PathVariable int customerId, Model model)
throws DataNotFoundException{
Customer customer = customerService.findById(customerId);
model.addAttribute("customer", customer);
return "customer/detail";
}

@ExceptionHandler(DataNotFoundException.class)
public String handleException() {
return "customer/notfound";
}
}

package sample.customer.web.controller;

import static org.springframework.web.bind.annotation.RequestMethod.*;

import java.nio.charset.Charset;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;

import sample.customer.biz.domain.Customer;
import sample.customer.biz.service.CustomerService;
import sample.customer.biz.service.DataNotFoundException;

@Controller
@RequestMapping("/api/customer")
public class CustomerRestController {

@Autowired
private CustomerService customerService;

@RequestMapping(method = POST)
@ResponseStatus(HttpStatus.OK)
@ResponseBody
public String register(@RequestBody Customer customer) {
customerService.register(customer);
return "OK";
}

// @RequestMapping(value = "/{customerId}", method = GET)
// @ResponseStatus(HttpStatus.OK)
// @ResponseBody
// public Customer findById(@PathVariable int customerId)
// throws DataNotFoundException {
// return customerService.findById(customerId);
// }

@RequestMapping(value = "/{customerId}", method = GET)
public ResponseEntity<Customer> findById(@PathVariable int customerId)
throws DataNotFoundException {
Customer customer = customerService.findById(customerId);

HttpHeaders headers = new HttpHeaders();
headers.setContentType(
new MediaType("text", "xml", Charset.forName("UTF-8")));
headers.set("My-Header", "MyHeaderValue");

return new ResponseEntity<Customer>(
customer, headers, HttpStatus.OK);
}

@ExceptionHandler
@ResponseStatus(HttpStatus.NOT_FOUND)
@ResponseBody
public String handleException(DataNotFoundException e) {
return "customer is not found";
}
}

package sample.customer.web.controller;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;

@Controller
public class FileUploadController {
private static final Log LOG = LogFactory.getLog(FileUploadController.class);

@RequestMapping(value = "/upload", method = RequestMethod.GET)
public String showUploadForm() {
return "upload";
}

@RequestMapping(value = "/upload", method = RequestMethod.POST)
public String uploadFile(
@RequestParam("uploadFile") MultipartFile multipartFile)
throws IOException{
// ファイル名
String fileName = multipartFile.getOriginalFilename();
// ファイルの大きさ(単位はbyte)
long size = multipartFile.getSize();
// コンテンツタイプ
String contentType = multipartFile.getContentType();
// 内容(byte配列)
byte[] fileContents = multipartFile.getBytes();

// ファイルとして保存
multipartFile.transferTo(new File("/tmp/" + fileName));

InputStream is = null;
try {
// ファイルの内容を読み込むためのInputStream
is = multipartFile.getInputStream();

// InputStreamを使用した処理
} finally {
// 必ずcloseする
is.close();
}

LOG.trace("size=" + size);
LOG.trace("contentType=" + contentType);
LOG.trace("fileContents=" + new String(fileContents, "UTF-8"));

return "redirect:/upload";
}
}

WEB-INFO / web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
<display-name>Sample MVC</display-name>
<context-param>
<param-name>defaultHtmlEscape</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:/META-INF/spring/beans-biz.xml
</param-value>
</context-param>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<filter>
<filter-name>characterEncodingFilter</filter-name>
<filter-class>
org.springframework.web.filter.CharacterEncodingFilter
</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:/META-INF/spring/beans-webmvc.xml
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>

views

--- upload.jsp

<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>ファイルアップロード</title>
</head>
<body>
<h1>ファイルアップロード</h1>
<form method="post" enctype="multipart/form-data">
<dl>
<dt>アップロードファイル</dt>
<dd><input type="file" name="uploadFile"></dd>
</dl>
<button type="submit">アップロード</button>
</form>
</body>
</html>

--- error.jsp

<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>例外発生(デバッグ用)</title>
</head>
<body>
<h1>例外発生(デバッグ用)</h1>
<dl>
<dt>例外クラス</dt>
<dd>${exception.class.name}</dd>
<dt>メッセージ</dt>
<dd>${exception.message}</dd>
</dl>

</body>
</html>

view/customer

-- details.jsp

<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>顧客詳細画面</title>
</head>
<body>
<h1>顧客詳細画面</h1>
<dl>
<dt>名前</dt>
<dd><c:out value="${customer.name}"/></dd>
<dt>住所</dt>
<dd><c:out value="${customer.address}"/></dd>
<dt>Eメールアドレス</dt>
<dd><c:out value="${customer.emailAddress}"/></dd>
</dl>
<c:url value="/customer" var="url"/>
<a href="${url}">一覧</a>
</body>
</html>

--- list.jsp

<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>顧客詳細画面</title>
</head>
<body>
<h1>顧客詳細画面</h1>
<dl>
<dt>名前</dt>
<dd><c:out value="${customer.name}"/></dd>
<dt>住所</dt>
<dd><c:out value="${customer.address}"/></dd>
<dt>Eメールアドレス</dt>
<dd><c:out value="${customer.emailAddress}"/></dd>
</dl>
<c:url value="/customer" var="url"/>
<a href="${url}">一覧</a>
</body>
</html>

--- notfound.jsp

<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>指定された顧客は見つかりません</title>
</head>
<body>
<h1>指定された顧客は見つかりません</h1>
<c:url value="/customer" var="url"/>
<a href="${url}">一覧画面へ戻る</a>
</body>
</html>

view/customer/edit

--- edited.jsp

<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>更新完了</title>
</head>
<body>
<h1>更新完了</h1>
<dl>
<dt>名前</dt>
<dd><c:out value="${editCustomer.name}"/></dd>
<dt>住所</dt>
<dd><c:out value="${editCustomer.address}"/></dd>
<dt>Eメールアドレス</dt>
<dd><c:out value="${editCustomer.emailAddress}"/></dd>
</dl>
<c:url var="url" value="/customer"/>
<a href="${url}">戻る</a>
</body>
</html>

--- enter.jsp

<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>入力画面</title>
</head>
<body>
<h1>入力画面</h1>
<form:form modelAttribute="editCustomer">
<dl>
<dt>名前</dt>
<dd>
<form:input path="name"/>
<form:errors path="name"/>
</dd>
<dt>住所</dt>
<dd>
<form:input path="address"/>
<form:errors path="address"/>
</dd>
<dt>Eメールアドレス</dt>
<dd>
<form:input path="emailAddress"/>
<form:errors path="emailAddress"/>
<form:errors path="ngEmail"/>
</dd>
</dl>
<button type="submit" name="_event_proceed" value="proceed">
次へ
</button>
</form:form>
</body>
</html>

---- review.jsp

<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>確認画面</title>
</head>
<body>
<h1>確認画面</h1>
<form method="post">
<dl>
<dt>名前</dt>
<dd><c:out value="${editCustomer.name}"/></dd>
<dt>住所</dt>
<dd><c:out value="${editCustomer.address}"/></dd>
<dt>Eメールアドレス</dt>
<dd><c:out value="${editCustomer.emailAddress}"/></dd>
</dl>
<button type="submit" name="_event_confirmed">更新</button>
<button type="submit" name="_event_revise">再入力</button>
</form>
</body>
</html>

  

トラックバック(0)

トラックバックURL: http://erikay.cho88.com/cms/mt-tb.cgi/1

コメントする