controller 역할하는 서블릿(모든 요청)
model 역할하는 클래스(model을 통해 요청에 대한 처리 구현)
package xyz.itwill.dto;
public class UserinfoDTO {
private String userid;
private String password;
private String name;
private String email;
private int status;
public UserinfoDTO() {
// TODO Auto-generated constructor stub
}
public String getUserid() {
return userid;
}
public void setUserid(String userid) {
this.userid = userid;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public int getStatus() {
return status;
}
public void setStatus(int status) {
this.status = status;
}
}
dao클래스에서 catch 대신에 throws SQLException으로 처리
dao, service, module 에서 모두 예외 처리 시 비효율 → dao, service는 throws로 떠넘긴후 module에서 예외처리 한번에 처리
package xyz.itwill.dao;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import xyz.itwill.dto.UserinfoDTO;
public class UserinfoModelTwoDAO extends JdbcDAO {
private static UserinfoModelTwoDAO _dao;
private UserinfoModelTwoDAO() {
// TODO Auto-generated constructor stub
}
static {
_dao=new UserinfoModelTwoDAO();
}
public static UserinfoModelTwoDAO getDAO() {
return _dao;
}
public int insertUserinfo(UserinfoDTO userinfo) throws SQLException {
Connection con=null;
PreparedStatement pstmt=null;
int rows=0;
try {
con=getConnection();
String sql="insert into userinfo values(?,?,?,?,?)";
pstmt=con.prepareStatement(sql);
pstmt.setString(1, userinfo.getUserid());
pstmt.setString(2, userinfo.getPassword());
pstmt.setString(3, userinfo.getName());
pstmt.setString(4, userinfo.getEmail());
pstmt.setInt(5, userinfo.getStatus());
rows=pstmt.executeUpdate();
} finally {
close(con, pstmt);
}
return rows;
}
public int updateUserinfo(UserinfoDTO userinfo) throws SQLException {
Connection con=null;
PreparedStatement pstmt=null;
int rows=0;
try {
con=getConnection();
String sql="update userinfo set password=?,name=?,email=?,status=? where userid=?";
pstmt=con.prepareStatement(sql);
pstmt.setString(1, userinfo.getPassword());
pstmt.setString(2, userinfo.getName());
pstmt.setString(3, userinfo.getEmail());
pstmt.setInt(4, userinfo.getStatus());
pstmt.setString(5, userinfo.getUserid());
rows=pstmt.executeUpdate();
} finally {
close(con, pstmt);
}
return rows;
}
public int deleteUserinfo(String userid) throws SQLException {
Connection con=null;
PreparedStatement pstmt=null;
int rows=0;
try {
con=getConnection();
String sql="delete from userinfo where userid=?";
pstmt=con.prepareStatement(sql);
pstmt.setString(1, userid);
rows=pstmt.executeUpdate();
} finally {
close(con, pstmt);
}
return rows;
}
public UserinfoDTO selectUserinfo(String userid) throws SQLException {
Connection con=null;
PreparedStatement pstmt=null;
ResultSet rs=null;
UserinfoDTO userinfo=null;
try {
con=getConnection();
String sql="select * from userinfo where userid=?";
pstmt=con.prepareStatement(sql);
pstmt.setString(1, userid);
rs=pstmt.executeQuery();
if(rs.next()) {
userinfo=new UserinfoDTO();
userinfo.setUserid(rs.getString("userid"));
userinfo.setPassword(rs.getString("password"));
userinfo.setName(rs.getString("name"));
userinfo.setEmail(rs.getString("email"));
userinfo.setStatus(rs.getInt("status"));
}
} finally {
close(con, pstmt, rs);
}
return userinfo;
}
public List<UserinfoDTO> selectUserinfoList() throws SQLException {
Connection con=null;
PreparedStatement pstmt=null;
ResultSet rs=null;
List<UserinfoDTO> userinfoList=new ArrayList<>();
try {
con=getConnection();
String sql="select * from userinfo order by userid";
pstmt=con.prepareStatement(sql);
rs=pstmt.executeQuery();
while(rs.next()) {
UserinfoDTO userinfo=new UserinfoDTO();
userinfo.setUserid(rs.getString("userid"));
userinfo.setPassword(rs.getString("password"));
userinfo.setName(rs.getString("name"));
userinfo.setEmail(rs.getString("email"));
userinfo.setStatus(rs.getInt("status"));
userinfoList.add(userinfo);
}
} finally {
close(con, pstmt, rs);
}
return userinfoList;
}
}
Service 클래스 : 모델(Model) 클래스의 요청 처리 메소드에게 데이타베이스 관련 처리 기능을 제공하기 위한 클래스
다수의 DAO 클래스의 메소드를 호출하여 필요한 기능을 제공하기 위한 메소드 작성 (모듈화)
데이타베이스 관련 기능 구현시 발생되는 모든 문제에 대한 인위적 예외 발생
싱글톤 디자인 패턴 적용
회원정보를 전달받아 USERINFO 테이블에 삽입하는 메소드
회원정보를 전달받아 USERINFO 테이블에 저장된 회원정보를 변경하는 메소드
아이디를 전달받아 USERINFO 테이블에 저장된 해당 아이디의 회원정보를 삭제하는 메소드
아이디를 전달받아 USERINFO 테이블에 저장된 해당 아이디의 회원정보를 검색하여 반환하는 메소드
USERINFO 테이블에 저장된 모든 회원정보를 검색하여 반환하는 메소드
아이디와 비밀번호를 전달받아 인증 처리하는 메소드
package xyz.itwill.service;
public class UserinfoService {
private static UserinfoService _service;
private UserinfoService() {
// TODO Auto-generated constructor stub
}
static {
_service=new UserinfoService();
}
public static UserinfoService getService() {
return _service;
}
//1. 회원정보를 전달받아 USERINFO 테이블에 삽입하는 메소드
// => 전달받은 회원정보의 아이디가 USERINFO 테이블에 저장된 기존 회원정보의 아이디와
//중복될 경우 인위적 예외 발생
public void addUserinfo(UserinfoDTO userinfo) throws SQLException, ExistsUserinfoException {
if(UserinfoModelTwoDAO.getDAO().selectUserinfo(userinfo.getUserid())!=null) {
//예외가 발생될 경우 아래에 작성된 명령 미실행 (예외 객체를 생성하여 인위적인 예외 발생)
throw new ExistsUserinfoException("이미 사용중인 아이디를 입력 하였습니다.");
}
UserinfoModelTwoDAO.getDAO().insertUserinfo(userinfo);
}
//2. 회원정보를 전달받아 USERINFO 테이블에 저장된 회원정보를 변경하는 메소드
// => 전달받은 회원정보가 USERINFO 테이블에 없는 경우 인위적 예외 발생
public void modifyUserinfo(UserinfoDTO userinfo) throws SQLException, UserinfoNotFoundException {
if(UserinfoModelTwoDAO.getDAO().selectUserinfo(userinfo.getUserid())==null) {
throw new UserinfoNotFoundException("회원정보가 존재하지 않습니다.");
}
UserinfoModelTwoDAO.getDAO().updateUserinfo(userinfo);
}
//3. 아이디를 전달받아 USERINFO 테이블에 저장된 해당 아이디의 회원정보를 삭제하는 메소드
// => 전달받은 아이디의 회원정보가 USERINFO 테이블에 없는 경우 인위적 예외 발생
public void removeUserinfo(String userid) throws SQLException, UserinfoNotFoundException {
if(UserinfoModelTwoDAO.getDAO().selectUserinfo(userid)==null) {
throw new UserinfoNotFoundException("회원정보가 존재하지 않습니다.");
}
UserinfoModelTwoDAO.getDAO().deleteUserinfo(userid);
}
//4. 아이디를 전달받아 USERINFO 테이블에 저장된 해당 아이디의 회원정보를 검색하여 반환하는 메소드
// => 전달받은 아이디의 회원정보가 USERINFO 테이블에 없는 경우 인위적 예외 발생
public UserinfoDTO getUserinfo(String userid) throws SQLException, UserinfoNotFoundException {
if(UserinfoModelTwoDAO.getDAO().selectUserinfo(userid)==null) {
throw new UserinfoNotFoundException("회원정보가 존재하지 않습니다.");
}
return UserinfoModelTwoDAO.getDAO().selectUserinfo(userid);
}
//5. USERINFO 테이블에 저장된 모든 회원정보를 검색하여 반환하는 메소드
public List<UserinfoDTO> getUserinfoList() throws SQLException {
return UserinfoModelTwoDAO.getDAO().selectUserinfoList();
}
//6. 아이디와 비밀번호를 전달받아 인증 처리하는 메소드
// => 인증 실패시 인위적 예외 발생 - 예외가 발생되지 않은 경우 인증 성공
public void auth(String userid, String password) throws SQLException, AuthFailException {
UserinfoDTO userinfo=UserinfoModelTwoDAO.getDAO().selectUserinfo(userid);
if(userinfo==null) {//아이디 인증 실패
throw new AuthFailException("입력된 아이디가 존재하지 않습니다.");
}
if(!userinfo.getPassword().equals(password)) {//비밀번호 인증 실패
throw new AuthFailException("입력된 아이디가 잘못 되었거나 비밀번호가 맞지 않습니다.");
}
}
}
회원정보(아이디)가 중복될 경우 발생될 예외를 표현하기 위한 클래스
package xyz.itwill.exception;
public class ExistsUserinfoException extends Exception {
private static final long serialVersionUID = 1L;
//객체 직렬화
public ExistsUserinfoException() { } //기본 생성자
public ExistsUserinfoException(String message) {
super(message);
}
}
package xyz.itwill.exception;
public class UserinfoNotFoundException extends Exception {
private static final long serialVersionUID = 1L;
public UserinfoNotFoundException() { }
public UserinfoNotFoundException(String message) {
super(message);
}
}
package xyz.itwill.exception;
public class AuthFailException extends Exception {
private static final long serialVersionUID = 1L;
public AuthFailException() { }
public AuthFailException(String message) {
super(message);
}
}
- 클라이언트의 모든 요청을 받을 수 있도록 서블릿을 설정하여 단일 진입점의 기능 구현
- Front Controller Pattern
- @WebServlet("URL") : 서블릿 클래스를 웹프로그램(서블릿)으로 등록하고 요청 URL 주소를 매핑하는 어노테이션
- 매핑 설정될 URL 주소에 패턴문자(* : 전체 또는 ? : 문자 하나)를 사용하여 URL 패턴 등록 가능
- @WebServlet("*.do") : 클라이언트가 [XXX.do] 형식의 URL 주소로 요청한 경우 서블릿 실행
- @WebServlet 어노테이션 대신 [web.xml] 파일에서 서블릿 클래스를 웹프로그램(서블릿)으로 등록하고 URL 주소 매핑 처리 (권장)
- 클라이언트 요청 분석 : 요청 URL 주소 이용 - http://localhost:8000/mvc/XXX.do
- HttpServletRequest.getRequestURI() : 요청 URL 주소에서 URI 주소를 반환하는 메소드
String requestURI=request.getRequestURI();//requestURI = /mvc/XXX.do
- HttpServletRequest.getContextPath() : 요청 URL 주소에서 컨텍스트 경로를 반환하는 메소드
String contextPath=request.getContextPath();//contextPath = /mvc
- 클라이언트 요청에 대한 요청값을 반환받아 저장
String command=requestURI.substring(contextPath.length());//command = /XXX.do
- 클라이언트 요청을 모델(Model)을 사용하여 처리하고 뷰(View) 관련 정보를 반환받아 저장
- 모델 역할의 Java 클래스로 객체를 생성하여 요청 처리 메소드 호출
- 하나의 요청에 대해 하나의 모델이 처리되도록 설정 (Command Controller Pattern)
- 회원관리 프로그램에서 클라이언트 요청에 대한 모델 객체가 매핑되도록 설계
- => 로그인정보 입력페이지(환영메세지 출력페이지) - /loginForm.do >> LoginFormModel Class
- => 로그인 처리페이지 - /login.do >> LoginModel Class
- => 로그아웃 처리페이지 - /logout.do >> LogoutModel Class
- => 회원정보 입력페이지 - /writeForm.do >> WriteFormModel Class
- => 회원정보 삽입페이지 - /write.do >> WriteModel Class
- => 회원목록 출력페이지 - /list.do >> ListModel Class
- => 회원정보 출력페이지 - /view.do >> ViewModel Class
- => 변경회원정보 입력페이지 - /modifyForm.do >> ModifyFormModel Class
- => 회원정보 변경페이지 - /modify.do >> ModifyModel Class
- => 회원정보 삭제페이지 - /remove.do >> RemoveModel Class
- => 에러메세지 출력페이지 - /error.do >> ErrorModel Class
Action action=null;
if(command.equals("/loginForm.do")) {
action=new LoginFormModel();
} else if(command.equals("/login.do")) {
action=new LoginModel();
} else {//요청에 대한 모델 클래스가 없는 경우
action=new ErrorModel();
}
ActionForward actionForward=action.execute(request, response);
- 응답 관련 정보가 저장된 ActionForward 객체를 이용하여 응답 처리
- request.getRequestDispatcher(String url) : URL 주소가 저장된 RequestDispatcher 객체를 반환하는 메소드
- RequestDispatcher 객체 : 다른 웹프로그램으로 스레드를 이동하기 위한 기능을 제공하는 객체
- RequestDispatcher.forward(request, response) : 요청 웹프로그램에서 다른 웹프로그램으로 스레드를 이동시켜 응답처리하기 위한 메소드 (포워드 이동)
- 요청 웹프로그램의 request 객체와 response 객체를 스레드가 이동되는 웹프로그램으로 전달
if(actionForward.isForward()) {//ActionForward 객체의 forward 필드값이 [true]인 경우 - 포워드 이동 //컨트롤러에서 뷰(XXX.jsp)로 스레드를 이동하여 JSP 문서의 실행결과(HTML 문서)를 클라이언트에게 전달하여 응답 request.getRequestDispatcher(actionForward.getPath()).forward(request, response); } else {//ActionForward 객체의 forward 필드값이 [false]인 경우 - 라다이렉트 이동 //컨트롤러에서 클라이언트에게 요청 URL 주소(XXX.do)를 전달하여 재요청하도록 응답 response.sendRedirect(actionForward.getPath()); }
if문 이용 → 가독성 감소(많은 시간 소요)
Map 객체 이용 → 유지보수 효율성 감소 (요청 모델을 클래스에 작성시 war파일로 만들어서 웹서버를 실행하면 수정할때마다 controller를 수정하고 이에 따라 수정된 war파일을 다시 다운로드 해야함) → text파일(properties)로 작성
★ properties 파일 이용 ★ → 프로젝트가 바뀌어도 수정할 필요 없음 → 유지보수 효율성 증가
private Map<String, Action> actionMap;
@Override
public void init(ServletConfig config) throws ServletException {
//System.out.println("ControllerServlet 클래스의 init() 메소드 호출");
actionMap=new HashMap<String, Action>();
//Map 객체에 엔트리(Entry - Key : 요청정보, Value : 모델 객체) 추가
actionMap.put("/loginForm.do", new LoginFormModel());
actionMap.put("/login.do", new LoginModel());
actionMap.put("/error.do", new ErrorModel());
}
★ properties 파일 이용 ★
Properties 파일에 요청정보와 모델 클래스를 저장하고 파일을 읽어 Map 객체의 엔트리 추가
유지보수의 효율성 증가 - 컨트롤러를 변경하지 않고 Properties 파일만 변경하여 요청정보와 모델 객체 변경 가능
Properties 파일(XXX.properties) : 프로그램 실행에 필요한 값을 제공하기 위한 텍스트 파일
Properties properties=new Properties();
String configFile=config.getInitParameter("configFile");
: /WEB-INF/model.propertiesString configFilePath=config.getServletContext().getRealPath(configFile);
FileInputStream in=new FileInputStream(configFilePath);
properties.load(in);
for(Object key:properties.keySet()) {
: Set 객체로부터 요소를 하나씩 제공받아 반복 처리String actionCommand=(String)key;
String actionClass=(String)properties.get(key);
모델 클래스를 이용하여 모델 객체 생성 → 리플렉션 기능 사용
Action actionObject=(Action)Class.forName(actionClass).getDeclaredConstructor().newInstance();
actionMap.put(actionCommand, actionObject);
Action action=actionMap.get(command);
package xyz.itwill.mvc;
//1.클라이언트의 모든 요청을 받을 수 있도록 서블릿을 설정하여 단일 진입점의 기능 구현
//@WebServlet("URL") : 서블릿 클래스를 웹프로그램(서블릿)으로 등록하고 요청 URL 주소를 매핑하는 어노테이션
//@WebServlet("*.do") : 클라이언트가 [XXX.do] 형식의 URL 주소로 요청한 경우 서블릿 실행
//@WebServlet 어노테이션 대신 [web.xml] 파일에서 서블릿 클래스를 웹프로그램(서블릿)으로 등록하고 URL 주소 매핑 처리
public class ControllerServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
//요청정보(Key - String)와 모델 객체(Value - Action)를 하나의 요소(Entry)로 묶어 여러개
//저장할 Map 객체의 필드
// => Map 객체를 이용하여 요청정보(Key)로 모델 객체(Value)를 빠르게 제공받기 위해 사용
private Map<String, Action> actionMap;
//클라이언트 최초 요청에 의해 서블릿 객체가 생성된 후 가장 먼저 자동으로 1번만 호출되는 메소드
// => 서블릿 객체의 초기화 작업을 위해 오버라이드 선언
@Override
public void init(ServletConfig config) throws ServletException {
//System.out.println("ControllerServlet 클래스의 init() 메소드 호출");
actionMap=new HashMap<String, Action>();
/*
//Map 객체에 엔트리(Entry - Key : 요청정보, Value : 모델 객체) 추가
actionMap.put("/loginForm.do", new LoginFormModel());
actionMap.put("/login.do", new LoginModel());
actionMap.put("/logout.do", new LogoutModel());
actionMap.put("/writeForm.do", new WriteFormModel());
actionMap.put("/write.do", new WriteModel());
actionMap.put("/list.do", new ListModel());
actionMap.put("/view.do", new ViewModel());
actionMap.put("/modifyForm.do", new ModifyFormModel());
actionMap.put("/modify.do", new ModifyModel());
actionMap.put("/remove.do", new RemoveModel());
actionMap.put("/error.do", new ErrorModel());
*/
//Properties 파일에 요청정보와 모델 클래스를 저장하고 파일을 읽어 Map 객체의 엔트리 추가
// => 유지보수의 효율성 증가 - 컨트롤러를 변경하지 않고 Properties 파일만 변경하여
//요청정보와 모델 객체 변경 가능
//Properties 파일(XXX.properties) : 프로그램 실행에 필요한 값을 제공하기 위한 텍스트 파일
//Properties 파일의 정보를 저장하기 위한 Properties 객체 생성
Properties properties=new Properties();
//ServletConfig.getInitParameter(String name) : [web.xml] 파일에서 init-param
//엘리먼트로 제공되는 값을 읽어와 반환하는 메소드
String configFile=config.getInitParameter("configFile");
//System.out.println("configFile = "+configFile);
//Properties 파일의 시스템 경로를 반환받아 저장
//String configFilePath=config.getServletContext().getRealPath("/WEB-INF/model.propeties");
String configFilePath=config.getServletContext().getRealPath(configFile);
//System.out.println("configFilePath = "+configFilePath);
try {
//Properties 파일에 대한 입력스트림을 생성하여 저장
FileInputStream in=new FileInputStream(configFilePath);
//입력스트림을 사용하여 Properties 파일의 내용을 읽어 Properties 객체에 엔트리로 저장
properties.load(in);
} catch (IOException e) {
e.printStackTrace();
}
//Properties 객체의 모든 키(Key)를 반환받아 반복 처리
//Properties.keySet() : Properties 객체에 저장된 모든 엔트리의 키(Key)를 Set 객체로 반환하는 메소드
for(Object key:properties.keySet()) {//Set 객체로부터 요소를 하나씩 제공받아 반복 처리
//Properties 객체에 저장된 엔트리의 키(Key) - 요청정보
String actionCommand=(String)key;
//Properties 객체에 저장된 엔트리의 값(Value) - 모델 클래스
String actionClass=(String)properties.get(key);
try {
//모델 클래스를 이용하여 모델 객체 생성 - 리플렉션 기능 사용
//리플렉션(Reflection) : 프로그램 실행시 클래스(Clazz)를 읽어 객체를 생성하고
//객체의 필드 또는 메소드에 접근하도록 제공하는 기능
//Class.forName(String className) : 문자열로 표현된 클래스를 전달받아 클래스를
//읽어 메모리에 저장하고 Class 객체(Clazz)를 반환하는 메소드 - ClassNotFoundException 발생
//Class.getDeclaredConstructor() : 메모리에 저장된 클래스(Class 객체)의 생성자가 저장된
//Constructor 객체를 반환하는 메소드
//Constructor.newInstance() : Constructor 객체에 저장된 생성자를 이용하여
//Object 타입의 객체를 생성하여 반환하는 메소드
Action actionObject=(Action)Class
.forName(actionClass).getDeclaredConstructor().newInstance();
//Map 객체에 엔트리(Entry - Key : 요청정보, Value : 모델 객체) 추가
actionMap.put(actionCommand, actionObject);
} catch (Exception e) {
e.printStackTrace();
}
}
}
//클라이언트의 요청을 처리하기 위한 자동 호출되는 메소드
// => 클라이언트가 서블릿(웹프로그램)을 요청할 때마다 서블릿 객체를 이용하여 반복적으로 호출
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//System.out.println("ControllerServlet 클래스의 service() 메소드 호출");
//2.클라이언트 요청 분석 : 요청 URL 주소 이용 - http://localhost:8000/mvc/XXX.do
//HttpServletRequest.getRequestURI() : 요청 URL 주소에서 URI 주소를 반환하는 메소드
String requestURI=request.getRequestURI();
//System.out.println("requestURI = "+requestURI);//requestURI = /mvc/XXX.do
//HttpServletRequest.getContextPath() : 요청 URL 주소에서 컨텍스트 경로를 반환하는 메소드
String contextPath=request.getContextPath();
//System.out.println("contextPath = "+contextPath);//contextPath = /mvc
//클라이언트 요청에 대란 요청값을 반환받아 저장
String command=requestURI.substring(contextPath.length());
//System.out.println("command = "+command);//command = /XXX.do
//3.클라이언트 요청을 모델(Model)을 사용하여 처리하고 뷰(View) 관련 정보를 반환받아 저장
// => 모델 역활의 Java 클래스로 객체를 생성하여 요청 처리 메소드 호출
// => 하나의 요청에 대해 하나의 모델이 처리되도록 설정 - Command Controller Pattern
//회원관리 프로그램에서 클라이언트 요청에 대한 모델 객체가 매핑되도록 설계
// => 로그인정보 입력페이지(환영메세지 출력페이지) - /loginForm.do >> LoginFormModel Class
// => 로그인 처리페이지 - /login.do >> LoginModel Class
// => 로그아웃 처리페이지 - /logout.do >> LogoutModel Class
// => 회원정보 입력페이지 - /writeForm.do >> WriteFormModel Class
// => 회원정보 삽입페이지 - /write.do >> WriteModel Class
// => 회원목록 출력페이지 - /list.do >> ListModel Class
// => 회원정보 출력페이지 - /view.do >> ViewModel Class
// => 변경회원정보 입력페이지 - /modifyForm.do >> ModifyFormModel Class
// => 회원정보 변경페이지 - /modify.do >> ModifyModel Class
// => 회원정보 삭제페이지 - /remove.do >> RemoveModel Class
// => 에러메세지 출력페이지 - /error.do >> ErrorModel Class
/*
//모델 클래스가 상속받은 인터페이스를 이용하여 참조변수 선언
// => 참조변수에는 인터페이스를 상속받은 모든 자식클래스(모델)로 생성된 객체 저장 가능
Action action=null;
if(command.equals("/loginForm.do")) {
action=new LoginFormModel();
} else if(command.equals("/login.do")) {
action=new LoginModel();
} else if(command.equals("/logout.do")) {
action=new LogoutModel();
} else if(command.equals("/writeForm.do")) {
action=new WriteFormModel();
} else if(command.equals("/write.do")) {
action=new WriteModel();
} else if(command.equals("/list.do")) {
action=new ListModel();
} else if(command.equals("/view.do")) {
action=new ViewModel();
} else if(command.equals("/modifyForm.do")) {
action=new ModifyFormModel();
} else if(command.equals("/modify.do")) {
action=new ModifyModel();
} else if(command.equals("/remove.do")) {
action=new RemoveModel();
} else if(command.equals("/error.do")) {
action=new ErrorModel();
} else {//요청에 대한 모델 클래스가 없는 경우
action=new ErrorModel();
}
*/
//Map 객체에 저장된 엔트리에서 요청정보(Key)를 이용하여 모델 객체(Value)를 반환받아 저장
// => 메모리 효율 및 가독성 증가
Action action=actionMap.get(command);
if(action==null) {//참조변수에 요청에 대한 모델 객체가 저장되어 있지 않은 경우
action=actionMap.get("/error.do");
}
//인터페이스 참조변수를 이용하여 추상메소드를 호출하면 참조변수에 저장된 모델 객체에
//오버라이드 선언된 요청 처리 메소드 호출 - 오버라이드에 의한 다형성
// => 요청 처리 메소드에 의해 요청 처리 후 응답 관련 정보가 저장된 ActionForward
//객체를 반환받아 저장
ActionForward actionForward=action.execute(request, response);
//4.응답 관련 정보를 저장된 ActionForward 객체를 이용하여 응답 처리
if(actionForward.isForward()) {//ActionForward 객체의 forward 필드값이 [true]인 경우 - 포워드 이동
//컨트롤러에서 뷰(XXX.jsp)로 스레드를 이동하여 JSP 문서의 실행결과(HTML 문서)를
//클라이언트에게 전달하여 응답
request.getRequestDispatcher(actionForward.getPath()).forward(request, response);
} else {//ActionForward 객체의 forward 필드값이 [false]인 경우 - 라다이렉트 이동
//컨트롤러에서 클라이언트에게 요청 URL 주소(XXX.do)를 전달하여 재요청하도록 응답
response.sendRedirect(actionForward.getPath());
}
}
}
package xyz.itwill.mvc;
public class ControllerServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
private Map<String, Action> actionMap;
@Override//자동으로 1번만 호출되는 init메소드 오버라이드 선언
public void init(ServletConfig config) throws ServletException {
actionMap=new HashMap<String, Action>();
Properties properties=new Properties();
String configFile=config.getInitParameter("configFile");
//[web.xml] 파일에서 init-param 엘리먼트로 제공되는 값 : /WEB-INF/model.properties
String configFilePath=config.getServletContext().getRealPath(configFile);
//Properties 파일의 시스템 경로 : C:\java\apache-tomcat-9.0.68\webapps\mvc\WEB-INF\model.properties
try {
FileInputStream in=new FileInputStream(configFilePath);//파일에 대한 입력스트림
properties.load(in);//Properties 파일을 읽어 Properties 객체에 엔트리로 저장
} catch (IOException e) {
e.printStackTrace();
}
for(Object key:properties.keySet()) {//Set 객체로부터 properties의 키를 하나씩 제공받아 반복 처리
String actionCommand=(String)key;//Properties 객체에 저장된 엔트리의 키 (요청정보)
String actionClass=(String)properties.get(key);//엔트리의 값 (모델 클래스) : just 문자
try {
Action actionObject=(Action)Class.forName(actionClass).getDeclaredConstructor().newInstance();
//모델 클래스를 이용하여 Object 타입의 모델 객체 생성 (리플렉션 이용)
actionMap.put(actionCommand, actionObject);
//Map 객체에 엔트리(Entry - Key : 요청정보, Value : 모델 객체) 추가
} catch (Exception e) {
e.printStackTrace();
}
}
}
//클라이언트의 요청을 처리하기 위해 자동 호출되는 service메소드 오버라이드 (요청할때마다 반복 호출)
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String requestURI=request.getRequestURI();//요청URI 주소(/mvc/XXX.do)
String contextPath=request.getContextPath();//컨텍스트 경로 (/mvc)
String command=requestURI.substring(contextPath.length());//client 요청값(/XXX.do)
Action action=actionMap.get(command);
//Map 객체에 저장된 엔트리에서 요청정보(Key:.do)를 이용하여 모델 객체(Value:model class)를 반환받아 저장
//model 객체 클래스의 메소드 호출 (하나의 요청에 대해 하나의 모델 처리)
if(action==null) {//참조변수에 요청에 대한 모델 객체가 저장되어 있지 않은 경우
action=actionMap.get("/error.do");
}
ActionForward actionForward=action.execute(request, response);
//모델 클래스에서 오버라이드 선언된 요청 처리 메소드 호출
if(actionForward.isForward()) {//ActionForward 객체를 이용하여 응답 처리
request.getRequestDispatcher(actionForward.getPath()).forward(request, response);
//ActionForward 객체의 forward 필드값이 [true]인 경우 - 포워드(스레드) 이동
} else {//ActionForward 객체의 forward 필드값이 [false]인 경우 - 라다이렉트 이동
response.sendRedirect(actionForward.getPath());
//[false]인 경우 - 라다이렉트(client에게 요청 URL 주소(XXX.do)를 전달하여 재요청) 이동
}
}
}
#Command(Key - String) = ModelClass(Value - String)
/loginForm.do = xyz.itwill.mvc.LoginFormModel
/login.do = xyz.itwill.mvc.LoginModel
/logout.do = xyz.itwill.mvc.LogoutModel
/writeForm.do = xyz.itwill.mvc.WriteFormModel
/write.do = xyz.itwill.mvc.WriteModel
/list.do = xyz.itwill.mvc.ListModel
/view.do = xyz.itwill.mvc.ViewModel
/modifyForm.do = xyz.itwill.mvc.ModifyFormModel
/modify.do = xyz.itwill.mvc.ModifyModel
/remove.do = xyz.itwill.mvc.RemoveModel
/error.do = xyz.itwill.mvc.ErrorModel
web.xml : 현재 프로젝트가 WAS 프로그램에 의해 웹자원(WebContext)로 변형될 때 필요한 정보를 제공하기 위한 환경설정파일
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" id="WebApp_ID" version="4.0">
<display-name>mvc</display-name>
<!-- servlet : 서블릿 클래스를 웹프로그램(서블릿)으로 등록하기 위한 엘리먼트 -->
<servlet>
<servlet-name>controller</servlet-name>
<servlet-class>xyz.itwill.mvc.ControllerServlet</servlet-class>
<!-- init-param : 서블릿 클래스에 필요한 값을 제공하기 위한 엘리먼트 -->
<init-param>
<param-name>configFile</param-name>
<param-value>/WEB-INF/model.properties</param-value>
</init-param>
<!-- load-on-startup : WAS 실행시 서블릿 클래스를 서블릿 객체로 생성하기 위한 엘리먼트 -->
<!-- => 클라이언트의 요청 없이 WAS 실행시 서블릿 객체를 미리 생성 - init() 메소드가 자동 호출되어 초기화 작업 -->
<!-- => 엘리먼트값은 0 이상의 정수값으로 설정하며 정수값이 작을수록 먼저 서블릿 객체로 생성 -->
<load-on-startup>1</load-on-startup>
</servlet>
<!-- servlet-mapping : 웹프로그램(서블릿)에 URL 패턴을 등록하기 위한 엘리먼트 -->
<servlet-mapping>
<servlet-name>controller</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.jsp</welcome-file>
<welcome-file>default.htm</welcome-file>
</welcome-file-list>
</web-app>
응답 관련 정보(뷰 - View)를 저장하기 위한 클래스
이동 형식에 대한 정보를 저장하기 위한 필드
private boolean forward;
private String path;
package xyz.itwill.mvc;
public class ActionForward {
private boolean forward;
//이동될 웹프로그램의 경로를 저장하기 위한 필드
// => 리다이렉트 이동 : /XXX.do, 포워드 이동 : /XXX.jsp
private String path;
public ActionForward() { } //기본생성자
public boolean isForward() {
return forward;
}
public void setForward(boolean forward) {
this.forward = forward;
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
}
모든 모델 역할의 클래스가 반드시 상속받아야 되는 인터페이스 (모델클래스가 공통으로 가지고 있어야하는 메소드)
인터페이스에는 요청 처리 메소드를 추상 메소드로 선언
요청 처리 메소드는 HttpServletRequest 객체와 HttpServletResponse 객체를 매개변수로 전달받아 요청 처리하고 뷰 관련 정보를 ActionForward 객체로 반환하도록 작성
요청 처리 메소드에서 발생되는 ServletException과 IOException는 예외 전달
package xyz.itwill.mvc;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public interface Action {
ActionForward execute(HttpServletRequest request, HttpServletResponse response)
throws ServletException,IOException;
}
package xyz.itwill.mvc;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class LoginFormModel implements Action {
@Override
public ActionForward execute(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
ActionForward actionForward=new ActionForward();
actionForward.setForward(true);
actionForward.setPath("/model_two/user_login.jsp");
return actionForward;
}
}
비로그인 사용자인 경우
로그인 사용자인 경우 (환영메세지를 전달하는 JSP 문서)
요청 웹프로그램(컨트롤러)의 URL 주소 경로와 응답 JSP 문서의 경로가 서로 다르므로 웹자원의 경로는 절대경로로 표현하는 것을 권장
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>MVC</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<%-- 요청 웹프로그램(컨트롤러)의 URL 주소 경로와 응답 JSP 문서의 경로가 서로 다르므로
웹자원의 경로는 절대경로로 표현하는 것을 권장 --%>
<%-- <link rel=stylesheet href="${pageContext.request.contextPath }/model_two/css/user.css" type="text/css"> --%>
<link rel=stylesheet href="<c:url value="/model_two/css/user.css"/>" type="text/css">
<script language="JavaScript">
function userLogin() {
if ( f.userid.value == "" ) {
alert("아이디를 입력하십시요.");
f.userid.focus();
return;
}
if ( f.password.value == "" ) {
alert("비밀번호를 입력하십시요.");
f.password.focus();
return;
}
f.action = "login.do";
f.submit();
}
</script>
</head>
<body bgcolor=#FFFFFF text=#000000 leftmargin=0 topmargin=0 marginwidth=0 marginheight=0>
<br>
<table width=780 border=0 cellpadding=0 cellspacing=0>
<tr>
<td width="20"></td>
<td style="color: red;">${message }</td>
</tr>
<tr>
<td width="20"></td>
<td>
<!--contents-->
<table width=590 border=0 cellpadding=0 cellspacing=0>
<tr>
<td bgcolor="f4f4f4" height="22"> <b>회원관리 - 로그인</b></td>
</tr>
</table>
<br>
<c:choose>
<c:when test="${empty(loginUserinfo) }"><%-- 비로그인 사용자인 경우 --%>
<!-- login Form -->
<form name="f" method="post">
<table border="0" cellpadding="0" cellspacing="1" width="590" bgcolor="BBBBBB">
<tr>
<td width=100 align=center bgcolor="E6ECDE" height="22">사용자 아이디</td>
<td width=490 bgcolor="ffffff" style="padding-left:10px;">
<input type="text" style="width:150" name="userid" value="${userid }">
</td>
</tr>
<tr>
<td width=100 align=center bgcolor="E6ECDE" height="22">비밀번호</td>
<td width=490 bgcolor="ffffff" style="padding-left:10px;">
<input type="password" style="width:150" name="password">
</td>
</tr>
</table>
</form>
<br>
<table width=590 border=0 cellpadding=0 cellspacing=0>
<tr>
<td align=center>
<input type="button" value="로그인" onClick="userLogin();">
</td>
</tr>
</table>
</c:when>
<c:otherwise><%-- 로그인 사용자인 경우 --%>
<table border="0" cellpadding="0" cellspacing="1" width="590" bgcolor="BBBBBB">
<tr>
<td align=center bgcolor="E6ECDE" height="22">
${loginUserinfo.name }님, 환영합니다.
</td>
</tr>
</table>
<br>
<table width=590 border=0 cellpadding=0 cellspacing=0>
<tr>
<td align=center>
<button type="button" onclick="location.href='list.do';">회원목록</button>
<button type="button" onclick="location.href='logout.do';">로그아웃</button>
<c:if test="${loginUserinfo.status == 9 }">
<button type="button" onclick="location.href='writeForm.do';">회원등록</button>
</c:if>
</td>
</tr>
</table>
</c:otherwise>
</c:choose>
</td>
</tr>
</table>
</body>
</html>
클라이언트가 [/login.do]로 요청한 경우 실행될 모델 클래스
로그인정보를 전달받아 USERINFO 테이블에 저장된 회원정보와 비교하여 인증 처리
HttpSession session=request.getSession();
package xyz.itwill.mvc;
public class LoginModel implements Action {
@Override
public ActionForward execute(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
ActionForward actionForward=new ActionForward();
//요청을 처리하면서 발생되는 모든 예외를 처리하기 위한 예외처리 기능 구현
try {
if(request.getMethod().equals("GET")) {//비정상적인 요청인 경우
throw new Exception();//인위적 예외 발생
}
//전달값을 반환받아 저장
String userid=request.getParameter("userid");
String password=request.getParameter("password");
//모델 클래스의 요청 처리 메소드에서는 Service 객체로 메소드를 호출하여
//데이타베이스 관련된 작업이 처리되도록 작성
//UserinfoService 클래스의 auth() 메소드를 호출하여 인증 처리
// => AuthFailException이 발생된 경우 인증 실패
UserinfoService.getService().auth(userid, password);
//인증이 성공된 경우 세션에 권한 관련 정보(회원정보) 저장
// => 세션 바인딩하여 HttpSession 객체를 반환받아 저장
HttpSession session=request.getSession();
//Session Scope : 동일한 세션을 사용하는 모든 웹프로그램에서 속성값을 반환받아 사용 가능
// => 웹브라우저가 종료되면 클라이언트에 바인딩된 세션은 자동으로 제거
session.setAttribute("loginUserinfo", UserinfoService.getService().getUserinfo(userid));
actionForward.setForward(false);
actionForward.setPath("loginForm.do");
} catch (AuthFailException e) {
//인증 실패에 의해 발생된 예외에 대한 처리 명령 작성
//Request Scope : 스레드가 이동된 웹프로그램(JSP)에서만 속성값을 반환받아 사용 가능
request.setAttribute("message", e.getMessage());
request.setAttribute("userid", request.getParameter("userid"));
actionForward.setForward(true);
actionForward.setPath("/model_two/user_login.jsp");
} catch (Exception e) {
//모든 예외에 대한 처리 명령 작성
// => [error.do]로 리다이렉트 이동하기 위한 정보가 저장된 ActionForward 객체 반환
e.printStackTrace();//서버 콘솔에 에러메세지 출력
actionForward.setForward(false);
actionForward.setPath("error.do");
}
return actionForward;
}
}
클라이언트가 [/logout.do]로 요청한 경우 실행될 모델 클래스
package xyz.itwill.mvc;
public class LogoutModel implements Action {
@Override
public ActionForward execute(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
HttpSession session=request.getSession();
//session.removeAttribute("loginUserinfo");
session.invalidate();
ActionForward actionForward=new ActionForward();
actionForward.setForward(false);
actionForward.setPath("loginForm.do");
return actionForward;
}
}
package xyz.itwill.mvc;
public class ErrorModel implements Action {
@Override
public ActionForward execute(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
ActionForward actionForward=new ActionForward();
actionForward.setForward(true);
actionForward.setPath("/model_two/user_error.jsp");
return actionForward;
}
}
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>MVC</title>
<style type="text/css">
body {
text-align: center;
}
.message {
color: red;
font-size: 1.5em;
}
</style>
</head>
<body>
<h1>에러페이지</h1>
<hr>
<p class="message">프로그램 실행에 예기치 못한 오류가 발생 하였거나 비정상적 방법으로
프로그램을 요청하여 오류가 발생 하였습니다.</p>
<button type="button" onclick="location.href='loginForm.do';">로그인 페이지 이동</button>
</body>
</html>
package xyz.itwill.mvc;
public class WriteFormModel implements Action {
@Override
public ActionForward execute(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
ActionForward actionForward=new ActionForward();
try {
HttpSession session=request.getSession();
UserinfoDTO loginUserinfo=(UserinfoDTO)session.getAttribute("loginUserinfo");
//비로그인 사용자이거나 로그인 사용자가 관리자가 아닌 경우 - 비정상적인 요청
if(loginUserinfo==null || loginUserinfo.getStatus()!=9) {
throw new Exception();
}
actionForward.setForward(true);
actionForward.setPath("/model_two/user_write.jsp");
} catch (Exception e) {
e.printStackTrace();
actionForward.setForward(false);
actionForward.setPath("error.do");
}
return actionForward;
}
}
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>MVC</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link rel=stylesheet href="<c:url value="/model_two/css/user.css"/>" type="text/css">
<script language="JavaScript">
function userCreate() {
if ( f.userid.value == "" ) {
alert("아이디를 입력하십시요.");
f.userid.focus();
return;
}
if ( f.password.value == "" ) {
alert("비밀번호를 입력하십시요.");
f.password.focus();
return;
}
if ( f.name.value == "" ) {
alert("이름을 입력하십시요.");
f.name.focus();
return;
}
f.action = "write.do";
f.submit();
}
</script>
</head>
<body bgcolor=#FFFFFF text=#000000 leftmargin=0 topmargin=0 marginwidth=0 marginheight=0>
<br>
<table width=780 border=0 cellpadding=0 cellspacing=0>
<tr>
<td width="20"></td>
<td style="color: red;">${message }</td>
</tr>
<tr>
<td width="20"></td>
<td>
<table width=590 border=0 cellpadding=0 cellspacing=0>
<tr>
<td bgcolor="f4f4f4" height="22"> <b>회원관리 - 회원등록</b></td>
</tr>
</table>
<br>
<form name="f" method="post">
<table border="0" cellpadding="0" cellspacing="1" width="590" bgcolor="BBBBBB">
<tr>
<td width=100 align=center bgcolor="E6ECDE" height="22">아이디</td>
<td width=490 bgcolor="ffffff" style="padding-left:10px;">
<input type="text" style="width:150" name="userid" value="${userinfo.userid }">
</td>
</tr>
<tr>
<td width=100 align=center bgcolor="E6ECDE" height="22">비밀번호</td>
<td width=490 bgcolor="ffffff" style="padding-left:10px;">
<input type="password" style="width:150" name="password" value="${userinfo.password }">
</td>
</tr>
<tr>
<td width=100 align=center bgcolor="E6ECDE" height="22">이름</td>
<td width=490 bgcolor="ffffff" style="padding-left:10px;">
<input type="text" style="width:240" name="name" value="${userinfo.name }">
</td>
</tr>
<tr>
<td width=100 align=center bgcolor="E6ECDE" height="22">이메일</td>
<td width=490 bgcolor="ffffff" style="padding-left:10px;">
<input type="text" style="width:240" name="email" value="${userinfo.email }">
</td>
</tr>
<tr>
<td width=100 align=center bgcolor="E6ECDE" height="22">회원등급</td>
<td width=490 bgcolor="ffffff" style="padding-left:10px;">
<select name="status">
<option value="1" <c:if test="${userinfo.status == 1 }">selected</c:if>>일반회원</option>
<option value="9" <c:if test="${userinfo.status == 9 }">selected</c:if>>관리자</option>
</select>
</td>
</tr>
</table>
</form>
<br>
<table width=590 border=0 cellpadding=0 cellspacing=0>
<tr>
<td align=center>
<input type="button" value="회원등록" onClick="userCreate();">
<input type="button" value="로그인" onClick="location.href='loginForm.do';">
</td>
</tr>
</table>
</td>
</tr>
</table>
</body>
</html>
클라이언트가 [/write.do]로 요청한 경우 실행될 모델 클래스
package xyz.itwill.mvc;
public class WriteModel implements Action {
@Override
public ActionForward execute(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
ActionForward actionForward=new ActionForward();
UserinfoDTO userinfo=null;
try {
if(request.getMethod().equals("GET")) {
throw new Exception();
}
request.setCharacterEncoding("utf-8");
String userid=request.getParameter("userid");
String password=request.getParameter("password");
String name=request.getParameter("name");
String email=request.getParameter("email");
int status=Integer.parseInt(request.getParameter("status"));
userinfo=new UserinfoDTO();
userinfo.setUserid(userid);
userinfo.setPassword(password);
userinfo.setName(name);
userinfo.setEmail(email);
userinfo.setStatus(status);
//UserinfoService 클래스의 addUserinfo() 메소드 호출
// => 전달받은 아이디가 USERINFO 테이블에 저장된 기존 회원의 아이디와 중복될 경우
//ExistsUserinfoException 발생
UserinfoService.getService().addUserinfo(userinfo);
actionForward.setForward(false);
actionForward.setPath("loginForm.do");
} catch (ExistsUserinfoException e) {
//아이디가 중복될 경우 발생되는 예외에 대한 처리 명령 작성
request.setAttribute("message", e.getMessage());
request.setAttribute("userinfo", userinfo);
actionForward.setForward(true);
actionForward.setPath("/model_two/user_write.jsp");
} catch (Exception e) {
e.printStackTrace();
actionForward.setForward(false);
actionForward.setPath("error.do");
}
return actionForward;
}
}
클라이언트가 [/list.do]로 요청한 경우 실행될 모델 클래스
package xyz.itwill.mvc;
public class ListModel implements Action {
@Override
public ActionForward execute(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
ActionForward actionForward=new ActionForward();
try {
HttpSession session=request.getSession();
UserinfoDTO loginUserinfo=(UserinfoDTO)session.getAttribute("loginUserinfo");
//비로그인 사용자인 경우 - 비정상적인 요청
if(loginUserinfo==null) {
throw new Exception();
}
//UserinfoService 클래스의 getUserinfoList() 메소드를 호출하여 반환된 회원목록을
//포워드 이동될 JSP에서 사용하기 위해 request 속성값으로 저장
request.setAttribute("userinfoList", UserinfoService.getService().getUserinfoList());
actionForward.setForward(true);
actionForward.setPath("/model_two/user_list.jsp");
} catch (Exception e) {
e.printStackTrace();
actionForward.setForward(false);
actionForward.setPath("error.do");
}
return actionForward;
}
}
request 속성값으로 제공된 회원목록을 전달하는 JSP 문서
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>MVC</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link rel=stylesheet href="<c:url value="/model_two/css/user.css"/>" type="text/css">
</head>
<body bgcolor=#FFFFFF text=#000000 leftmargin=0 topmargin=0 marginwidth=0 marginheight=0>
<br>
<table width=780 border=0 cellpadding=0 cellspacing=0>
<tr>
<td width="20"></td>
<td>
<table width=590 border=0 cellpadding=0 cellspacing=0>
<tr>
<td bgcolor="f4f4f4" height="22"> <b>회원관리 - 회원목록</b></td>
</tr>
</table>
<br>
<table border="0" cellpadding="0" cellspacing="1" width="590" bgcolor="BBBBBB">
<tr>
<td width=190 align=center bgcolor="E6ECDE" height="22">아이디</td>
<td width=200 align=center bgcolor="E6ECDE">이름</td>
<td width=200 align=center bgcolor="E6ECDE">이메일</td>
</tr>
<c:forEach var="userinfo" items="${userinfoList }">
<tr>
<td width=190 align=center bgcolor="ffffff" height="20">
${userinfo.userid }
</td>
<td width=200 align=center bgcolor="ffffff">
<a href="view.do?userid=${userinfo.userid }" class="user">
${userinfo.name }
</a>
</td>
<td width=200 align=center bgcolor="ffffff">
${userinfo.email }
</td>
</tr>
</c:forEach>
</table>
<br>
<table border="0" cellpadding="0" cellspacing="1" width="590">
<tr>
<td align="right">
<c:if test="${loginUserinfo.status == 9 }">
<input type="button" value="회원등록" onclick="location.href='writeForm.do';"/>
</c:if>
<input type="button" value="로그아웃" onclick="location.href='logout.do';"/>
</td>
</tr>
</table>
</td>
</tr>
</table>
</body>
</html>
클라이언트가 [/view.do]로 요청한 경우 실행될 모델 클래스
package xyz.itwill.mvc;
public class ViewModel implements Action {
@Override
public ActionForward execute(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
ActionForward actionForward=new ActionForward();
try {
HttpSession session=request.getSession();
UserinfoDTO loginUserinfo=(UserinfoDTO)session.getAttribute("loginUserinfo");
//비로그인 사용자인 경우 - 비정상적인 요청
if(loginUserinfo==null) {
throw new Exception();
}
if(request.getParameter("userid")==null) {
throw new Exception();
}
String userid=request.getParameter("userid");
//UserinfoService 클래스의 getUserinfo() 메소드를 호출하여 반환된 회원정보를
//포워드 이동될 JSP에서 사용하기 위해 request 속성값으로 저장
// => UserinfoService 클래스의 getUserinfo() 메소드에서 해당 아이디의 회원정보가
//검색되지 않은 경우 UserinfoNotFoundException 발생 >> 에러페이지 이동
request.setAttribute("userinfo", UserinfoService.getService().getUserinfo(userid));
actionForward.setForward(true);
actionForward.setPath("/model_two/user_view.jsp");
} catch (Exception e) {
e.printStackTrace();
actionForward.setForward(false);
actionForward.setPath("error.do");
}
return actionForward;
}
}
request 속성값으로 제공된 회원정보를 전달하는 JSP 문서
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>MVC</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link rel=stylesheet href="<c:url value="/model_two/css/user.css"/>" type="text/css">
<script language="JavaScript">
function userRemove(userid) {
if (confirm("정말로 삭제 하시겠습니까?") ) {
location.href='remove.do?userid='+userid;
}
}
</script>
</head>
<body bgcolor=#FFFFFF text=#000000 leftmargin=0 topmargin=0 marginwidth=0 marginheight=0>
<br>
<table width=780 border=0 cellpadding=0 cellspacing=0>
<tr>
<td width="20"></td>
<td>
<table width=590 border=0 cellpadding=0 cellspacing=0>
<tr>
<td bgcolor="f4f4f4" height="22"> <b>회원관리 - 회원정보</b></td>
</tr>
</table>
<br>
<table border="0" cellpadding="0" cellspacing="1" width="590" bgcolor="BBBBBB">
<tr>
<td width=100 align=center bgcolor="E6ECDE" height="22">아이디</td>
<td width=490 bgcolor="ffffff" style="padding-left:10px;">
${userinfo.userid }
</td>
</tr>
<tr>
<td width=100 align=center bgcolor="E6ECDE" height="22">이름</td>
<td width=490 bgcolor="ffffff" style="padding-left:10px;">
${userinfo.name }
</td>
</tr>
<tr>
<td width=100 align=center bgcolor="E6ECDE" height="22">이메일</td>
<td width=490 bgcolor="ffffff" style="padding-left:10px;">
${userinfo.email }
</td>
</tr>
</table>
<br>
<table width=590 border=0 cellpadding=0 cellspacing=0>
<tr>
<td align=center>
<c:if test="${loginUserinfo.status == 9 }">
<input type="button" value="수정" onClick="location.href='modifyForm.do?userid=${userinfo.userid}';">
<input type="button" value="삭제" onClick="userRemove('${userinfo.userid}');">
</c:if>
<input type="button" value="목록" onClick="location.href='list.do';">
</td>
</tr>
</table>
</td>
</tr>
</table>
</body>
</html>
클라이언트가 [/modifyForm.do]로 요청한 경우 실행될 모델 클래스
package xyz.itwill.mvc;
public class ModifyFormModel implements Action {
@Override
public ActionForward execute(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
ActionForward actionForward=new ActionForward();
try {
HttpSession session=request.getSession();
UserinfoDTO loginUserinfo=(UserinfoDTO)session.getAttribute("loginUserinfo");
//비로그인 사용자이거나 로그인 사용자가 관리자가 아닌 경우 - 비정상적인 요청
if(loginUserinfo==null || loginUserinfo.getStatus()!=9) {
throw new Exception();
}
if(request.getParameter("userid")==null) {
throw new Exception();
}
String userid=request.getParameter("userid");
//UserinfoService 클래스의 getUserinfo() 메소드를 호출하여 반환된 회원정보를
//포워드 이동될 JSP에서 사용하기 위해 request 속성값으로 저장
// => UserinfoService 클래스의 getUserinfo() 메소드에서 해당 아이디의 회원정보가
//검색되지 않은 경우 UserinfoNotFoundException 발생 >> 에러페이지 이동
request.setAttribute("userinfo", UserinfoService.getService().getUserinfo(userid));
actionForward.setForward(true);
actionForward.setPath("/model_two/user_modify.jsp");
} catch (Exception e) {
e.printStackTrace();
actionForward.setForward(false);
actionForward.setPath("error.do");
}
return actionForward;
}
}
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>MVC</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link rel=stylesheet href="<c:url value="/model_two/css/user.css"/>" type="text/css">
<script language="JavaScript">
function userModify() {
if ( f.name.value == "" ) {
alert("이름을 입력하십시요.");
f.name.focus();
return false;
}
f.action = "modify.do";
f.submit();
}
</script>
</head>
<body bgcolor=#FFFFFF text=#000000 leftmargin=0 topmargin=0 marginwidth=0 marginheight=0>
<br>
<table width=780 border=0 cellpadding=0 cellspacing=0>
<tr>
<td width="20"></td>
<td>
<table width=590 border=0 cellpadding=0 cellspacing=0>
<tr>
<td bgcolor="f4f4f4" height="22"> <b>회원관리 - 회원정보수정</b></td>
</tr>
</table>
<br>
<form name="f" method="post">
<input type="hidden" name="userid" value="${userinfo.userid }">
<table border="0" cellpadding="0" cellspacing="1" width="590" bgcolor="BBBBBB">
<tr>
<td width=100 align=center bgcolor="E6ECDE" height="22">아이디</td>
<td width=490 bgcolor="ffffff" style="padding-left:10px;">
${userinfo.userid }
</td>
</tr>
<tr>
<td width=100 align=center bgcolor="E6ECDE" height="22">비밀번호</td>
<td width=490 bgcolor="ffffff" style="padding-left:10px;">
<input type="password" style="width:150" name="password">
<span style="color: red;">** 비밀번호를 변경하지 않을 경우 입력하지 마세요. **</span>
</td>
</tr>
<tr>
<td width=100 align=center bgcolor="E6ECDE" height="22">이름</td>
<td width=490 bgcolor="ffffff" style="padding-left:10px;">
<input type="text" style="width:240" name="name" value="${userinfo.name }">
</td>
</tr>
<tr>
<td width=100 align=center bgcolor="E6ECDE" height="22">이메일 주소</td>
<td width=490 bgcolor="ffffff" style="padding-left:10px;">
<input type="text" style="width:240" name="email" value="${userinfo.email }">
</td>
</tr>
<tr>
<td width=100 align=center bgcolor="E6ECDE" height="22">회원등급</td>
<td width=490 bgcolor="ffffff" style="padding-left:10px;">
<select name="status">
<option value="1" <c:if test="${userinfo.status == 1 }">selected</c:if>>일반회원</option>
<option value="9" <c:if test="${userinfo.status == 9 }">selected</c:if>>관리자</option>
</select>
</td>
</tr>
</table>
</form>
<br>
<table width=590 border=0 cellpadding=0 cellspacing=0>
<tr>
<td align=center>
<input type="button" value="수정" onClick="userModify();">
<input type="button" value="목록" onClick="location.href='list.do';">
</td>
</tr>
</table>
</td>
</tr>
</table>
</body>
</html>
클라이언트가 [/modify.do]로 요청한 경우 실행될 모델 클래스
package xyz.itwill.mvc;
public class ModifyModel implements Action {
@Override
public ActionForward execute(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
ActionForward actionForward=new ActionForward();
try {
if(request.getMethod().equals("GET")) {
throw new Exception();
}
request.setCharacterEncoding("utf-8");
String userid=request.getParameter("userid");
String password=request.getParameter("password");
String name=request.getParameter("name");
String email=request.getParameter("email");
int status=Integer.parseInt(request.getParameter("status"));
UserinfoDTO userinfo=new UserinfoDTO();
userinfo.setUserid(userid);
if(password==null || password.equals("")) {
//비밀번호 전달값이 없는 경우 - 기존 회원의 비밀번호 사용
userinfo.setPassword(UserinfoService.getService().getUserinfo(userid).getPassword());
} else {
//비밀번호 전달값이 있는 경우 - 입력된 비밀번호 사용
userinfo.setPassword(password);
}
userinfo.setName(name);
userinfo.setEmail(email);
userinfo.setStatus(status);
//UserinfoService 클래스의 modifyUserinfo() 메소드 호출
UserinfoService.getService().modifyUserinfo(userinfo);
actionForward.setForward(false);
actionForward.setPath("view.do?userid="+userid);
} catch (Exception e) {
e.printStackTrace();
actionForward.setForward(false);
actionForward.setPath("error.do");
}
return actionForward;
}
}
클라이언트가 [/remove.do]로 요청한 경우 실행될 모델 클래스
package xyz.itwill.mvc;
public class RemoveModel implements Action {
@Override
public ActionForward execute(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
ActionForward actionForward=new ActionForward();
try {
HttpSession session=request.getSession();
UserinfoDTO loginUserinfo=(UserinfoDTO)session.getAttribute("loginUserinfo");
//비로그인 사용자이거나 로그인 사용자가 관리자가 아닌 경우 - 비정상적인 요청
if(loginUserinfo==null || loginUserinfo.getStatus()!=9) {
throw new Exception();
}
if(request.getParameter("userid")==null) {
throw new Exception();
}
String userid=request.getParameter("userid");
//UserinfoService 클래스의 removeUserinfo() 메소드 호출
UserinfoService.getService().removeUserinfo(userid);
actionForward.setForward(false);
if(loginUserinfo.getUserid().equals(userid)) {
actionForward.setPath("logout.do");
} else {
actionForward.setPath("list.do");
}
} catch (Exception e) {
e.printStackTrace();
actionForward.setForward(false);
actionForward.setPath("error.do");
}
return actionForward;
}
}