본문 바로가기

카테고리 없음

MultiActionController example

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>