SQL등의 오류나 사용자가 입력을 제대로 하지 않아 DB로 입력이 실패되는 등 오류가 생겼을 때

 

설정해 놓은 페이지로 연결하고 메세지를 띄울 수 있다.

 

==>  SERVICE 나 DAO 에서 오류가 난 경우 CONTROLLER에서 try catch 하도록 설정하고

 

catch 시 오류 내용을 적어서 request를 통해서 forward 시켜 오류창

 

으로 넘어가도록 한다.

catch (SQLException e) {
	e.printStackTrace();
				
	String errorMessage = "SQL문 장애발생으로 데이터 입력 실패함!!";
    req.setAttribute("errorMessage", errorMessage);
    req.setAttribute("e", e);
    String path = "/WEB-INF/ncstestMember/error.jsp";
    req.getRequestDispatcher(path).forward(req, resp);
  }

[오류페이지 jsp]

 <h1>${requestScope.errorMessage}</h1>
        
        <span class="error-cnotent-title"> 발생한 예외 : ${e}</span>

[ 로그인 시 ]

1. 클라이언트가 ID PW 입력 ->

2. 전달 받은 ID PW를 DB에서 일치 확인 -> service, dao 에서 반환

3. if 결과 ==  o x 

4-1. 일치하는게 존재하면 : 

 Session 객체에 담아서 브라우저 종료시까지 정보가 저장되도록 한다. (활동 없으면 1800초 후 사라지도록 설정)

session.setAttribute("loginMember" , loginMember);
session.setMaxInactiveInterval(1800);

+아이디 저장 체크 시 쿠키를 활용해서 쿠키를 내보내준다.

Cookie cookie = new Cookie("saveId", memberId);

-> saveId라는 Key 와 해당 id를 value로 가지는 Cookie 객체 생성

-> 체크시 쿠키 유효기간을 설정해주고 체크가 없으면 0으로 설정해 쿠키가 사라지게한다.

->쿠키 파일이 사용되어질 경로를 지정한다. (getContextPath == 메인부터 모두에서)

->response 객체에 해당 cookie를 추가해준다.

Cookie cookie = new Cookie("saveId",memberId);

if(req.getParameter("save")!=null) {
	cookie.setMaxAge(60*60*24*30);
}else {
	cookie.setMaxAge(0);
}

cookie.setPath(req.getContextPath());
resp.addCookie(cookie);

resp.sendRedirect(req.getContextPath());

*Servlet에서 응답 화면을 지정하는 방법 두가지.

1) forward : 요청 위임식으로

-- req, resp를 전달해서 화면을 만들게 해준다. (req, resp 유지)

2) redirect : 재요청식

--req와 resp를 삭제하고 다시 생성 / 다른 주소를 재요청한다.

 

4-2. 일치하지 않는다면 alert() 를 띄우고 돌아간다.

 

 

==> 로그인이 완료 된 경우

jsp 파일에서 <c:when> 과 <c:otherwise> 에서

sessionScope.loginMember 가 비어있는지 조건에 따라 test 구문을 넣어 표시 정보를 다르게 할 수 있다.

<c:choose>
    <c:when test="${empty sessionScope.loginMember}"> 
        <li></li>
    </c:when>

    <c:otherwise>
        <li></li>
    </c:otherwise>
 </c:choose>

 

[로그아웃 시]

--> 반대로 session에서 회원 정보를 제거해주면 된다.

//session 객체 얻어오기
HttpSession session = req.getSession();

session.invalidate();

==> session을 통째로 무효화

(session의 로그인 아이디만 삭제도 가능하지만 다른 임시 정보들이 저장된 경우도 있으므로 바람직하지 않다.)

resp.sendRedirect(req.getContextPath());

-->리다이렉트

 

[비밀번호 암호화]

회원가입 같은 경우 비밀번호는 암호화되어 저장될 필요가 있다.

이를 위해 getParameter단계에서 사전에 아예 암호화되도록

Filter를 이용해 암호화된 정보가 getParameter 되도록 오버라이딩을 해준다.

 

1)필터 생성

%%%%%

필터? 클아이언트 요청 시 생성되는 HttpServletRequest, HttpServletResponse

이 두 객체가 요청 응답을 처리하는 Servlet/JSP에 도달하기 전/후 처리를 하는 클래스이다.

필터는 여러 개를 연쇄적으로 연결할 수 있다.(FilterChain)

필터의 생명 주기 : init -> doFilter -> destroy 반복

--> 모두 끝나면 필터의 매핑과 해당 서블릿의 매핑까지 확인한다.

@WebFilter(filterName = "encrypFiter" , urlPatterns = {"적용주소"})
public class EncrypFilter implements Filter{
	public void init(FilterConfig fConfig) throws ServletException {
		
	}
    public void destroy() {
		
	}
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
		//HttpServletRequest, HttpServletResponse의 부모타입으로 매개변수가 선언됨
		//다형성으로 모두 잡아서 필터링 == 부모 부분만 사용 가능 => 다운캐스팅 해서 사용
		HttpServletRequest req= (HttpServletRequest)request;
//		HttpServletResponse resp = (HttpServletResponse)response;
		
		//필터링 확인
		if(req.getMethod().equals("POST")) {
			//POST방식 요청일 경우( 비밀번호 입력이 포함되면 무조건 POST방식 )
			EncryptWrapper encWrapper = new EncryptWrapper(req);
//			req 요청 객체를 EncrytWrapper로 감싸기
//			오버라이딩 사용 가능
			//기존 req 대신 encWrapper를 Servlet으로 전달
			chain.doFilter(encWrapper, response);
		}
		else {
			chain.doFilter(request, response);
			//다음 필터로 요청 응답 전달, 없으면 Servlet/JSP로 전달
		}
}

2) getParameter 오버라이딩

==>HttpServletRequestWrapper : 클라이언트 요청을 감싸서 가공하는 객체

--> 이 객체를 상속받은 클래스를 생성해 오버라이딩을 진행한다.

     HttpServletRequestWrapper는 매개변수 1개짜리 생성자만 존재한다.

이 클래스에서 오버라이딩 해서 getParameter 시 전달받은 name값이 pw인 경우들을 추가해 

일반적인 경우 부모의 방식을 따르고

비밀번호에 해당하는 경우  SHA-512 해쉬함수를 이용한 암호화를 반환한다.

 

public class EncryptWrapper extends HttpServletRequestWrapper {
	
	public EncryptWrapper(HttpServletRequest request) {
		super(request);
	}
	//getParameter() 메소드를 오버라이딩
	@Override
	public String getParameter(String name) {
		//매개변수로 memberPw가 넘어온 경우 암호화를 진행
		//아닌경우 원래 getParameter() 동작을 수행
		String value = null;
		switch(name) {
		case "memberPw": case "pwd1":
			value = getSha512(super.getParameter(name));
			
			break;
		
		default :value = super.getParameter(name);
		}
		
		
		return value;
	}
	
	   /** SHA-512 해쉬 함수를 이용하여 문자열 암호화를 진행하는 메소드
	    * @param pwd
	    * @return encPwd
	    */
	   private String getSha512(String pwd) {
	      
	      // 1. 암호화된 비밀번호를 저장할 변수 선언
	      String encPwd = null;
	      
	      // 2. 해쉬 함수를 수행하는 객체를 저장할 변수 선언
	      // 해쉬 함수 : 특정 값을 여러 단계의 연산을 거쳐 일정 길이의 무작위 값을 얻어내는 함수
	      MessageDigest md = null;
	      
	      try {
	         // 3. SHA-512 방식의 해쉬함수를 수행할 수 있는 객체를 얻어옴
	         md = MessageDigest.getInstance("SHA-512");
	         
	         // 4. md를 이용해 문자열 암호를 하기 위해 byte 배열로 변환
	         byte[] bytes = pwd.getBytes(Charset.forName("UTF-8"));
	         
	         
	         // 5. md 객체에 바이트로 변환된 비밀번호를 전달하여 암호화를 수행
	         md.update(bytes);
	         
	         // 6. md 객체에서 암호화된 내용을 꺼내옴
	         //  Base64 : 바이트 코드를 문자열로 바꾸는 라이브러리
	         encPwd = Base64.getEncoder().encodeToString(md.digest());
	         // md.digest() : 암호화된 코드를 꺼내옴
	         
	         System.out.println("암호화 전 : " + pwd);
	         System.out.println("암호화 후 : " + encPwd);
	         
	      }catch (NoSuchAlgorithmException e) {
	         // SHA-512 해쉬함수가 없는 경우 발생
	         e.printStackTrace();
	      }
	      
	      return encPwd;
	   }
	   

}

DBCP : Database Connection Pool

 

사용자가 DB에 접속이 몰리면 과부하 문제도 있고 연결 속도에 지장이 생길 수 있다

이를 해결하기 위해 미리 커넥션을 만들어 놓고 전달해주면 속도를 줄이며

최대 커넥션을 설정해 과부하를 막을 수 있도록 해준다

이를 커넥션 풀이라고 한다

[Connection Pool]
//미리 DB와 연결되어있는 Connection 객체를 일정 개수 이상 만들어 두고
//요청 시 만들어둔 Connection을 빌려주고
//요청 완료 시 다시 반환 받아오는 방법'

//항상 일정 개수 이상의 Connection 객체가 존재
//요청이 많을 경우 지정된 범위 내에서 추가적인 Connection 객체 생성할 수 있음
//Connection 개수에 제한이 있기 때문에 DB에 과도한 요청을 보내는 경우를 방지

 

이를 위해 이클립스에 미리 설정을 해놓는다

1. Server -> context.xml 에 세팅

      <Resource 
     name = "jdbc/oracle"
     auth = "Container"
     type = "javax.sql.DataSource"
     driverClassName="oracle.jdbc.OracleDriver"
     url = "jdbc:oracle:thin:@127.0.0.1:1521:xe"
     username = "username "
     password = "password !"
     maxTotal="200"
     maxIdle = "20"
     maxWaitMillis = "-1"/>
     %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 

      jdbc/oracle : NAME
      DataSource : DriverManager의 업그레이드판
       maxTotal : 최대 커넥션 개수 
      maxIdle  : 평소에 생성되어있는 커넥션의 최대 개수
      maxWaitMillis : 커넥션이 반환되는 최대 시간(-1이면 무제한)
     %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

2.  web.xml 에 세팅 (생략가능인듯?)

    <!--  DBCP 설정 자원 위치 -->
    <resource-ref>
    <description>Oracle Datasource</description>
    <res-ref-name>jdbc/oracle</res-ref-name>
    <res-type>javax.sql.DataSource</res-type>
    <res-auth>Container</res-auth>
   </resource-ref> 

3. JDBC 연결시 Context 사용 (템플릿 사용)



// Servers에 존재하는 context.xml 파일을 찾는 작업
     

  Context initContext = new InitialContext();
         Context envContext  = (Context)initContext.lookup("java:/comp/env");  
          // java:comp/env   응용 프로그램 환경 항목
         
         // context.xml 파일에서 name이 "jdbc/oracle"인 DataSource를 얻어옴
         // DataSource : DriverManager를 대체하는 객체로 
         // Connection 생성, Connectoin pool을 구현하는 객체
         DataSource ds = (DataSource)envContext.lookup("jdbc/oracle");
         
         conn = ds.getConnection(); // DataSource에 의해 미리 만들어진 Connection 중 하나를 얻어옴.
         conn.setAutoCommit(false);
         
         //-----------------------------------------------------------
    // JNDI(Java Naming and Directory Interface API)
         /*디렉터리 서비스에 접근하는데 사용하는 API
         어플리케이션은 JNDI를 사용하여 서버의 resource를 찾는다.
         특히 JDBC resource를 data source라고 부른다.
         
         Resource를 서버에 등록할 때 고유한 JNDI 이름을 붙이는데, JNDI 이름은 디렉터리 경로 형태를 가진다.
         예를 들어 data source의 JNDI 이름은 'jdbc/mydb' 형식으로 짓는다.
         
          서버에서 'jdbc/oracle'라는 DataSource를 찾으려면 
         'java:comp/env/jdbc/oracle'라는 JNDI 이름으로 찾아야 한다. 
         즉 lookup() 메소드에 'java:comp/env/jdbc/oracle'를 인자값으로 넘긴다.
         //--------------------------------------------------------------
         */

 

스크립팅 원소:

1) 선언문(declaration) <%! 자바코드 %>

2) 스트립틀릿(scriptlet) <% 자바코드 %>

3) 출력식, 표현식(expression) <%= 자바코드 %>

 

스크립팅 원소를 더 편하게 쓸수있는 라이브러리->JSTL

 

Servlet / JSP에는 기본적으로 내장되어있는 객체가 존재함. 

        총 4종류가 존재하며 각각 영향을 미칠 수 있는 범위가 다름. 

        1. page scope  현재 페이지(현재 Servlet 또는 현재 JSP 에서만 사용 가능)
        
        2. request scope 
        -> 요청 받은 Servlet/JSP + 요청 위임한 Servlet/ JSP 
        -> (2페이지 이상)
        
        3. session scope
        -> 사이트에 접속한 브라우저당 1개씩 생성됨 
            같은 브라우저끼리 공유가 됨
            브라우저 종료 또는 세션 만료시 소멸
            브라우저가 종료되지 않거나 세션이 만료되지 않으면 계속 유지
            클라이언트가 서버에 접속하면 세션을 1개 생성해서 저장하는 것임

        4. application scope 
            -> 하나의 웹 애플리케이션 당 1개 생성. 
            -> 서버 종료 전까지 웹 애플리케이션 어디서든 사용 가능

JSTL/EL

EL(Expression Language) : JSP의 표현식을 조금 더 효율적이고 간단하게 작성하는 언어

 

JSTL

JSP에서 사용하는 태그 라이브러리로 
JSP에서 자주 사용하거나 공통적으로 사용되는 코드를 쉽게 사용하기 위해
태그화하여 표준으로 제공함.

 

https://tomcat.apache.org/download-taglibs.cgi 접속
jar files -> impl, EL, Spec 다운로드
WEB-INF/lib 폴더에 추가

 

JSTL 사용을 위한 선언 방법

 

JSTL을 사용하고자 하는 JSP가 있을 경우
해당 JSP 최상단에 JSTL 라이브러리를 추가하는 지시자 taglib를 작성해야 한다.

 

EX) /<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>/

 

prefix : 접두사. 다른 태그와 구별할 수 있는 namespace;

 

uri (unifomr resource identifier): 네트워크 상에서 자원을 구변하는 식별자
자원을 구분하는 유일한 주소
(url: uniform resource locator -> 인터넷에서 특정 자원 위치 지정 )
->uri에 작성하는 주소는 네트워크 상의 주소가 아닌 다운로드 받은 라이브러리 상의 주소가 아닌
  다운로드 받은 라이브러리 내부 구분 주소

 

[  변수 선언 c: set 태그  ]

-변수를 선언하고 초기화를 진행하는 태그(초기화 무조건 수행)
-c:set 태그로 선언한 변수는 EL을 이용해서 출력할 수 있다.

특징 1: 별도의 변수 타입 지정을 하지 않는다.
특징 2: 변수의 범위(scope)를 지정할 수 있다.
(page request session application)
var : 변수명
value : 저장할 값
scope : 변수 범위 

 

ex) /<c:set var="num1" value="100" scope="session/>/

 

[  변수 삭제 (c:remove)  ]

지정한 변수를 특정 scope 또는 모든 scope에서 제거
ex) 
게시글 작성 -> 오류 발생 -> 다시 작성페이지 돌아옴 -> 이전 내용이 모두 삭제
이를 해결하기 위해 작성 완료 시 session에 글 내용을 임시 저장
->정상적으로 글 등록이 완료되면 임시 저장된 내용을 삭제

 

<c:remove var="num1" scope="session"/>

 

[  조건문 - if문 (c:if 태그)  ]

if문을 태그 형식으로 작성한 것.
별도의 else 구문이 존재하지 않음

test 속성 : 조건을 작성하는 속성 EL 형식으로만 작성 가능.

1. if(조건식) ==  <c:if test="조건식">

2. if else if else == c:choose -> c:when -> c:otherwise

3. for문 + 추가기능 == c:forEach

 

/<c:if test="${test1>test2}">
test1이 더 큽니다.
</c:if>/
별도의 else 구문이 없으므로 필요 시 반대 조건의 c:if를 작성해야 함 

 

[  조건문 - if~ else if~ else(c:choose , c:when, c:otherwise)  ]

c:choose 태그 내부에
c:when 태그를 이용하여 조건 작성(if, else if )
c:otherwise 태그를 이용해 조건을 만족하지 않는 경우 작성(else)

<%--choose문 안에 주석쓰면 오류남 --%>

 

/ <c:choose>
<c:when test="${param.aaa>10}">
10보다 큼
</c:when>

<c:when test="${param.aaa ==10}">
10과 같다
</c:when>

<c:otherwise>
10보다 작다
</c:otherwise>
</c:choose>/

 

[  c:forEach 태그  ]

- java의 for문 + 추가 기능을 가지고 있는 태그
- 속성

var: 현재 반복 횟수에 해당하는 변수 (==int i )
begin: 반복 시작 값
end:  반복 종료 값
step: 반복 시 마다 증가할 값 (--- 여기까지 쓰면 일반 for문), 미작성 시 기본값 1

items: 반복 접근할 객체 명(Collection 객체)(-- items 추가시 향상된 for문)
varStatus: 현재 반복에 해당되는 상태 정보

- 제공되는 값 
1) current : 현재 반복 횟수 또는 현재 접근중인 객체
2) index : 현재 객체가 몇번째 인덱스인지 반환 (0부터 시작)
3) count : 현재 반복문이 몇바퀴 반복 중인지 반환 (1부터 시작)
4) first : 첫 번째 반복일 경우 true 반환
5) last : 마지막 반복일 경우 true 반환

 

[  일반 for문 형식 사용  ]
/<c:forEach var="i" begin="1" end="6" step="1" >
<h${i}>안녕하세요 forEach 작성 테스트 중입니다 ${i}번째 시도</h${i}>
</c:forEach>/

 

[  향상된 for문처럼 사용  ]

/<c:forEach var="item" items="${paramValues.lang}" varStatus="vs">

~~내용~~

</c:forEach> /

 

 

 

 

HTML form태그가 전달하는 방식:

 

1) GET방식

- 요청 시 주소에 값(파라미터)을 담아서 전달하는 방식

- 장점 : 캐싱(북마크, 주소복사) 가능

- 단점 : 비밀번호도 주소에 노툴되는 문제 발생

           +주소창 길이는 제한됨(데이터 길이 제한)

==>쿼리스트링 사용 : 주소에 담긴 파라미터를 나타내는 문자열

==>요청 주소 뒤에 ?를 기점으로 시작. + name속성값=value 형태로 작성, 여러개면 &로 붙힘

 

2)POST방식

- 요청 시 HTTP Body에 값을 감아서 전달하는 방식

- 장점 : 값이 주소에 노출되지 않아 보안성이 높음.

          + 데이터 크기 제한 없음.

- 단점 : 캐싱 불가능. 문자 인코딩 처리가 필요

 

[하나의 프로젝트에서 같은 주소 요청을 처리하는 Servlet은 중복 존재할 수 없다]

== 요청 주소당 Servlet은 하나만 가능하고 이 하나에서 GET 과 POST를 둘 다 받게 할 수 있다.

(doget(), dopost() 작성)

 

JSP : HTML에 Java코드를 작성할 수 있는 파일. HTML을 쉽게 Java와 합쳐 작성할 수 있게 도와준 Servlet

---> 한마디로 발전된 Servlet으로 둘이 전혀 다른게 아님

 

JSP의 장점:

1) Servlet보다 쉽다

2) 디자인과 로직이 나눠있을 수 있음

3) 변수의 범위 설정 가능(scope)

 

 

 

 

Servelt 이란?

웹 프로그래밍에서 클라이언트의 요청을 처리하고 그 결과를 다시 응답하는 자바 프로그래밍 기술

== 자바로 구현된 CGI(특별한 라이브러리나 도구가 아닌 별로도 제작된 웹 서버와 프로그램간의 교환 방식)

==코딩으로 웹 브라우저용 출력화면(HTML) 을 만드는 방법

 

-주요 특징

1. 클라이언트의 요총에 대해 동적으로 작동하는 웹 애플리케이션 컴포넌트

== 미리 만들어둔 화면이 아닌 요청을 받을 때 마다 알맞은 화면을 만들어 응답

2. HTML로 응답

3. java thread를 이용하여(요청마다) 동작

4. MVC Model2 패턴에서 Controller로 이용

5. servelt 클래스를 상속받음

(단점 = servlet에서 작성한 html 코드 변경 시 재컴파일 해야함)

 

-작동 방식

1. 사용자가 HTTP Request를 Servlet Container로 전송

2. Request를 받은 Servlet Container 는 두 객체를 생성

(HttpServletRequest)  - 요청 관련 내용 객체 ,  (HttpServletResponse) - 응답 관련 내용 객체

3. web.xml (DD) 은 사용자가 요청한 URL 을 분석하여 어떤 서블릿 클래스에 요청 내용을 전달할 지 찾음

4. 해당 서블릿에서 init() 메서드를 호출 후 service() 메서드를 호출하여 클라이언트로부터 전송받은 방식에 따라

 GET / POST 여부로 메서드 호출

5. doGet / doPost 메서드는 동적 페이지 생성 후 HttpServletResponse객체에 응답을 보냄

6. 응답이 끝나면 destroy 메서드를 호출하여 HttpServletRequest HttpServletResponse 객체 소멸

 

 

 

 

+ Recent posts