MultiActionController를 이용하여 한개의 Controller클래스에 다수개의 메소드를 선언하고 클라이언트에서 각각의 메소드를 호출하는 예제
MultiActionController를 상속한 클래스에 클라이언트가 호출가능한 메소드를 선언하는 형식
메소드 리턴타입으로 가능한 자료형과 처리되는 형태
2. Map인 경우: new ModelAndView().addAllObjects(map)
3. String인 경우: new ModelAndView(str)
4. void인 경우: null
메소드 파리미터로 사용가능한 자료형
2. 두번째 파라미터: HttpServletResponse
3. 세번째 파라미터: HttpSession 혹은 Command 객체 중 하나
요청 URL에 포함된 파라미터에서 메소드이름을 찾아서 호출하도록 설정하려면 ParameterMethodNameResolver클래스를 bean으로 선언하여 사용할 Controller에 설정해 주어야 한다.
dispatcher-servlet.xml 설정파일
<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의 형태
예를 들어, 아래와 같은 콘트롤러에서 searchByEmpno() 메소드를 호출하려면 다음과 같이 요청한다.
http://localhost/spring256/search.htm?mode=getEmpByEmpno&empno=7369
src/config/jdbc.properties
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
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
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
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>