※ DTO는 Model-1 사용
※ 기존 DAO에서 catch 제거 (throws를 써서 에러 떠넘기기)
📃UserinfoModelTwoDAO.java
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; } }
※ xyz.itwill.service 패키지 생성
※ UserinfoService.java 생성📌Service 클래스
: 모델(Model) 클래스의 요청 처리 메소드에게 데이터베이스 관련 처리 기능을 제공하기 위한 클래스 - 단위 프로그램(모듈 프로그램) : 컴퍼넌트(Component)
→ 다수의 DAO 클래스의 메소드를 호출하여 필요한 기능을 제공하기 위한 메소드 작성 - 모듈화
→ 데이터베이스 관련 기능 구현시 발생되는 모든 문제에 대한 인위적 예외 발생📃UserinfoService
package xyz.itwill.service; // import java.sql.SQLException; import java.util.List; // import xyz.itwill.dao.UserinfoModelTwoDAO; import xyz.itwill.dto.UserinfoDTO; import xyz.itwill.exception.AuthFailException; import xyz.itwill.exception.ExistsUserinfoException; import xyz.itwill.exception.UserinfoNotFoundException; // //Service 클래스 : 모델(Model) 클래스의 요청 처리 메소드에게 데이터베이스 관련 처리 기능을 제공하기 위한 클래스 - 단위 프로그램(모듈 프로그램) : 컴퍼넌트(Component) //→ 다수의 DAO 클래스의 메소드를 호출하여 필요한 기능을 제공하기 위한 메소드 작성 - 모듈화 //→ 데이터베이스 관련 기능 구현시 발생되는 모든 문제에 대한 인위적 예외 발생 public class UserinfoService { private static UserinfoService _servide; // public UserinfoService() { // TODO Auto-generated constructor stub } // static { _servide=new UserinfoService(); } // public static UserinfoService getService() { return _servide; } // //회원정보를 전달받아 USERINFO 테이블에 삽입하는 메소드 //→ 전달받은 회원정보의 아이디가 USERINFO 테이블에 저장된 기존 회원정보의 아이디와 중복될 경우 인위적 예외 발생 public void addUserinfo(UserinfoDTO userinfo) throws SQLException, ExistsUserinfoException { if(UserinfoModelTwoDAO.getDAO().selectUserinfo(userinfo.getUserid())!=null) {//아이디가 중복될 경우 //인위적 예외 발생 → 예외 클래스를 잡는 패키지 생성 xyz.itwill.exception → ExistsUserinfoException.java 생성 //예외가 발생될 경우 아래에 작성된 명령 미실행 throw new ExistsUserinfoException("이미 사용중인 아이디를 등록 하였습니다.");//에러는 떠넘기기 } UserinfoModelTwoDAO.getDAO().insertUserinfo(userinfo);//SQLException 에러는 Model이 처리할거 } // //회원정보를 전달받아 USERINFO 테이블에 저장된 회원정보를 변경하는 메소드 //→ 전달받은 회원정보가 USERINFO 테이블에 없는 경우 인위적 예외 발생 public void modifyUserinfo(UserinfoDTO userinfo) throws SQLException, UserinfoNotFoundException { if(UserinfoModelTwoDAO.getDAO().selectUserinfo(userinfo.getUserid())==null) {//검색된 회원이 없다면 //인위적 예외 발생 → 예외 클래스를 잡는 패키지 xyz.itwill.exception → UserinfoNotFoundException.java 생성 throw new UserinfoNotFoundException("회원정보가 존재하지 않습니다.");//에러는 떠넘기기 } UserinfoModelTwoDAO.getDAO().updateUserinfo(userinfo);//SQL SQLException 떠넘기기 } // //아이디를 전달받아 USERINFO 테이블에 저장된 해당 아이디의 회원정보를 삭제하는 메소드 //→ 전달받은 아이디의 회원정보가 USERINFO 테이블에 없는 경우 인위적 예외 발생 public void removeUserinfo(String userid) throws SQLException ,UserinfoNotFoundException { if(UserinfoModelTwoDAO.getDAO().selectUserinfo(userid)==null) { throw new UserinfoNotFoundException("회원정보가 존재하지 않습니다.");//에러는 떠넘기기 } UserinfoModelTwoDAO.getDAO().deleteUserinfo(userid); } // //아이디를 전달받아 USERINFO 테이블에 저장된 해당 아이디의 회원정보를 검색하여 반환하는 메소드 //→ 전달받은 아이디의 회원정보가 USERINFO 테이블에 없는 경우 인위적 예외 발생 public UserinfoDTO getUserinfo(String userid) throws SQLException ,UserinfoNotFoundException { if(UserinfoModelTwoDAO.getDAO().selectUserinfo(userid)==null) { throw new UserinfoNotFoundException("회원정보가 존재하지 않습니다.");//에러는 떠넘기기 } return UserinfoModelTwoDAO.getDAO().selectUserinfo(userid); } // //USERINFO 테이블에 저장된 모든 회원정보를 검색하여 반환하는 메소드 public List<UserinfoDTO> getUserinfoList() throws SQLException { return UserinfoModelTwoDAO.getDAO().selectUserinfoList(); } // //아이디와 비밀번호를 전달받아 인증 처리하는 메소드 //→ 인증 실패시 인위적 예외 발생 - 예외가 발생되지 않은 경우 인증 성공 public void auth(String userid, String password) throws SQLException ,AuthFailException { UserinfoDTO userinfo=UserinfoModelTwoDAO.getDAO().selectUserinfo(userid); if(userinfo==null) {//아이디 인증 실패 → 예외 클래스를 잡는 패키지 생성 xyz.itwill.exception → AuthFailException.java 생성 throw new AuthFailException("입력된 아이디가 존재하지 않습니다."); } if(!userinfo.getPassword().equals(password)) {//비밀번호 인증 실패 throw new AuthFailException("입력된 아이디가 잘못 되었거나 비밀번호가 맞지 않습니다."); } } }
※ xyz.itwill.exception 패키지 생성
📢회원정보(아이디)가 중복될 경우 발생될 예외를 표현하기 위한 클래스
→ 예외 클래스는 반드시 Exception 클래스를 상속받아 작성
📃ExistsUserinfoException.java
package xyz.itwill.exception; // //회원정보(아이디)가 중복될 경우 발생될 예외를 표현하기 위한 클래스 //→ 예외 클래스는 반드시 Exception 클래스를 상속받아 작성 public class ExistsUserinfoException extends Exception {//serialVersionUID 만들어서 에러 제거 private static final long serialVersionUID = 1L; // public ExistsUserinfoException() { // TODO Auto-generated constructor stub } // public ExistsUserinfoException(String message) { super(message); } }
📢회원정보를 찾을 수 없을 경우 발생될 예외를 표현하기 위한 클래스
📃UserinfoNotFoundException.java
package xyz.itwill.exception; // //회원정보를 찾을 수 없을 경우 발생될 예외를 표현하기 위한 클래스 public class UserinfoNotFoundException extends Exception { private static final long serialVersionUID = 1L; // public UserinfoNotFoundException() { // TODO Auto-generated constructor stub } // public UserinfoNotFoundException(String message) { super(message); } }
📢인증에 실패한 경우 발생될 예외를 표현하기 위한 클래스
📃AuthFailException.java
package xyz.itwill.exception; // //인증에 실패한 경우 발생될 예외를 표현하기 위한 클래스 public class AuthFailException extends Exception { private static final long serialVersionUID = 1L; // public AuthFailException() { // TODO Auto-generated constructor stub } // public AuthFailException(String message) { super(message); } }
※ xyz.itwill.mvc 패키지 생성
※ ControllerServlet.java 생성📌컨트롤러(Controller - Servlet)
: 클라이언트의 모든 요청을 받아 모델(Model - Class)의 요청 처리 메소드를 호출하여 요청을 처리하고 처리 결과를 뷰(View - JSP)로 전달받아 응답되도록 제어하는 웹프로그램
📃ControllerServlet.java
package xyz.itwill.mvc; // import java.io.FileInputStream; import java.io.IOException; import java.util.HashMap; import java.util.Map; import java.util.Properties; // import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; //컨트롤러(Controller - Servlet) : 클라이언트의 모든 요청을 모델(Model - Class)의 요청 처리 메소드를 //호출하여 요청을 처리하고 처리결과를 뷰(View - JSP)로 전달하여 응답되도록 제어하는 웹프로그램 // //1.클라이언트의 모든 요청을 받을 수 있도록 서블릿을 설정하여 단일 진입점의 기능 구현 // → Front Controller Pattern //@WebServlet("URL") : 서블릿 클래스를 웹프로그램(서블릿)으로 등록하고 요청 URL 주소를 매핑하는 어노테이션 //→ 매핑 설정될 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>(); // /* //properties 파일 생성해서 저장 //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()); } } }
📃web.xml
<?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>
※xyz.itwill.mvc 패키지에 Action.java 인터페이스 생성
📢모든 모델 역활의 클래스가 반드시 상속받아야 되는 인터페이스
→ 모델 클래스의 요청 처리 메소드에 대한 작성 규칙 제공
→ 컨트롤러 역활의 서블릿에서 모델 객체로 요청 처리 메소드를 쉽게 호출할 수 있으며 유지보수의 효율성 증가📢요청 처리 메소드를 추상 메소드로(명령이 없는 메소드) 선언
→ 인터페이스를 상속받은 모든 자식클래스에서 반드시 추상 메소드를 오버라이드 선언
→ HttpServletReqest 객체와 HttpServletResponse 객체를 매개변수 전달받아 요청 처리하고 뷰 관련 정보를 ActionForward 객체로 반환하도록 작성
※(클라이언트의 요청을 처리하기위해서는 request,response가 무조건 필요)
→ 요청 처리 메소드에서 발생되는 ServletException과 IOException는 예외 전달📃Action.java
package xyz.itwill.mvc;import java.io.IOException; // import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; // //모든 모델 역활의 클래스가 반드시 상속받아야 되는 인터페이스 //→ 모델 클래스의 요청 처리 메소드에 대한 작성 규칙 제공 //→ 컨트롤러 역활의 서블릿에서 모델 객체로 요청 처리 메소드를 쉽게 호출할 수 있으며 유지보수의 효율성 증가 //요청 처리 메소드를 추상 메소드로(명령이 없는 메소드) 선언 //→ 인터페이스를 상속받은 모든 자식클래스에서 반드시 추상 메소드를 오버라이드 선언 //→ HttpServletReqest 객체와 HttpServletResponse 객체를 매개변수 전달받아 요청 처리하고 뷰 관련 정보를 ActionForward 객체로 반환하도록 작성 //(클라이언트의 요청을 처리하기위해서는 request,response가 무조건 필요) //→ 요청 처리 메소드에서 발생되는 ServletException과 IOException는 예외 전달 public interface Action { ActionForward execute(HttpServletRequest request, HttpServletResponse response)//ActionForward 클래스를 만들어야지 에러가 안생김 throws ServletException,IOException; }
📢응답 관련 정보(뷰 - View)를 저장하기 위한 클래스
📃ActionForward.java
package xyz.itwill.mvc; // //응답 관련 정보(뷰 - View)를 저장하기 위한 클래스 public class ActionForward { //이동 형식에 대한 정보를 저장하기 위한 필드 //→ false : 리다이렉트 이동, true : 포워드 이동 //리다이렉트 이동 : 클라이언트에게 요청 URL 주소(/XXX.do)를 전달하여 다시 요청하도록 응답 처리 //→ 클라이언트 브라우저의 요청 URL 주소 변경 //포워드 이동 : 서블릿(컨트롤러)에서 JSP(뷰)로 스레드를 이동하여 응답 처리 //→ 클라이언트 브라우저의 요청 URL 주소 미변경 private boolean forward;//필드 생성 // //이동될 웹프로그램의 경로를 저장하기 위한 필드 //→ 리다이렉트 이동 : /XXX.do, 포워드 이동 : /XXX.jsp private String path;//필드 생성 // public ActionForward() { // TODO Auto-generated constructor stub } 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; } }
※ xyz.itwill.mvc 패키지에 ErrorModel.java 클래스 생성
📢클라이언트가 [/error.do]로 요청한 경우 실행될 모델 클래스
→ [user_error.jsp]로 포워드 이동하기 위한 정보가 저장된 ActionForward 객체를 반환
📃ErrorModel.java
package xyz.itwill.mvc; // import java.io.IOException; // import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; // //클라이언트가 [/error.do]로 요청한 경우 실행될 모델 클래스 //→ [user_error.jsp]로 포워드 이동하기 위한 정보가 저장된 ActionForward 객체를 반환 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; } }
📃user_error.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%-- 에러메세지를 전달하는 JSP 문서 --%> <%-- → [로그인 페이지 이동] 태그를 클릭한 경우 로그인 정보 입력페이지(loginForm.do)로 이동 --%> <!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>
※ xyz.itwill.mvc 패키지에 LoginFormModel.java 클래스 생성
📢클라이언트가 [/loginForm.do]로 요청한 경우 실행될 모델 클래스
→ [user_login.jsp]로 포워드 이동하기 위한 정보가 저장된 ActionForward 객체 반환
📃LoginFormModel.java
package xyz.itwill.mvc; // import java.io.IOException; // import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; // //클라이언트가 [/loginForm.do]로 요청한 경우 실행될 모델 클래스 //→ [user_login.jsp]로 포워드 이동하기 위한 정보가 저장된 ActionForward 객체 반환 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 문서
→[로그인] 태그를 클릭한 경우 로그인 처리페이지(/login.do)로 이동 - 입력값 전달
📢로그인 사용자인 경우 환영메세지를 전달하는 JSP 문서
→ [회원목록] 태그를 클릭한 경우 회원목록 출력페이지(/list.do)로 이동
→ [로그아웃] 태그를 클릭한 경우 로그아웃 처리페이지(/logout.do)로 이동
→ [회원등록] 태그를 클릭한 경우 회원정보 입력페이지(/writeForm.do)로 이동 - 관리자에게만 적용📃user_login.jsp
<%@page import="xyz.itwill.dto.UserinfoDTO"%> <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%-- 비로그인 사용자인 경우 사용자로부터 로그인정보를 입력받기 위한 JSP 문서 --%> <%-- →[로그인] 태그를 클릭한 경우 로그인 처리페이지(/login.do)로 이동 - 입력값 전달 --%> <%-- 로그인 사용자인 경우 환영메세지를 전달하는 JSP 문서 --%> <%-- → [회원목록] 태그를 클릭한 경우 회원목록 출력페이지(/list.do)로 이동 --%> <%-- → [로그아웃] 태그를 클릭한 경우 로그아웃 처리페이지(/logout.do)로 이동 --%> <%-- → [회원등록] 태그를 클릭한 경우 회원정보 입력페이지(/writeForm.do)로 이동 - 관리자에게만 적용 --%> <% UserinfoDTO loginUserinfo=(UserinfoDTO)session.getAttribute("loginUserinfo"); // String message=(String)request.getAttribute("message"); if(message==null) { message=""; } // String userid=(String)session.getAttribute("userid"); if(userid==null) { userid=""; } %> <!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="<%=request.getContextPath() %>/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> <% if(loginUserinfo==null) {//비로그인 사용자인 경우 %> <!-- 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> <% } else {//로그인 사용자인 경우 %> <table border="0" cellpadding="0" cellspacing="1" width="590" bgcolor="BBBBBB"> <tr> <td align=center bgcolor="E6ECDE" height="22"> <%=loginUserinfo.getName() %>님, 환영합니다. </td> </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> <% if(loginUserinfo.getStatus()==9) { %> <button type="button" onclick="location.href='writeForm.do';">회원등록</button> <% } %> </td> </tr> </table> <% } %> </td> </tr> </table> </body> </html>
※ xyz.itwill.mvc 패키지에 LoginModel.java 클래스 생성
📢클라이언트가 [/login.do]로 요청한 경우 실행될 모델 클래스
→ 로그인 정보를 전달받아 USERINFO 테이블에 저장된 회원정보와 비교하여 인증 처리
→ 인증 성공 : 세션에 권한 관련 정보를 저장하고 [loginForm.do]로 리다이렉트 이동하기 위한 정보가 저장된 ActionForward 객체 반환
→ 인증 실패 : : [user_login.jsp]로 포워드 이동하기 위한 정보가 ActionForward 객체 반환📢객체 반환 - 에러메세지와 아이디를 속성값으로 저장하여 JSP 문서에 제공
📃LoginModel.java
package xyz.itwill.mvc; // import java.io.IOException; // import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; // import xyz.itwill.exception.AuthFailException; import xyz.itwill.service.UserinfoService; // //클라이언트가 [/login.do]로 요청한 경우 실행될 모델 클래스 //→ 로그인 정보를 전달받아 USERINFO 테이블에 저장된 회원정보와 비교하여 인증 처리 //→ 인증 성공 : 세션에 권한 관련 정보를 저장하고 [loginForm.do]로 리다이렉트 이동하기 위한 정보가 저장된 ActionForward 객체 반환 //→ 인증 실패 : : [user_login.jsp]로 포워드 이동하기 위한 정보가 ActionForward 객체 반환 //객체 반환 - 에러메세지와 아이디를 속성값으로 저장하여 JSP 문서에 제공 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; } }
※ xyz.itwill.mvc 패키지에 LogoutModel.java 클래스 생성
📢클라이언트가 [/logout.do]로 요청한 경우 실행될 모델 클래스
→ 로그아웃 처리
→ [loginForm.do]로 리다이렉트 이동하기 정보가 저장된 ActionForward 객체 반환📃 LogoutModel.java
package xyz.itwill.mvc; // import java.io.IOException; // import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; // //클라이언트가 [/logout.do]로 요청한 경우 실행될 모델 클래스 // → 로그아웃 처리 // → [loginForm.do]로 리다이렉트 이동하기 정보가 저장된 ActionForward 객체 반환 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; } }
※ xyz.itwill.mvc 패키지에 WriteFormModel.java 클래스 생성
📢클라이언트가 [/writeForm.do]로 요청한 경우 실행될 모델 클래스
→ 관리자만 요청 가능하도록 권한 설정
→ [user_write.jsp]로 포워드 이동하기 위한 정보가 저장된 ActionForward 객체 반환📃 WriteFormModel.java
package xyz.itwill.mvc; // import java.io.IOException; // import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; // import xyz.itwill.dto.UserinfoDTO; // //클라이언트가 [/writeForm.do]로 요청한 경우 실행될 모델 클래스 // => 관리자만 요청 가능하도록 권한 설정 // => [user_write.jsp]로 포워드 이동하기 정보가 저장된 ActionForward 객체 반환 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; } }
📌사용자로부터 회원정보를 입력받기 위한 JSP 문서 - 관리자만 요청 가능한 페이지
→ [회원등록] 태그를 클릭한 경우 회원정보 삽입페이지(write.do)로 이동 - 입력값 전달
→ [로그인] 태그를 클릭한 경우 로그인정보 입력페이지(loginForm.do)로 이동📃user_write.jsp
<%@page import="xyz.itwill.dto.UserinfoDTO"%> <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%-- 사용자로부터 회원정보를 입력받기 위한 JSP 문서 - 관리자만 요청 가능한 페이지 --%> <%-- → [회원등록] 태그를 클릭한 경우 회원정보 삽입페이지(write.do)로 이동 - 입력값 전달 --%> <%-- → [로그인] 태그를 클릭한 경우 로그인정보 입력페이지(loginForm.do)로 이동 --%> <% String message=(String)request.getAttribute("message"); if(message==null) { message=""; } // UserinfoDTO userinfo=(UserinfoDTO)request.getAttribute("userinfo"); if(userinfo==null) { userinfo=new UserinfoDTO(); userinfo.setUserid(""); userinfo.setPassword(""); userinfo.setName(""); userinfo.setEmail(""); userinfo.setStatus(1); } %> <!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="<%=request.getContextPath() %>/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.getUserid()%>"> </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.getPassword()%>"> </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.getName()%>"> </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.getEmail()%>"> </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" <% if(userinfo.getStatus()==1) { %> selected <% } %>>일반회원</option> <option value="9" <% if(userinfo.getStatus()==9) { %> selected <% } %>>관리자</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]로 요청한 경우 실행될 모델 클래스
→ 회원정보를 전달받아 USERINFO 테이블에 삽입 처리
→ [loginForm.do]로 리다이렉트 이동하기 위한 정보가 저장된 ActionForward 객체 반환📃WriteModel.java
package xyz.itwill.mvc; // import java.io.IOException; // import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; // import xyz.itwill.dto.UserinfoDTO; import xyz.itwill.exception.ExistsUserinfoException; import xyz.itwill.service.UserinfoService; // //클라이언트가 [write.do]로 요청한 경우 실행될 모델 클래스 //→ 회원정보를 전달받아 USERINFO 테이블에 삽입 처리 //→ [loginForm.do]로 리다이렉트 이동하기 위한 정보가 저장된 ActionForward 객체 반환 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);//try 밖에다가 변수 선언해야 에러 안뜸 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]로 요청한 경우 실행될 모델 클래스
→ 로그인 사용자만 요청 가능하도록 권한 설정
→ USERINFO 테이블에 저장된 모든 회원정보를 검색하여 request 속성값으로 저장
→ [user_list.jsp]로 포워드 이동하기 위한 정보가 저장된 ActionForward 객체 반환📃ListModel.java
package xyz.itwill.mvc; // import java.io.IOException; // import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; // import xyz.itwill.dto.UserinfoDTO; import xyz.itwill.service.UserinfoService; //클라이언트가 [list.do]로 요청한 경우 실행될 모델 클래스 //→ 로그인 사용자만 요청 가능하도록 권한 설정 //→ USERINFO 테이블에 저장된 모든 회원정보를 검색하여 request 속성값으로 저장 //→ [user_list.jsp]로 포워드 이동하기 위한 정보가 저장된 ActionForward 객체 반환 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 문서
→ 회원정보에서 [회원이름]을 클릭한 경우 회원정보 출력페이지(view.do)로 이동 - 아이디 전달
→ [회원등록] 태그를 클릭한 경우 회원정보 입력페이지(writeForm.do)로 이동 - 관리자에게만 제공
→ [로그아웃] 태그를 클릭한 경우 로그아웃 처리페이지(logout.do)로 이동📃user_list.jsp
<%@page import="xyz.itwill.dao.UserinfoModelOneDAO"%> <%@page import="java.util.List"%> <%@page import="xyz.itwill.dto.UserinfoDTO"%> <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%-- request 속성값으로 제공된 회원목록을 전달하는 JSP 문서 --%> <%-- → 회원정보에서 [회원이름]을 클릭한 경우 회원정보 출력페이지(view.do)로 이동 - 아이디 전달 --%> <%-- → [회원등록] 태그를 클릭한 경우 회원정보 입력페이지(writeForm.do)로 이동 - 관리자에게만 제공 --%> <%-- → [로그아웃] 태그를 클릭한 경우 로그아웃 처리페이지(logout.do)로 이동 --%> <% UserinfoDTO loginUserinfo=(UserinfoDTO)session.getAttribute("loginUserinfo"); // List<UserinfoDTO> userinfoList=(List<UserinfoDTO>)request.getAttribute("userinfoList"); %> <!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="<%=request.getContextPath() %>/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> <% for(UserinfoDTO userinfo:userinfoList) { %> <tr> <td width=190 align=center bgcolor="ffffff" height="20"> <%=userinfo.getUserid() %> </td> <td width=200 align=center bgcolor="ffffff"> <a href="view.do?userid=<%=userinfo.getUserid() %>" class="user"> <%=userinfo.getName() %> </a> </td> <td width=200 align=center bgcolor="ffffff"> <% if(userinfo.getEmail()!=null) { %> <%=userinfo.getEmail() %> <% } %> </td> </tr> <% } %> </table> <br> <table border="0" cellpadding="0" cellspacing="1" width="590"> <tr> <td align="right"> <% if(loginUserinfo.getStatus()==9) { %> <input type="button" value="회원등록" onclick="location.href='writeForm.do';"/> <% } %> <input type="button" value="로그아웃" onclick="location.href='logout.do';"/> </td> </tr> </table> </td> </tr> </table> </body> </html>
📢클라이언트가 [/view.do]로 요청한 경우 실행될 모델 클래스
→ 로그인 사용자만 요청 가능하도록 권한 설정
→ 아이디를 전달받아 USERINFO 테이블에 저장된 해당 아이디의 회원정보를 검색하여 request 속성값으로 저장
→ [user_view.jsp]로 포워드 이동하기 정보가 저장된 ActionForward 객체 반환📃ViewModel.java
package xyz.itwill.mvc; // import java.io.IOException; // import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; // import xyz.itwill.dto.UserinfoDTO; import xyz.itwill.service.UserinfoService; // //클라이언트가 [/view.do]로 요청한 경우 실행될 모델 클래스 //→ 로그인 사용자만 요청 가능하도록 권한 설정 //→ 아이디를 전달받아 USERINFO 테이블에 저장된 해당 아이디의 회원정보를 검색하여 request 속성값으로 저장 //→ [user_view.jsp]로 포워드 이동하기 정보가 저장된 ActionForward 객체 반환 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 문서
→ [수정] 태그를 클릭한 경우 변경회원정보 입력페이지(modifyForm.do)로 이동 - 아이디 전달
→ [삭제] 태그를 클릭한 경우 회원정보 삭제페이지(remove.do)로 이동 - 아이디 전달
→ [목록] 태그를 클릭한 경우 회원목록 출력페이지(list.do)로 이동
→ [수정] 태그와 [삭제] 태그는 관리자에게만 제공📃user_view.jsp
<%@page import="xyz.itwill.dto.UserinfoDTO"%> <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%-- request 속성값으로 제공된 회원정보를 전달하는 JSP 문서 --%> <%-- → [수정] 태그를 클릭한 경우 변경회원정보 입력페이지(modifyForm.do)로 이동 - 아이디 전달 --%> <%-- → [삭제] 태그를 클릭한 경우 회원정보 삭제페이지(remove.do)로 이동 - 아이디 전달 --%> <%-- → [목록] 태그를 클릭한 경우 회원목록 출력페이지(list.do)로 이동 --%> <%-- → [수정] 태그와 [삭제] 태그는 관리자에게만 제공 --%> <% UserinfoDTO loginUserinfo=(UserinfoDTO)session.getAttribute("loginUserinfo"); // UserinfoDTO userinfo=(UserinfoDTO)request.getAttribute("userinfo"); %> <!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="<%=request.getContextPath() %>/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.getUserid() %> </td> </tr> <tr> <td width=100 align=center bgcolor="E6ECDE" height="22">이름</td> <td width=490 bgcolor="ffffff" style="padding-left:10px;"> <%=userinfo.getName() %> </td> </tr> <tr> <td width=100 align=center bgcolor="E6ECDE" height="22">이메일</td> <td width=490 bgcolor="ffffff" style="padding-left:10px;"> <% if(userinfo.getEmail()!=null) { %> <%=userinfo.getEmail() %> <% } %> </td> </tr> </table> <br> <table width=590 border=0 cellpadding=0 cellspacing=0> <tr> <td align=center> <% if(loginUserinfo.getStatus()==9) { %> <input type="button" value="수정" onClick="location.href='modifyForm.do?userid=<%=userinfo.getUserid()%>';"> <input type="button" value="삭제" onClick="userRemove('<%=userinfo.getUserid()%>');"> <% } %> <input type="button" value="목록" onClick="location.href='list.do';"> </td> </tr> </table> </td> </tr> </table> </body> </html>
📌클라이언트가 [/modifyForm.do]로 요청한 경우 실행될 모델 클래스
→ 관리자만 요청 가능하도록 권한 설정
→ 아이디를 전달받아 USERINFO 테이블에 저장된 해당 아이디의 회원정보를 검색하여 request 속성값으로 저장
→ [user_modify.jsp]로 포워드 이동하기 정보가 저장된 ActionForward 객체 반환📃ModifyFormModel.java
package xyz.itwill.mvc; // import java.io.IOException; // import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; // import xyz.itwill.dto.UserinfoDTO; import xyz.itwill.service.UserinfoService; // //클라이언트가 [/modifyForm.do]로 요청한 경우 실행될 모델 클래스 //→ 관리자만 요청 가능하도록 권한 설정 //→ 아이디를 전달받아 USERINFO 테이블에 저장된 해당 아이디의 회원정보를 검색하여 request 속성값으로 저장 //→ [user_modify.jsp]로 포워드 이동하기 정보가 저장된 ActionForward 객체 반환 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; } }
📢request 속성값으로 제공된 회원정보를 입력태그의 초기값으로 설정하고 변경할 회원정보를 사용자로부터 입력받기 위한 JSP 문서
→ [수정] 태그를 클릭한 경우 회원정보 변경페이지(modify.do)로 이동 - 입력값 전달
→ [목록] 태그를 클릭한 경우 회원목록 출력페이지(list.do)로 이동📃user_modify.jsp
<%@page import="xyz.itwill.dao.UserinfoModelOneDAO"%> <%@page import="xyz.itwill.dto.UserinfoDTO"%> <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%-- request 속성값으로 제공된 회원정보를 입력태그의 초기값으로 설정하고 변경할 회원정보를 사용자로부터 입력받기 위한 JSP 문서 --%> <%-- → [수정] 태그를 클릭한 경우 회원정보 변경페이지(modify.do)로 이동 - 입력값 전달 --%> <%-- → [목록] 태그를 클릭한 경우 회원목록 출력페이지(list.do)로 이동 --%> <% UserinfoDTO userinfo=(UserinfoDTO)request.getAttribute("userinfo"); %> <!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="<%=request.getContextPath() %>/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.getUserid()%>"> <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.getUserid()%> </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.getName()%>"> </td> </tr> <tr> <td width=100 align=center bgcolor="E6ECDE" height="22">이메일 주소</td> <td width=490 bgcolor="ffffff" style="padding-left:10px;"> <% if(userinfo.getEmail()!=null) { %> <input type="text" style="width:240" name="email" value="<%=userinfo.getEmail()%>"> <% } else { %> <input type="text" style="width:240" name="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" <% if(userinfo.getStatus()==1) { %> selected <% } %>>일반회원</option> <option value="9" <% if(userinfo.getStatus()==9) { %> selected <% } %>>관리자</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]로 요청한 경우 실행될 모델 클래스
→ 회원정보를 전달받아 USERINFO 테이블에 저장된 회원정보 변경 처리
→ [view.do]로 리다이렉트 이동하기 위한 정보가 저장된 ActionForward 객체 반환 - 아이디 전달📃ModifyModel.java
package xyz.itwill.mvc; // import java.io.IOException; // import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; // import xyz.itwill.dto.UserinfoDTO; import xyz.itwill.service.UserinfoService; //클라이언트가 [/modify.do]로 요청한 경우 실행될 모델 클래스 //→ 회원정보를 전달받아 USERINFO 테이블에 저장된 회원정보 변경 처리 //→ [view.do]로 리다이렉트 이동하기 위한 정보가 저장된 ActionForward 객체 반환 - 아이디 전달 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]로 요청한 경우 실행될 모델 클래스
→ 관리자만 요청 가능하도록 권한 설정
→ 아이디를 전달받아 USERINFO 테이블에 저장된 해당 아이디의 회원정보 삭제 처리
→ [list.do]로 리다이렉트 이동하기 위한 정보가 저장된 ActionForward 객체 반환
→ 관리자가 자신 계정의 회원정보를 삭제한 경우 [logout.do]로 리다이렉트 이동하기 위한 정보가 저장된 ActionForward 객체 반환📃RemoveModel.java
package xyz.itwill.mvc; // import java.io.IOException; // import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; // import xyz.itwill.dto.UserinfoDTO; import xyz.itwill.service.UserinfoService; // //클라이언트가 [/remove.do]로 요청한 경우 실행될 모델 클래스 //→ 관리자만 요청 가능하도록 권한 설정 //→ 아이디를 전달받아 USERINFO 테이블에 저장된 해당 아이디의 회원정보 삭제 처리 //→ [list.do]로 리다이렉트 이동하기 위한 정보가 저장된 ActionForward 객체 반환 //→ 관리자가 자신 계정의 회원정보를 삭제한 경우 [logout.do]로 리다이렉트 이동하기 위한 정보가 저장된 ActionForward 객체 반환 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; } }
※ControllerServlet.java 수정
※web.xml 수정
⭕properties 파일 만드는법
1. WEB-INF 우클릭 → New → File
2. File name : model.properties 작성 후 Finish
📃model.properties
#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