카테고리 없음

MultiActionController example

Soul-Learner 2011. 8. 10. 18:28

MultiActionController를 이용하여 한개의 Controller클래스에 다수개의 메소드를 선언하고 클라이언트에서 각각의 메소드를 호출하는 예제

MultiActionController를 상속한 클래스에 클라이언트가 호출가능한 메소드를 선언하는 형식

메소드 리턴타입으로 가능한 자료형과 처리되는 형태

1. ModelAndView : 리턴한 그대로 전달된다
2. Map인 경우: new ModelAndView().addAllObjects(map)
3. String인 경우: new ModelAndView(str)
4. void인 경우: null



메소드 파리미터로 사용가능한 자료형

1. 첫번째 파라미터: HttpServletRequest
2. 두번째 파라미터: HttpServletResponse
3. 세번째 파라미터: HttpSession 혹은 Command 객체 중 하나



요청 URL에 포함된 파라미터에서 메소드이름을 찾아서 호출하도록 설정하려면 ParameterMethodNameResolver클래스를 bean으로 선언하여 사용할 Controller에 설정해 주어야 한다.

dispatcher-servlet.xml 설정파일

<?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:p="http://www.springframework.org/schema/p"
 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
 
 <bean name="/hello.htm"
  class="spring.test.controller.HelloController">
  <property name="dataSource" ref="dataSource"/>
 </bean>
 
 <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
  <property name="location">
   <value>classpath:config/jdbc.properties</value>
  </property>
 </bean>
 
 <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
  destroy-method="close">
   <property name="driverClassName" value="${jdbc.driver}"/>
   <property name="url" value="${jdbc.url}"/>
   <property name="username" value="${jdbc.username}"/>
   <property name="password" value="${jdbc.password}"/>
  </bean>
  
  <bean id="empDao" class="db.EmpDAO">
   <property name="ds" ref="dataSource"/>
  </bean>
 
 <bean id="sqlDateFormat"
  class="dateutil.SQLDateFormat"/>
  
 <bean name="/emp/empMultiActionCont.htm"
  class="spring.test.controller.EmpMultiActionController"
  p:cacheSeconds="-1"
  p:sqlDateFormat-ref="sqlDateFormat"
  p:empDao-ref="empDao"
  p:methodNameResolver-ref="methodNameResolver"/>
  
 <bean id="methodNameResolver"
  class="org.springframework.web.servlet.mvc.multiaction.ParameterMethodNameResolver"
  p:paramName="mode" />
 
 <bean id="beanNameUrlMapping"
  class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>

 <bean id="viewResolver"
  class="org.springframework.web.servlet.view.InternalResourceViewResolver">
  <property name="prefix" value="/" />
  <property name="suffix" value=".jsp"/>
 </bean>
</beans>



웹브라우저에서 콘트롤러의 특정 메소드를 호출하기 위한 URL의 형태

http://localhost/ContextName/search.htm?mode=methodName&paramName=paramValue

예를 들어, 아래와 같은 콘트롤러에서 searchByEmpno() 메소드를 호출하려면 다음과 같이 요청한다.
http://localhost/spring256/search.htm?mode=getEmpByEmpno&empno=7369

src/config/jdbc.properties

jdbc.driver=oracle.jdbc.OracleDriver
jdbc.url=jdbc:oracle:thin:@localhost:1521:XE
jdbc.username=scott
jdbc.password=tiger



EmpMultiActionController.java ( MultiActionController를  상속하여 작성)

다수개의 메소드를 콘트롤러에 선언하여 클라이언트에서 호출할 수 있도록 하려면 MultiActionController클래스를 상속해서 콘트롤러를 작성해야 한다.

다음 코드는 다수개의 메소드가 호출될 수  있다는 것만 확인하기 위한 것이므로 특정 디자인 패턴에 적합하지 않은 구성일 수도 있다.

package spring.test.controller;

import javax.servlet.http.*;

import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.web.bind.ServletRequestDataBinder;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.multiaction.MultiActionController;

import dateutil.SQLDateFormat;
import db.*;

public class EmpMultiActionController extends MultiActionController {

 /* 주입(DI)될 참조변수 */ 
 private EmpDAO empDao;
 private SQLDateFormat sqlDateFormat;
 
 public void setEmpDao(EmpDAO empDao) {
  this.empDao = empDao;
 }
 
 public void setSqlDateFormat(SQLDateFormat sqlDateFormat) {
  this.sqlDateFormat = sqlDateFormat;
 }

 public ModelAndView inputForm(HttpServletRequest request, HttpServletResponse response){
  ModelAndView mav = new ModelAndView("emp/inputForm");
  return mav;
 }
 
 public ModelAndView insert(HttpServletRequest request, HttpServletResponse response,
    Employee command){
  boolean ok = empDao.insert(command);
  ModelAndView mav = list(request,response);
  String msg = null;
  if(ok) msg = "정상적으로 정보를 저장했습니다";
  else msg = "저장도중에 오류가 발생하여 저장에 실패했습니다";
  mav.addObject("insertResult", msg);
  return mav;
 }
 
 public ModelAndView list(HttpServletRequest request, HttpServletResponse response){
  ModelAndView mav = new ModelAndView("emp/empList");
  mav.addObject("list", empDao.getList());
  return mav;
 }

 public ModelAndView getEmpByEmpno(HttpServletRequest request, HttpServletResponse response,
    Employee command){
  //int empno = Integer.valueOf(request.getParameter("empno"));
  int empno = command.getEmpno();
  ModelAndView mav = new ModelAndView("emp/empView");
  mav.addObject("emp", empDao.getEmpByEmpno(empno));
  return mav;
 }

 public ModelAndView updateForm(HttpServletRequest request, HttpServletResponse response,
  Employee command){
  ModelAndView mav = getEmpByEmpno(request,response,command);
  mav.setViewName("emp/updateForm");
  return mav;
 }
 
 public ModelAndView update(HttpServletRequest request, HttpServletResponse response,
  Employee command){
  boolean ok = empDao.update(command);
  ModelAndView mav = getEmpByEmpno(request,response,command);
  String msg = null;
  if(ok) msg = "정상적으로 정보를 변경했습니다";
  else msg = "변경도중에 오류가 발생하여 변경에 실패했습니다";
  mav.addObject("updateResult", msg);
  return mav;
 }
 
 
 public ModelAndView delete(HttpServletRequest request, HttpServletResponse response,
  Employee command){
  boolean ok = empDao.delete(command);
  ModelAndView mav = list(request,response);
  String msg = null;
  if(ok) msg = "정상적으로 정보를 삭제했습니다";
  else msg = "삭제도중에 오류가 발생하여 변경에 실패했습니다";
  mav.addObject("deleteResult", msg);
  return mav;
 }

 /* command 객체에 할당될 파라미터의 타입을 편집할 수 있도록 오버라이드한다.
  * 여기서는 hiredate 문자열을 java.sqlDate형으로 변환하는 내용이다.
  * @see org.springframework.web.servlet.mvc.multiaction.MultiActionController#initBinder(javax.servlet.http.HttpServletRequest, org.springframework.web.bind.ServletRequestDataBinder)
 */
 @Override
 protected void initBinder(HttpServletRequest request,
   ServletRequestDataBinder binder) throws Exception {
  //MyDateFormat sdf = new MyDateFormat("yyyy-MM-dd");
  CustomDateEditor cde = new CustomDateEditor(sqlDateFormat, false);
  binder.registerCustomEditor(java.sql.Date.class, "hiredate",cde );
 }

}



EmpDAO.java

package db;

import java.sql.*;
import java.util.ArrayList;

import javax.naming.*;
import javax.sql.*;

import org.apache.commons.dbcp.BasicDataSource;

public class EmpDAO {

 /* Spring 빈 설정파일에서 주입하는 대상 객체 */
 private BasicDataSource ds;
 
 public void setDs(BasicDataSource ds) {
  this.ds = ds;
 }

 public Connection getConn() throws NamingException, SQLException{
  
   //Context initCtx = new InitialContext();   
   //Context envCtx = (Context) initCtx.lookup("java:comp/env");   
   //DataSource ds = (DataSource) envCtx.lookup("jdbc/myoracle");   
   Connection conn = ds.getConnection();
   return conn;
 }
 
 public boolean authenticate(Employee emp){
  String sql = "select empno, ename from employee where empno=? and ename=?";

  Connection conn = null;
  PreparedStatement pstmt = null;
  ResultSet rs = null;
  try {
   conn = getConn();
   pstmt = conn.prepareStatement(sql);
   pstmt.setInt(1,emp.getEmpno());
   pstmt.setString(2,emp.getEname());
   rs = pstmt.executeQuery();
   if(rs.next())return true;
   return false;
  } catch (NamingException e) {
   e.printStackTrace();
  } catch (SQLException e) {
   e.printStackTrace();
  }finally{
   try{
    closeAll(rs, pstmt, conn);
   }catch(Exception e){}
  }
  return false;
 }
 
 public boolean insert(Employee emp){
  String sql = "insert into employee (empno,ename,deptno,sal,hiredate) "+
  "values(?,?,?,?,?)";

  Connection conn = null;
  PreparedStatement pstmt = null;

  try {
   conn = getConn();
   pstmt = conn.prepareStatement(sql);
   pstmt.setInt(1,emp.getEmpno());
   pstmt.setString(2,emp.getEname());
   pstmt.setInt(3,emp.getDeptno());
   pstmt.setInt(4,emp.getSal());
   pstmt.setDate(5,emp.getHiredate());
   int n = pstmt.executeUpdate();
   return n>0 ? true : false;
  } catch (Exception e) {
   e.printStackTrace();
  }finally{
   closeAll(null, pstmt, conn);
  }
  return false;

 }
 
 public Employee getEmpByEmpno(int empno) {
  String sql = "select * from employee where empno=?";

  Connection conn = null;
  PreparedStatement pstmt = null;
  ResultSet rs = null;
  try {
   conn = getConn();
   pstmt = conn.prepareStatement(sql);
   pstmt.setInt(1,empno);
   rs = pstmt.executeQuery();
   if(rs.next()){
    Employee emp = new Employee();
    emp.setEmpno(rs.getInt("EMPNO"));
    emp.setEname(rs.getString("ENAME"));
    emp.setDeptno(rs.getInt("DEPTNO"));
    emp.setSal(rs.getInt("SAL"));
    emp.setHiredate(rs.getDate("HIREDATE"));
    return emp;
   }
   return null;
  } catch (Exception e) {
   e.printStackTrace();
  }finally{
   closeAll(rs, pstmt, conn);
  }
  return null;
 }
 
 public boolean update(Employee emp) {
  String sql = "update employee set deptno=?, sal=? where empno=?";

  Connection conn = null;
  PreparedStatement pstmt = null;

  try {
   conn = getConn();
   pstmt = conn.prepareStatement(sql);
   pstmt.setInt(1,emp.getDeptno());
   pstmt.setInt(2,emp.getSal());
   pstmt.setInt(3,emp.getEmpno());
   int n = pstmt.executeUpdate();
   return n>0 ? true : false;
  } catch (Exception e) {
   e.printStackTrace();
  }finally{
   closeAll(null, pstmt, conn);
  }
  return false;
 }
 
 public boolean delete(Employee emp) {
  String sql = "delete from employee where empno=?";

  Connection conn = null;
  PreparedStatement pstmt = null;

  try {
   conn = getConn();
   pstmt = conn.prepareStatement(sql);
   pstmt.setInt(1,emp.getEmpno());
   int n = pstmt.executeUpdate();
   return n>0 ? true : false;
  } catch (Exception e) {
   e.printStackTrace();
  }finally{
   closeAll(null, pstmt, conn);
  }
  return false;
 }
 
 public ArrayList<Employee> getEmpByPage(int page) throws NamingException, SQLException{
  int end = page*4;
  int begin = page*4-(4-1);
  String sql =
   "select * from ( "+
    "select t1.*, rownum rn from ( "+
     "select empno, LPAD(' ', (LEVEL-1)*5, ' ')||decode(LEVEL,1,'','└ ')||ename ename, "+
      "hiredate from employee "+
      "start with ename='KING' connect by prior empno=mgr "+
        ")t1 "+
       ") "+
      "where rn between ? and ?";
  Connection conn = getConn();
   PreparedStatement pstmt = conn.prepareStatement(sql);
   pstmt.setInt(1, begin);
   pstmt.setInt(2, end);
   ResultSet rs = pstmt.executeQuery();
   ArrayList<Employee> list = new ArrayList<Employee>();
   while(rs.next()){
  // 한개의 레코드를 한개의 객체(DTO)로 Mapping하여 Collection에 저장
    Employee dto = new Employee();
    dto.setEmpno(rs.getInt("EMPNO"));
    dto.setEname(rs.getString("ENAME"));
    dto.setHiredate(rs.getDate("HIREDATE"));
    list.add(dto);
   }
   rs.close();
   pstmt.close();
   conn.close();
   return list;
 }
 
 public ArrayList<Employee> getList(){
  String sql = "select empno, ename, deptno from employee";
  Connection conn = null;
  PreparedStatement pstmt = null;
  ResultSet rs = null;
  try{
   conn = getConn();
   pstmt = conn.prepareStatement(sql);
   rs = pstmt.executeQuery();

    ArrayList<Employee> list = new ArrayList<Employee>();
    while(rs.next()){
     Employee dto = new Employee();
     dto.setEmpno(rs.getInt("EMPNO"));
     dto.setEname(rs.getString("ENAME"));
     dto.setDeptno(rs.getInt("DEPTNO"));
     list.add(dto);
    }
    return list;
  }catch(Exception e){
   e.printStackTrace();
  }finally{
   closeAll(rs,pstmt,conn);
  }
   return null;
 }
 
 public int getPageCnt(int rowsPerPage) {
  String sql = "select count(*) from employee";
  Connection conn = null;
  PreparedStatement pstmt = null;
  ResultSet rs = null;
  try {
   conn = getConn();
   pstmt = conn.prepareStatement(sql);
   rs = pstmt.executeQuery();
   rs.next();
   int totalCnt = rs.getInt(1);
   int pgCnt = totalCnt/rowsPerPage;
   if(totalCnt%rowsPerPage > 0 ) pgCnt++;
   return pgCnt;
  } catch (NamingException e) {
   e.printStackTrace();
  } catch (SQLException e) {
   e.printStackTrace();
  }finally{
   try{
    closeAll(rs,pstmt,conn);
   }catch(Exception e){}
  }
  return 0;
 }
 
 public ArrayList<String> getEnames(String keyword) {
  keyword = keyword.toUpperCase();
  //String sql = "select ename from emp where ename like '"+keyword+"%'";
  String sql = "select ename from employee where ename like ?";

  Connection conn = null;
  PreparedStatement pstmt = null;
  ResultSet rs = null;
  try {
   conn = getConn();
   pstmt = conn.prepareStatement(sql);
   pstmt.setString(1,keyword+"%");
   rs = pstmt.executeQuery();
   ArrayList<String> list = new ArrayList<String>();
   while(rs.next()){
    list.add(rs.getString("ENAME"));
   }
   return list;
  } catch (NamingException e) {
   e.printStackTrace();
  } catch (SQLException e) {
   e.printStackTrace();
  }finally{
   try{
    closeAll(rs, pstmt, conn);
   }catch(Exception e){}
  }
  return null;
 }
 
 private void closeAll(ResultSet rs, PreparedStatement pstmt, Connection conn){
  try{
   if(rs!=null)rs.close();
   if(pstmt!=null)pstmt.close();
   if(conn!=null)conn.close();
  }catch(Exception e){}
 }
}



Employee.java

package db;

import java.sql.Date;

public class Employee {
 
 private int empno;
 private String ename;
 private java.sql.Date hiredate;
 private int deptno;
 private int sal;
 
 public Employee() {}

 public Employee(int empno, String ename, Date hiredate) {
  this.empno = empno;
  this.ename = ename;
  this.hiredate = hiredate;
 }

 public int getEmpno() {
  return empno;
 }

 public String getEname() {
  return ename;
 }

 public Date getHiredate() {
  return hiredate;
 }

 public void setEmpno(int empno) {
  this.empno = empno;
 }

 public void setEname(String ename) {
  this.ename = ename;
 }

 public void setHiredate(Date hiredate) {
  this.hiredate = hiredate;
 }

 public int getDeptno() {
  return deptno;
 }

 public int getSal() {
  return sal;
 }

 public void setDeptno(int deptno) {
  this.deptno = deptno;
 }

 public void setSal(int sal) {
  this.sal = sal;
 }
 
}


SQLDateFormat.java

package dateutil;

import java.text.ParseException;
import java.text.SimpleDateFormat;
/* 문자열 날짜를 java.sql.Date형으로 변환하기 위한 커스텀 Property Editor*/
public class SQLDateFormat extends SimpleDateFormat{

 public SQLDateFormat() {
  super("yyyy-MM-dd");
 }
 
 public SQLDateFormat(String pattern) {
  super(pattern);
 }

 @Override
 public java.sql.Date parse(String arg0) {
  java.util.Date udate = null;
  try {
   udate = super.parse(arg0);
  } catch (ParseException e) {
   e.printStackTrace();
  }
  return new java.sql.Date(udate.getTime());
 }
}



empList.jsp

<%@ page contentType="text/html; charset=EUC-KR"
    pageEncoding="EUC-KR"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<c:if test="${!empty insertResult}">
 <script> alert("${insertResult}");</script>
</c:if>
<c:if test="${!empty deleteResult}">
 <script> alert("${deleteResult}");</script>
</c:if>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=EUC-KR">
<title>사원정보 리스트</title>
<style>
 .header{ background-color: #dddddd; }
 a:link { text-decoration: none; }
 a:visited { text-decoration: none; color:blue;}
 a:hover { text-decoration: none; color:gold; }
 a:active { text-decoration: none; color:red; }
</style>
</head>
<body><br/><br/><center>
<table border="1" cellspacing="0" width="400">
 <caption>사원정보 리스트</caption>
 <tr class="header"><th>사번</th><th>이름</th><th>부서</th></tr>
 <c:forEach var="e" items="${list}">
 <tr><td>${e.empno}</td><td>
  <a href="empMultiActionCont.htm?mode=getEmpByEmpno&empno=${e.empno}">${e.ename}</a>
 </td><td>${e.deptno}</td></tr>
 </c:forEach>
</table>
<hr width="400"/>
<input type="button" value="사원정보입력"
 onClick="location.href='empMultiActionCont.htm?mode=inputForm'"/>

<hr width="400"/>
</center>
</center>
</body>
</html>



inputForm.jsp
<%@ page language="java" contentType="text/html; charset=EUC-KR"
    pageEncoding="EUC-KR"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=EUC-KR">
<title>사원정보 입력 폼</title>
<style>
 table{border: 2px double black; }
 th{ text-align: right; }
 td{ text-align: left; }
 .btn { text-align: center; }
</style>
</head>
<body><br/><br/><center>
사원정보 입력 폼<p/>
<form action="empMultiActionCont.htm" method="post">
 <input type="hidden" name="mode" value="insert"/>
<table border="1" cellspacing="0" width="300" height="150" rules="none" cellpadding="5">
 <tr><th>이름</th><td>
  <input type="text" name="ename" value="홍길동"/>
 </td></tr>
 <tr><th>사번</th><td>
  <input type="text" name="empno" value="1234"/>
 </td></tr>
 <tr><th>부서</th><td>
  <input type="text" name="deptno" value="30"/>
 </td></tr>
 <tr><th>급여</th><td>
  <input type="text" name="sal" value="1500"/>
 </td></tr>
 <tr><th>입사</th><td>
  <input type="text" name="hiredate" value="2010-05-25"/>
 </td></tr>
 <tr><td> </td><td> </td></tr>
 <tr><td colspan="2" class="btn">
  <input type="submit" value="저 장"/>
  <input type="reset" value="취 소"/>
  </td></tr>
</table>
</form>
<p/>
<hr width="400"/>
<input type="button" value="리스트"
 onClick="location.href='empMultiActionCont.htm?mode=list'"/>
<hr width="400"/>
</center>
</body>
</html>


empView.jsp
<%@ page contentType="text/html; charset=EUC-KR"
    pageEncoding="EUC-KR"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<c:if test="${!empty updateResult}">
 <script> alert("${updateResult}");</script>
</c:if>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=EUC-KR">
<title>사원정보 리스트</title>
<style>
 .header{ background-color: #dddddd; }
 a:link { text-decoration: none; }
 td { text-align: left; }
</style>
<script>
function deleteConfirm(){
 if(confirm("정말로 삭제하시겠습니까?")){
  location.href='empMultiActionCont.htm?mode=delete&empno=${emp.empno}';
 }
}
</script>
</head>
<body><br/><br/><center>
<table border="1" cellspacing="0" width="400" cellpadding="5">
 <caption>사원정보 상세보기</caption>
 <tr ><th class="header">사번</th><td>${emp.empno}</td></tr>
 <tr><th class="header">이름</th><td>${emp.ename}</td></tr>
 <tr><th class="header">부서</th><td>${emp.deptno}</td></tr>
 <tr><th class="header">급여</th><td>${emp.sal}</td></tr>
 <tr><th class="header">입사</th><td>${emp.hiredate}</td></tr>
</table>
<p/>
<hr width="400"/>
<input type="button" value="리스트"
 onClick="location.href='empMultiActionCont.htm?mode=list'"/>
<input type="button" value="정보변경"
 onClick="location.href='empMultiActionCont.htm?mode=updateForm&empno=${emp.empno}'"/>
<input type="button" value="정보삭제"
 onClick="deleteConfirm();"/>
<hr width="400"/>
</center>
</body>
</html>


updateForm.jsp
<%@ page language="java" contentType="text/html; charset=EUC-KR"
    pageEncoding="EUC-KR"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=EUC-KR">
<title>사원정보 변경 폼</title>
<style>
 table{border: 2px double black; }
 th{ text-align: right; }
 td{ text-align: left; }
 .btn { text-align: center; }
</style>
</head>
<body><br/><br/><center>
사원정보 수정 폼<p/>
<form action="empMultiActionCont.htm" method="post">
 <input type="hidden" name="mode" value="update"/>
 <input type="hidden" name="empno" value="${emp.empno}" />
<table border="1" cellspacing="0" width="300" height="150" rules="none" cellpadding="5">
 <tr><th>이름</th><td> ${emp.ename}</td></tr>
 <tr><th>사번</th><td> ${emp.empno}</td></tr>
 <tr><th>부서</th><td> <input type="text" name="deptno" value="${emp.deptno}"/></td></tr>
 <tr><th>급여</th><td> <input type="text" name="sal" value="${emp.sal}"/></td></tr>
 <tr><td> </td><td> </td></tr>
 <tr><td colspan="2" class="btn">
  <input type="submit" value="저 장"/>
  <input type="reset" value="취 소"/>
  </td></tr>
</table>
</form>
<p/>
<hr width="400"/>
<input type="button" value="리스트"
 onClick="location.href='empMultiActionCont.htm?mode=list'"/>
<hr width="400"/>
</center>
</body>
</html>