이제 Ctrl + F11 로 실행 안하고, 주소창에 주소 적어서 들어갈 것! (서블릿 사용할 때)
Ctrl + F11 로 실행할 시 나중에 문제가 생기기 때문에 이제 이렇게 실행안함
context.xml 복사해오기
이렇게 기본 틀 빼고 다 지우기!
여기에 이제 DB 연동하는 Connection Pool 만들 것!
p.571 - 커넥션풀 설정
p.443 - 커넥션풀 설명
< context.xml >
<?xml version="1.0" encoding="UTF-8"?> <Context> <!-- DBCP 사용을 위한 환경 설정 --> <Resource name="jdbc/MySQL" auth="Container" type="javax.sql.DataSource" username="root" password="1234" driverClassName="com.mysql.jdbc.Driver" factory="org.apache.tomcat.dbcp.dbcp2.BasicDataSourceFactory" url="jdbc:mysql://localhost:3306/jsp_model2" maxActive="500" /> </Context>
대소문자 구분!
name : 나중에 불러올 이름 ( 달라져도 됨 부를 때 잘 적으면 되니까 )
type : 인터페이스
maxActive 는 지금 우리가 가상으로 사용하기 때문에 500개 설정해도 8개만 반환될 거
======== dbcpTest.jsp
java.sql 패키지
javax.naming
다운캐스팅 안해서 오류
오류 사라짐!
javax.sql
# tip.
context.xml 에 root / 1234 를 적어놓으면 전부 노출됨 (또 아이디나 비밀번호가 바뀌면 서버 재시작 해야하기때문) 그래서 별로 좋지 않은 방법!
Properties 객체로 만드는 방법이나
이렇게 username, password 를 따로 적는 칸이 있다!
⇒ 실무에선 이렇게 쓰는게 좋다
< dbcpTest.jsp >
<%@pageimport="javax.sql.DataSource"%> <%@pageimport="javax.naming.InitialContext"%> <%@pageimport="javax.naming.Context"%> <%@pageimport="java.sql.Connection"%> <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <% Connection con = null; try { // -------------- DBCP 사용을 위한 설정 ---------------- // context.xml 의 <Context> 태그 설정을 가져오기 Context initCtx = new InitialContext(); // context.xml 의 <Context> 태그 내의 <Resource> 태그 부분 가져오기 Context envCtx = (Context)initCtx.lookup("java:comp/env"); /* Context 타입으로 다운캐스팅 */ // ============================ 여기까지는 바뀔 일 없음! // context.xml 의 JNDI(name 속성) 가져오기 DataSource ds = (DataSource)envCtx.lookup("jdbc/MySQL"); /* DataSource 타입으로 다운캐스팅 */ // DataSource 객체의 getConnection() 메서드를 호출하여 Connection 객체 가져오기 con = ds.getConnection(); out.println("<h1>DBCP 연결 성공!</h1>"); } catch(Exception e) { out.println("<h1>DBCP 연결 실패!</h1>"); e.printStackTrace(); } %>
p.580 - FrontController
======== TestFrontController.java
바로 상속 받는 방법
jsp 는 웹페이지만 새로고침 하면 되지만 java 파일이 바뀌면 Server 재시작 해줘야함
Ctrl + Alt + R (재시작 단축키) ← 톰캣 누르고 단축키 누르기
지금은 404 에러 뜸
어노테이션 추가!
> 서버 재시작 하기!
재시작 해보면 이제 404 에러는 안뜸!
콘솔창에 syso 도 잘 나옴!
< TestFrontController.java >
import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; // 서블릿 클래스는 반드시 javax.servlet.http.HttpServlet 클래스를 상속받아 정의 // 서블릿 주소 요청을 감지하기 위해 클래스 선언부 위에 // @@WebServlet 어노테이션을 사용하여 "*.XXX" 형태의 문자열을 전달하면 // 요청 URL 주소에 XXX 형태로 끝나는 요청은 모두 서블릿 주소로 간주하여 // 현재 컨트롤러로 요청을 전달하게 됨 // ex) "*.bo" 문자열 전달 시 주소창에 XXXX.bo 로 끝나는 요청을 모두 서블릿 요청으로 처리함 @WebServlet("*.bo") publicclass TestFrontController extends HttpServlet { // HttpServlet 클래스를 상속받은 서블릿 클래스에서는 // HTTP 요청 방식 메서드(GET/POST)에 따라 자동으로 호출되는 // doGet(), doPost() 메서드 오버라이딩 하여 각 요청에 따른 처리 작업 기술해야함 // => GET/POST 방식 모두 처리할 작업이 동일하므로 두 메서드를 별도로 작성하지 않고 // 하나의 메서드로 통합하여 처리하기 위해 doProcess() 메서드를 정의하고 공통적으로 호출 protectedvoid doProcess(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException { // POST 방식에서 한글 깨짐 문제 해결을 위해 인코딩 방식 UTF-8 설정 System.out.println("TestFrontController"); request.setCharacterEncoding("UTF-8"); String servletPath = request.getServletPath(); System.out.println("요청주소 : " + servletPath); } @Override protectedvoid doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException { // 공통 작업을 처리하는 doProcess() 메서드를 호출하여 request, response 객체 전달 doProcess(request, response); } @Override protectedvoid doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException { // 공통 작업을 처리하는 doProcess() 메서드를 호출하여 request, response 객체 전달 doProcess(request, response); } }
요청 주소까지 받아올 수 있다!
< 새 프로젝트 만들었을 때 다시 설정하는 방법 >
======== Test2 웹프로젝트 만들기
context.xml
/Test 만 쓰면 이거 하나만 불러오는 거! (특정 url만 불러오기)
보통 main 만 불러올 때 이런식으로 씀! 잘 쓸 일 없다!
p.60
p.581
Test 프로젝트에서
< TestFrontController.java >
추가
출력창
requestURI : 입력한 주소
contextPath : 프로젝트 명
command : contextPath.length() ⇐ 5! 그래서 /Test/test.bo 여기의 인덱스 5번인 / 부터 test.do 까지 subString 으로 추출
⇒ 근데 이제 이 세개 쓸 일은 없고 request.getServletPath(); 이거 씀!
package db; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import javax.naming.Context; import javax.naming.InitialContext; import javax.naming.NamingException; import javax.sql.DataSource; publicclassjdbcUtil { // DB 관련 기본 기능(연결, 자원반환, commit, rollback 등)을 담당하는 클래스 // 1. DBCP 기능을 활용한 Connection 객체 가져오는 메서드 getConnection() 정의 public Connection getConnection() { // DBCP 로부터 전달받은 // Connection 객체를 저장할 변수 선언 Connection con = null; try { // -------------- DBCP 사용을 위한 설정 ---------------- // context.xml 의 <Context> 태그 설정을 가져오기 Context initCtx = new InitialContext(); // context.xml 의 <Context> 태그 내의 // <Resource> 태그 부분 가져오기 Context envCtx = (Context)initCtx.lookup("java:comp/env"); /*Context 타입으로 다운캐스팅*/ // ============================ 여기까지는 바뀔 일 없음! // context.xml 의 JNDI(name 속성) 가져오기 DataSource ds = (DataSource)envCtx.lookup("jdbc/MySQL");/* DataSource 타입으로 다운캐스팅 */ // DataSource 객체의 getConnection() 메서드를 // 호출하여 Connection 객체 가져오기 con = ds.getConnection(); // DB 작업에 대한 Auto Commit 기능 해제 con.setAutoCommit(false); // 기본값은 true(=Auto Commit 활성화) } catch (Exception e) { e.printStackTrace(); } return con; // Connection 객체 리턴 } // 메서드 오버로딩을 활용하여 // Connection, PreparedStatement, ResultSet 객체 반환 publicvoidclose(Connection con) { try { con.close(); } catch (SQLException e) { e.printStackTrace(); } } publicvoidclose(PreparedStatement pstmt) { try { pstmt.close(); } catch (SQLException e) { e.printStackTrace(); } } publicvoidclose(ResultSet rs) { try { rs.close(); } catch (SQLException e) { e.printStackTrace(); } } // Auto Commit 해제로 인해 Commit, Rollback 기능을 수행하는 // 각각의 메서드 정의 publicvoidcommit(Connection con) { try { con.commit(); } catch (SQLException e) { e.printStackTrace(); } } publicvoidrollback(Connection con) { try { con.rollback(); } catch (SQLException e) { e.printStackTrace(); } } }
Connection 에서 이 작업이 이루어졌기 때문에
여기서 Connection 을 받아오는 것!
======== vo (value object)패키지에서 ActionForward.java 클래스 만들기
우리 사용했던 자바빈 처럼 뭔가를 담아놓는 패키지!
575p
< ActionForward.java >
package vo; publicclassActionForward { /* * 서블릿에서 클라이언트로부터 요청을 받아 처리 후 * View 페이지로 포워딩 할 때 * 이동할 View 페이지의 URL(주소)와 * 포워딩 방식(Dispatch or Redirect)을 다루기 위한 클래스 */ private String path; // 포워딩 할 View 페이지의 URL 을 저장할 변수 privateboolean redirect; // 포워딩 방식을 저장할 변수 // (true : Redirect, false : Dispatch) public String getPath() { return path; } publicvoidsetPath(String path) { this.path = path; } publicbooleanisRedirect() { return redirect; } publicvoidsetRedirect(boolean redirect) { this.redirect = redirect; } }
143
> Test 프로젝트로 이동
test.jsp 복사해서 Test 프로젝트에 Dispatcher_test.jsp / Redirect_test.jsp 만들기
if(command.equals("/InputTest.test")) { String id = request.getParameter("id"); System.out.println("id : " + id); Testtest = new Test(); test.test(request, response); } elseif(command.equals("/DispatcherTest.test")) { // Dispatcher 방식으로 포워딩 // (주소표시줄 변경 X, request 객체가 공유됨) // => request 객체의 getRequestDispatcher() 메서드를 // 호출하여 포워딩 할 페이지 전달 // => RequestDispatcher 객체가 리턴됨 RequestDispatcher dispatcher = request.getRequestDispatcher("dispatcher_result.jsp"); // => RequestDispatcher 객체의 forward() 메서드를 // 호출하여 request, response 객체 전달 dispatcher.forward(request, response); // 두 객체를 가지고 지정된 페이지로 포워딩 수행 } elseif(command.equals("/RedirectTest.test")) { // Redirect 방식으로 포워딩 // (주소표시줄 변경 O, request 객체가 공유되지 않음) // => response 객체의 sendRedirect() 메서드를 호출하여 // 포워딩 할 페이지 전달 response.sendRedirect("redirect_result.jsp"); // 지정된 페이지로 포워딩 }
if 문에 else if 문 추가!
javax.servlet
======== dispatcher_result.jsp / redirect_result.jsp 만들기
request 파라미터 : <%=request.getParameter("id") %>
각 jsp 파일에 body 에 한 줄 추가!
> dispatcher_test.jsp 실행
실행창
admin 입력 후 이동
admin 값 가져옴
요청한 주소가 유지
> redirect_test.jsp 실행
똑같이 admin 입력 후 이동
.test 가 아닌 redirect_result.jsp 창이 나옴! id 값도 null 값 뜸!
요청한 주소(.test)가 아닌 이동하는 페이지(redirect_result.jsp)로 바뀜
⇒ 둘의 차이점은 1) 주소창 2) 아이디값
> 다시 MVC_Board 프로젝트로 돌아가기
< BoardFrontController.java >
protectedvoiddoProcess(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // POST 방식 한글 처리 request.setCharacterEncoding("UTF-8"); // 서블릿 주소 가져오기 String command = request.getServletPath(); // "BoardList.bo" 와 "BoardWriteProAction.bo" 주소 판별 if(command.equals("/BoardList.bo")) { // BoardList.bo 서블릿 주소가 요청되면 // BoardListAction 클래스의 인스턴스를 생성하여 // 글목록 가져오기 작업을 수행하기 위해 // 메서드를 호출하여 작업 처리 BoardListAction action = new BoardListAction(); action.getList(); } elseif (command.equals("/BoardWritePro.bo")) { // BoardWritePro.bo 서블릿 주소가 요청되면 // BoardWriteProAction 클래스의 인스턴스를 생성하여 // 입력받은 글쓰기 폼 내용을 저장하는 작업을 수행하기 위해 // 메서드 호출 BoardWriteProAction action = new BoardWriteProAction(); action.write(); } }
지금은 if 문(else~ if문) 안에 저렇게 길게 적는데 나중에는 interface를 implements 해서 쓸 거! 그럼 코드 간편해진다
574
action 패키지에서
======== BoardListAction.java / BoardWriteProAction.java 클래스 만들기
일단 각 getList() 메서드와 write() 메서드 만들어두기 (나중에 지울 거!)
다시 다 지우고
action 패키지에서
======== Action.java (인터페이스로 만들기)
package action; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import vo.ActionForward; publicinterfaceAction { /* * - 서블릿 요청이 들어올 때 각 요청에 따른 다른 클래스들의 객체를 생성하여 * 요청을 처리해야하는 데, 이 때 공통 부모인 Action 인터페이스를 정의하여 * 추상메서드를 각 Action 클래스에서 구현하도록 강제하면 * 다형성을 통해 하나의 Action 인터페이스 타입으로 * Action 클래스를 관리할 수 있음 * - 각 요청을 받아들일 execute() 메서드를 통해 * request, response 객체를 전달받고 * 이동할 URL과 포워딩 방식이 저장된 ActionForward타입 객체를 리턴하도록 함 */ public ActionForward execute(HttpServletRequest request, HttpServletResponse response) throws Exception; }
// if문을 사용하여 서블릿주소 판별 및 각 요청처리를 위한 작업요청 if(command.equals("/BoardWriteForm.bo")) { // 글쓰기 페이지 요청은 비즈니스 로직이 없는 // View 페이지(JSP)로 바로 연결 수행 // ⇒ ActionForward 객체의 포워딩 방식을 // 별도로 설정하지 않음(기본값 false : Dispatcher) // 주소 변경없음! forward = new ActionForward(); //forward.setRedirect(false); // 포워딩 방식을 Dispatcher 방식으로 설정 // (기본값이라 생략가능) forward.setPath("/board/qna_board_write.jsp"); // 이동할 View 페이지 경로 지정 } elseif(command.equals("/BoardWritePro.bo")) { }
if 문 변경!
요청한 서블릿 주소 (프로젝트명/서블릿주소)
jsp 파일에서 Ctrl+F11 로 실행했을 때 창
프로젝트명/폴더명/파일명
그래서 Ctrl+F11 로 실행하면 안됨! (주소가 달라지기 때문!)
< main.jsp >
<h2><a href="BoardWriteForm.bo">글쓰기 페이지</a></h2>
body 에 추가
> 실행해보기
글쓰기 페이지 눌러보기
주소창 확인
⇒ 여기까지가 Dispatcher 방식
======== action 패키지에서 BoardWriteProAction.java 만들기