[Study] 자바 웹을 다루는 기술

16 분 소요

3장 설치

오라클 11g release 2를 설치 완료후 cmd 창에서

C:\Users\iamhch>sqlplus

SQL*Plus: Release 11.2.0.2.0 Production on 금 1월 1 19:16:26 2021

Copyright (c) 1982, 2014, Oracle.  All rights reserved.

Enter user-name: system
Enter password:

Connected to:
Oracle Database 11g Express Edition Release 11.2.0.2.0 - 64bit Production

SQL> create user scott identified by tiger;

User created.

SQL> grant resource, connect to scott;

Grant succeeded.

SQL> exit
Disconnected from Oracle Database 11g Express Edition Release 11.2.0.2.0 - 64bit Production

C:\Users\iamhch>sqlplus

SQL*Plus: Release 11.2.0.2.0 Production on 금 1월 1 19:21:10 2021

Copyright (c) 1982, 2014, Oracle.  All rights reserved.

Enter user-name: scott
Enter password:

Connected to:
Oracle Database 11g Express Edition Release 11.2.0.2.0 - 64bit Production

SQL>

4장 웹 애플리케이션 이해하기

톰캣에서 컨텍스트를 인식하는 방법

폴더 구조가 아래와 같아야 함. (웹 애플리케이션 이름) > (WEB-INF) > (classes) + (lib) + web.xml

web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee" 
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" 
id="WebApp_ID"  version="3.0">
</web-app>

main.html은 (웹 애플리케이션 이름) 폴더에 생성함. 필요에 따라 images 등 폴더를 생성해도 됨

웹 브라우저로 요청하는 주소 http://IP주소:포트번호/컨텍스트이름/요청파일이름

컨테이너에 웹 애플리케이션을 등록하는 방법 2가지

  1. %CATALINA_HOME%webApps 디렉토리 하위에 웹 애플리케이션 폴더를 넣음
  2. server.xml에 직접 웹 애플리케이션을 등록함
server.xml
<Context path="/컨텍스트 이름" docBase="실제 웹 애플리케이션의 WEB-INF 디렉토리 위치" reloadable="true or false"/>
(실제예시)
<Context path="/webMal" docBase="C:\\webShop" reloadable="true" />

위 예제에서 /webShop이 아닌 /webMal 이라는 이름으로 컨텍스트를 등록했음.

등록되지 않은 컨텍스트를 브라우져에서 호출하면 404 에러를 출력함.

배치 Deploy란?

  • 개발이 완료된 웹 애플리케이션을 실제 사용자들에게 서비스하기 위한 작업
  • 이클립스 상단 메뉴에서 File>Export>Web>WAR file 선택
  • WAR 파일을 톰캣가 설치된 webapps 폴더 아래 넣어두고
  • 다시 톰캣을 재실행하면 자동으로 webapps 폴더 아래 WAR 파일이 압축 풀리며 컨텍스트 폴더가 생성이 됨

html/jsp 파일의 인코딩을 자동으로 지정 : windows>preference>web>utf-8

5장 서블릿

서블릿이란?

  • 서버 쪽에서 실행되면서 클라이언트의 요청에 따라 동적으로 서비스를 제공하는 자바 클래스
  • HttpServelt을 상속받음
### **1) Servlet**
Servlet은 서블릿 프로그램을 개발할때 반드시 구현해야 하는 메서드를 선언하고 있는 인터페이스이다.  **이 표준을 구현해야 서블릿 컨테이너가 해당 서블릿을 실행할수 있다.**

### **2) GenericServlet**
GenericServlet은 Servlet 인터페이스를 상속하여 클라이언트-서버 환경에서 서버단의 애플리케이션으로서 필요한 기능을 구현한 추상클래스이다. service() 메서드를 제외한 모든 메서드를 재정의하여 적절한 기능으로 구현했다. GenericServlet 클래스를 상속하면 애플리케이션의 프로토콜에 따라 메서드 재정의 구문을 적용해야 한다.

### **3) HttpServlet**
일반적으로 서블릿이라하면 거의 대부분 HttpServlet을 상속받은 서블릿을 의미한다. HttpServlet은 GenericServlet을 상속받았으며, GenericServlet의 유일한 추상 메서드인 service를 HTTP 프로토콜 요청 메서드에 적합하게 재구현해놨다.
이미 DELETE, GET, HEAD, OPTIONS, POST, PUT, TRACE를 처리하는 메소드가 모두 정의되어 있다.
  
출처: [https://12bme.tistory.com/555](https://12bme.tistory.com/555) [길은 가면, 뒤에 있다.]
  • 클라이언트 요청 » public service() 호출 » protected service() 호출 » doXXX 호출
  • 서블릿 생명 주기 메서드 :: 초기화 init() » 작업수행 doXXX » 종료 destory()
  • 서블릿 생성 과정 :: 사용자 정의 서블릿 클래스 만들기 » 서블릿 생명주기 메서드 구현 » 서블릿 매핑 작업 » 웹 브라우저에서 서블릿 매핑 이름으로 요청하기

서블릿 매핑 방법

각 프로젝트에 있는 web.xml에서 설정
<servlet> 태그와 <servlet-mapping> 태그를 이용함
여러 개의 서블릿 매핑 시에는 <servlet> 태그를 먼저 정의하고 <servlet-mapping> 태그를 정의함
애너테이션을 이용하는 방법 :: 서블릿 클래스 위에 @WebServlet("/서블릿매핑이름"); 기록

(예시)
	<servlet>
		<servlet-name>aaa</servlet-name>
		<servlet-class>sec01.ex01.FirstServlet</servlet-class>
	</servlet>
	<servlet-mapping>
		<servlet-name>aaa</servlet-name>
		<url-pattern>/first</url-pattern>
	</servlet-mapping>
  • 이클립스에서 서블릿 소스 만들 때 build path에 libraries에서 servlet-api.jar를 추가해 줘야 함.

6장 서블릿 기초 :: 요청과 응답 처리

  • 서블릿 요청과 응답 수행 API 기능 요청 API :: javax.sevlet.http.HttpServletRequest 클래스 응답 API :: javax.sevlet.http.HttpServletResponse 클래스

  • 브라우저에서 요청은
  • 태그를 이용해 서블릿에 요청
  • 태그 여러가지 속성 name : 자바스크립트에서 폼 태그 접근할 때 주로 사용 method : get/post action : JSP나 서블릿을 지정함 encType : 전송할 데이터의 인코딩 방식
  • 서블릿에서 form 태그의 정보를 받는다. = HttpServeltRequest 클래스 String getParameter(String name) :: name값을 알고 있을 때 name에 전송된 값을 받아오는데 사용 String[] getParameterValues(String name) :: 같은 name에 대해 여러 개의 값을 얻을 때 사용 Enumeration getParameterNames() :: name값을 모를 때 사용

  • 서블릿의 응답 처리 방법 doGet()이나 doPost() 메서드 안에서 처리함. javax.servlet.http.HttpServletResponse 객체를 이용함 setContentType()을 이용해 클라이언트에게 전송할 데이터 종류 (MIME-TYPE)을 지정함. 클라이언트(웹 브라우저)와 서블릿의 통신은 자바I/O 스트림을 이용함

MIME-TYPE 지정예 HTML : text/html 일반텍스트 : text/plain XML 데이터 전송시 : application/xml

  • HpptServletRespnse 를 이용한 서블릿 응답 실습 1 setContentType()을 이용해 MIME-TYPE 지정 2 데이터를 출력할 PrintWriter 객체 생성 3 출력 데이터를 HTML 형식으로 만듦 4 PrintWriter의 print()나 println()을 이용해 데이터 출력

  • Integer.parseInt() :: 숫자를 넘겨받아도 문자로 전송되어 들어오기에 int로 형변환해줘야 함.

7장 서블릿 비즈니스 로직 처리

서블릿 기본 기능 3가지 1) 요청 2) 응답 3) 비즈니스 로직 처리 (DB연동 + 타 시스템 연동, API처리)

자바 클래스를 통해 DB와 연동함

MemberServlet MemberDAO MemberVO JDBC

자바 데이터베이스 강좌 https://cafe.naver.com/standardjava https://cafe.naver.com/spring4shoppingmall

테이블 :: SQL developer 이용 id varchar2(10) pwd varchar2(10) name varchar2(50) email varchar2(50) joinDate date default sysdate

오라클 드라이버 (ojdbc6.jar –> 프로젝트의 /WebContent/WEB-INF/lib 폴더에 복사하여 붙여넣음) https://www.oracle.com/technetwork/apps-tech/jdbc-112010-090769.html

--회원 테이블 생성
create table t_member(
    id varchar2(10) primary key,
    pwd varchar2(10),
    name varchar2(50),
    email varchar2(50),
    joinDate date default sysdate
);

--회원 정보 추가
insert into t_member
values('hong','1212','홍길동','hong@gmail.com',sysdate);

insert into t_member
values('lee','1212','이순신','lee@test.com',sysdate);

insert into t_member
values('kim','1212','김유신','kim@web.com',sysdate);
commit;

select * from t_member;

MemberDAO.java

package sec01.ex01;

import java.sql.Connection;
import java.sql.Date;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

public class MemberDAO {
	private static final String driver= "oracle.jdbc.driver.OracleDriver";
	private static final String url= "jdbc:oracle:thin:@localhost:1521:XE";
	private static final String user= "scott";
	private static final String pwd= "tiger";
	private Connection con;
	private Statement stmt;
	
	public List<MemberVO> listMembers(){
		List<MemberVO> list = new ArrayList<MemberVO>();
		
		try {
			connDB();
			String query = "select * from t_member";
			System.out.println(query);
			ResultSet rs = stmt.executeQuery(query);
			
			while(rs.next()) {
				String id = rs.getString("id");
				String pwd = rs.getString("pwd");
				String name = rs.getString("name");
				String email = rs.getString("email");
				Date joinDate = rs.getDate("joinDate");
				
				MemberVO vo = new MemberVO();
				vo.setId(id);
				vo.setPwd(pwd);
				vo.setName(name);
				vo.setEmail(email);
				vo.setJoinDate(joinDate);
				
				list.add(vo);
			}
			rs.close();
			stmt.close();
			con.close();
				
		}catch(Exception e) {
			e.printStackTrace();
		}
		return list;
	}
	
	private void connDB() {
		try {
			Class.forName(driver);
			System.out.println("Oracle 드라이버 로딩 성공");
			con = DriverManager.getConnection(url,user,pwd);
			System.out.println("Connection 생성 성공");
			stmt = con.createStatement();
			System.out.println("Statement 생성 성공");
		}catch(Exception e) {
			e.printStackTrace();
		}
	}
}
  • PreparedStatement 를 이용 :: SQL을 컴파일하여 사용함으로 속도 향상, ? 사용으로 쿼리문 이용이 편리함

  • DB driver 연결시 가장 시간이 많이 걸림 ⇒ ConnectionPool 을 사용함 (백그라운드 운영)
  • JNDI (Java Naming and Directory Interface) 사용
  • 톰캣 DataSource 설정 :: JDBC드라이버를 /WEB-INF/lib 폴더에 설치
  • –> ConnectionPool 기능 관련 jar파일을 /WEB-INF/lib 폴더에 설치
  • –> CATALINA_HOME\context.xml에 Connection 객체 생성시 연결할 데이터 베이스 정보를 JNDI로 설정함
  • –> DAO 클래스에서 데이터 베이스 연동 시 JNDI 이름으로 데이터베이스를 연결해서 작업함

  • ConnectionPool 관련 라이브러리 다운받기
  • http://www.java2s.com/Code/Jar/t/Downloadtomcatdbcp7030jar.htm

톰캣 서버 context.xml

<Resource
	    name="jdbc/oracle"    			// Datasource에 대한 JNDI 이름
	    auth="Container" 				// 인증주체
	    type="javax.sql.Datasource"		//데이터베이스 종류별 Datasource
	    driverClassName="oracle.jdbc.OracleDriver"	
	    url="jdbc:orcale:thin@localhost:1521:XE"
	    username="scott"
	    password="tiger"
	    maxActive="50"			// 동시에 최대로 DB 연결 connection 수
	    maxWait="-1" />			// 새로운 연결 기다리는 최대시간

MemberDAO.java ```Java package sec02.ex01;

import java.sql.Connection; import java.sql.Date; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.util.ArrayList; import java.util.List;

import javax.naming.Context; import javax.naming.InitialContext; import javax.sql.DataSource;

public class MemberDAO { /* private static final String driver = “oracle.jdbc.driver.OracleDriver”; private static final String url = “jdbc:oracle:thin:@localhost:1521:XE”; private static final String user = “scott”; private static final String pwd = “tiger”; */

private Connection con;
private PreparedStatement pstmt;
private DataSource dataFactory;

public MemberDAO() {
	try {
		Context ctx = new InitialContext();
		Context envContext = (Context) ctx.lookup("java:/comp/env");
		dataFactory = (DataSource) envContext.lookup("jdbc/oracle");
	} catch (Exception e) {
		e.printStackTrace();
	}
}

public List listMembers() {
	List list = new ArrayList();
	try {
		//connDB();
		con=dataFactory.getConnection();
		String query = "select * from t_member ";
		System.out.println("prepareStatememt: " + query);
		pstmt = con.prepareStatement(query);
		ResultSet rs = pstmt.executeQuery();
		while (rs.next()) {
			String id = rs.getString("id");
			String pwd = rs.getString("pwd");
			String name = rs.getString("name");
			String email = rs.getString("email");
			Date joinDate = rs.getDate("joinDate");
			MemberVO vo = new MemberVO();
			vo.setId(id);
			vo.setPwd(pwd);
			vo.setName(name);
			vo.setEmail(email);
			vo.setJoinDate(joinDate);
			list.add(vo);
		}
		rs.close();
		pstmt.close();
		con.close();
	} catch (Exception e) {
		e.printStackTrace();
	}
	return list;
}

/*
private void connDB() {
	try {
		Class.forName(driver);
		System.out.println("Oracle 드라이버 로딩 성공");
		con = DriverManager.getConnection(url, user, pwd);
		System.out.println("Connection 생성 성공");
	} catch (Exception e) {
		e.printStackTrace();
	}
}
*/

}


* 현업에서 사용하는 기술 2가지 = PreparedStatement + DataSource 기능

* PreparedStatement에서 insert문 사용방법
1 insert문에서 회원정보를 저장하기 위해 ?(물음표)를 사용함
2 ?는 id,pwd,name,age에 순서대로 대응함
3 각 ?에 대응하는 값을 지정하기 위해 PreparedStatement의 setter를 이용함
4 setter() 메서드의 첫 번째 인자는 '?'의 순서를 지정함
5 ?은 1부터 시작함
6 insert, delete, update문은 executeUpdate() 메서드를 호출함

# 8장 서블릿 확장 API

>서블릿 포워드 방법 -> 데이터 전송도 가능

1 redirect 방법 
- HttpServletResponse 객체의 sendRedirect() 메서드 이용
- 웹 브라우저에 재요청하는 방식
- 형식 : response.sendRedirect("포워드할 서블릿 or JSP");

2 Refresh 방법
- HeepServlet Response 객체의 addHeader() 메서드를 이용
- 웹 브라우저에 재요청하는 방식
- 형식 : response.addHeader("Refresh,"경과시간(초), url=요청할 서블릿 or JSP");

3 location 방법
- 자바스크립트 location 객체의 href 속성을 이용
- 자바스크립트에서 재요청하는 방식
- 형식 loaction.href = '요청할 서블릿 or JSP'

4 dispatch 방법
- 일반적으로 포워딩 기능을 지칭
- 서블릿이 직접 요청하는 방법
- RequestDispatcher 클래스의 forward() 메서드 이용
- 형식 : RequestDispatcher dis = request.getRequestDispatcher("포워드할 서블릿 or JSP");
- dis.forward(request, response);

>바인딩

포워딩 방법은 데이터 전송이 적은 경우 get으로 전송하지만
전달할 변수가 많을 경우에는 바인딩으로 처리함
request - setAttribute() / getAttribute() / removeAttribute()
리다이렉트 방법으로는 바인딩 보낼 수 없음 (다른 요청이 됨)
--> 디스패치 방식으로만 바인딩을 보낼 수 있음
== 모델 2나 스프링 에서 포워딩 시 사용함

```Java
request.setAttribute("membersList",membersList);
		RequestDispatcher dispatch = request.getRequestDispatcher("viewMembers");
		dispatch.forward(request, response);

ServletContext와 ServletConfig

ServletContext :: 컨테이너에서 Context마다 생성됨 ServletConfig :: Context 안에서 각 Servlet마다 생성됨 == 인터페이스

9장 쿠키, 세션

쿠키 API 특징

  • javax.servlet.http.Cookie를 이용
  • HttpServletResponse의 addCookie() 메서드를 이용해 클라이언트 브라우저에 쿠키를 전송한 후 저장함
  • HttpServletRequest의 getCookie() 메서드를 이용해 쿠키를 서버로 가져옴

쿠키 Set – addCookie()

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		request.setCharacterEncoding("utf-8");
		response.setContentType("text/html;charset=utf-8");
		PrintWriter out = response.getWriter();
		
		Date d = new Date();
		Cookie c = new Cookie("cookieTest",URLEncoder.encode("JSP프로그래밍입니다.","utf-8"));		// URLEncoder.encode 을 이용하여 ASCII로 저장함
		c.setMaxAge(24*60*60); 	// 초단위, 24시간을 유효시간으로 설정함
		response.addCookie(c);	// 브라우저로 전송해서 클라이언트에 저장함
		out.println("현재시간 : " + d);
		out.println("<br> 문자열을 Cookie에 저장합니다.");
	}

쿠키 Get – getCookies(), getName(), getValue()

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		request.setCharacterEncoding("utf-8");
		response.setContentType("text/html;charset=utf-8");
		PrintWriter out = response.getWriter();
		
		Cookie[] allValues = request.getCookies();
		for(int i=0;i<allValues.length;i++) {
			if(allValues[i].getName().equals("cookieTest")) {
				out.println("<h2>Cookie 값 가져오기 : "+URLDecoder.decode(allValues[i].getValue(),"utf-8"));
			}
		}
	
	}

  • 세션 쿠키는 setMaxAge(-1); 로 설정하면 브라우져 메모리에 설정됨.

세션을 이용하여 로그인 정보 바인딩

HttpSession 객체는 HttpServletRequest의 getSession() 메서드를 호출해서 얻음 getSession() :: 기존의 세션 객체가 존재하면 반환하고, 없으면 새로 생성 getSession(true) :: 기존의 세션 객체가 존재하면 반환하고, 없으면 새로 생성 getSession(false) :: 기존의 세션 객체가 존재하면 반환하고, 없으면 null을 반환


if(session.isNew()){
	if(user_id !=null){
		session.setAttribute("user_id",user_id);
		out.println("<a href='login'>로그인 상태 확인</a>");
	}else{
		out.print("<a href='login2.html'>다시 로그인하세요!</a>");
		session.invalidate();
	}
}else{
	user_id = (String) session.getAttribute("user_id");
	if(user_id != null && user_id.length() !=0 ){
		out.print("안녕하세요" + user_id +"님!!");
	}else{
		out.print("<a href='login2.html'>다시 로그인하세요!!!</a>");
		session.invalidate();
	}
}
  • (주의) 브라우저 설정에서 쿠키 사용을 차단하면 세션도 사용할 수 없음. – 이런경우에는 encodingURL 메서드를 사용하여 세션을 get 방식으로 전송할 수 있음.

10장 서블릿 필터와 리스너

10.1 서블릿 속성과 스코프

서블릿 속성 (attribute) ::ServletContext, HttpServlet, HttpServletRequest 객체에 바인딩되어 저장된 객체 (정보)

  • 각 서블릿 API의 setAttribute()로 속성을 바인딩함
  • 각 서블릿 API의 getAttribute()로 속성을 접근함
  • 각 서블릿 API의 removeAttribute()로 속성을 제거함

서블릿 스코프 (scope)

  • 서블릿 API에 바인딩된 속성에 대한 접근 범위
  • ServletContext 속성은 애플리케이션 전체에서 접근 가능
  • HttpSession 속성은 사용자만 접근 가능
  • HttpServletRequest 속성은 해당 요청/응답에 대해서만 접근 가능
  • 각 스코프를 이용해서 로그인 상태 유지, 장바구니, MVC의 Model과 View의 데이터 전달 기능을 구현

스코프 종류와 속성의 접근범위

  • 애플리케이션 스코프 (ServletContext) :: 속성은 애플리케이션 전체에 대해 접근할 수 있음
  • 세션 스코프 (HttpSession) :: 속성은 브라우저에서만 접근할 수 있음
  • 리퀘스트 스코프 (HttpServletRequest) :: 속성은 해당 요청/응답 사이클에서만 접근가능

실제 예시

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		response.setContentType("text/html;charset=utf-8");
		PrintWriter out = response.getWriter();
		String ctxMesg = "context에 바인딩됩니다.";
		String sesMesg = "session에 바인딩됩니다.";
		String reqMesg = "request에 바인딩됩니다.";
		
		ServletContext ctx = getServletContext();
		HttpSession session = request.getSession();
		ctx.setAttribute("context", ctxMesg);
		session.setAttribute("session", sesMesg);
		request.setAttribute("request", reqMesg);
		out.print("바인딩을 수행합니다");
	}

10.2 서블릿의 여러가지 URL 패턴

URL 패턴 :: 서블릿 매핑 시 사용되는 가상의 이름

  • 클라이언트가 브라우저에서 요청할 때 사용되며 반드시 /(슬래시)로 시작해야 함
  • 이름일치 / 디렉토리까지 일치 / 확장자만 일치 하는 세가지로 나뉘어짐

10.3 Filter API

10.4 여러 가지 서블릿 관련 Listener API

11장 JSP 정의와 구성 요소

JSP 3단계 작업 과정

톰켓 컨테이너에서 JSP 변환과정 3단계

1 변환 단계 :: 컨테이너는 JSP파일을 자바 파일로 변환함 2 컴파일 단계 :: 컨테이너는 변환된 자바 파일을 클래스 파일로 컴파일함 3 실행 단계 :: 컨테이너는 클래스 파일을 실행하여 그 결과를 브라우저로 전송해 출력해 줌

JSP 페이지 구성 요소

디렉티브 태그 :: JSP 페이지에 대한 전반적인 설정 정보를 지정할 때 사용하는 태그

  • 페이지 디렉티브 태그 (Page Directive Tag):: JSP 페이지 전반적인 정보 설정
  • 인쿨루드 디렉티브 태그 (Include Directive Tag) :: 공통으로 사용하는 JSP페이지를 다른 JSP페이지에 추가할 때 사용합니다.
  • 태그라이브 디렉티브 태그 (Taglib Directive Tag) :: 개발자나 프레임워크에서 제공하는 태그를 사용할 때 사용합니다.

페이지 디렉티브 형식 :: <%@page %> 안에 속성과 값을 나열함. (주의) import 속성을 제외하고는 속성은 한 번만 선언해야 함.

인클루드 디렉티브 태그 사용법 :: 왼쪽과 상단 메뉴 등은 공통으로 사용하기 이런 경우 공통 페이지를 인클루드 해서 사용함. <@ inlcude file=”공통기능.jsp” %>

12장 JSP 스크립트 요소 기능

1 JSP 스크립트 요소

: <% %> 기호 안에 자바 코드로 구현함. <% %>기호를 스크립트릿(scriptlet)이라고 함

  • 선언문 :: JSP에서 변수나 메서드를 선언할 때 사용
  • 스크립트릿 :: JSP에서 자바 코드를 작성할 때 사용
  • 표현식 :: JSP에서 변수의 값을 출력할 때 사용

(1) 선언문 :: <%! 멤버 변수 or 멤버 메서드 %>

  • 위에서 선언한 멤버 변수를 사용할 때 <%= name %> 식으로 멤버 변수를 받아서 사용함

(2) 스크립트릿 :: <% 자바 코드 %>

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%!
	String name = "이순신";
	public String getName(){
		return name;
	}
%>
<% 	String age = request.getParameter("age"); %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>선언문 연습</title>
</head>
<body>
	<h1>안녕하세요 <%=name %>님!!!</h1>
	<h1>나이는 <%=age %>살입니다!!!</h1>
</body>
</html>
  • 위 코드에서 보면 알 수 있듯이 html구문은 서블릿에서 마지막에 처리해 주던 out.print문이기에 선언부, 실행부, html구문 순서로 나온다.

(3) 표현식 :: 표현식은 JSP 페이지의 정한 위치에 값을 출력하는 기능임. <%=값 or 자바변수 or 식%> (주의할 점) 표현식에서는 마지막에 ; 표시를 하면 안됨

(4) 주석문 :: <%– 내용 –%>

JSP 에서 제공하는 내장 객체들

  • request :: 클라이언트의 요청 정보를 저장 == HttpServletRequest – 한번의 요청에 대해 같은 요청을 공유하는 JSP페이지를 공유함.
  • response :: 응답 정보를 저장
  • out :: JSP 페이지에서 결과를 출력
  • session :: 세션 정보를 저장 == HttpSession – 같은 브라우저에서 공유함
  • application :: 컨텍스트 정보를 저장 == ServletContext – 같은 애플리케이션에서 공유함
  • pageContext :: JSP 페이지에 대한 정보를 저장
  • page :: JSP 페이지의 서블릿 인스턴스를 저장 == 서블릿 this –> 한번의 요청에 대해 하나의 JSP 페이지를 공유함
  • config :: JSP 페이지에 대한 설정 정보를 저장
  • exception :: 예외 발생시 예외를 처리

session 내장 객체에 데이터 바인딩 연습

<% HttpSession session = request.getSession(); session.setAttribute(“name”, “이순신”); %> //다른 JSP에서 session을 통해 아래와 같이 정보를 받음 <% String name = (String)session.getAttribute(“name”); %>

application 내장 객체에 데이터 바인딩 연습

<% application.setAttribute(“address”,”서울시 성동구”);%>

out 내장 객체 사용 – html 문장 안으로 출력됨

<% out.println(name+”, “+age); %>

JSP 페이지 예외 처리하기

오류 메시지가 브라우저에 나타나면 사용자 입장에서는 큰 문제가 발생한 것으로 인식하기 쉬움 그러면 사이트에 대한 신뢰도가 떨어지게 된다. 따라서 예외나 오류가 발생할 경우 이를 안내하는 페이지, 즉 예외 처리 전용 페이지가 나타나게 하여 좀 더 신뢰 있고 사용자 친화적인 웹 페이지를 만들수 있음.

JSP 페이지 예외 처리 과정

  1. 예외 처리 담당 JSP를 만든다. <% page isErrorPage=’true’ @>
  2. 예외 발생시 예외 처리 담당 JSP 파일을 지정함. <%page errorPage=’addException.jsp’ %>

exception 내장 객체를 사용하기

  • exception.toString :: toString으로 구체적인 에러 메시지를 보여줌
  • exception.getMessage() :: 에러 메시지를 보여줌
  • exception.printStackTrace() :: printStackTrace() 내용을 보여줌

에러 코드에 따른 예외 페이지 지정 :: web.xml에 태그를 사용하여 , 을 지정할 수 있음

  • 가장 대표적인 404, 500 에러에 대한 에러 페이지를 만든다. :: error_404.jsp, error_500.jsp

  • JSP welcom 파일 지정하기 :: web.xml 파일에 태그 안에 을 지정할 수 있음

13장 자바 코드를 없애는 액션 태그

서블릿, JSP 관련 lib jar파일 – BuildPath로 설정

  • 서블릿 :: servlet-api.jar
  • jsp :: jsp-api.jar

DB관련 lib jar파일 – WebContent>WEB-INF>lib에 복사붙여넣기

  • ojdbc6.jar
  • tomcat-dbcp-7.0.30.jar

액션 태그 – 값도 전달할 수 있음

인클루드 액션 태그 형식

<jsp:include page="jsp페이지" flush="true 또는 false">
	<jsp:param name="변수명1" value="값" />
	<jsp:param name="변수명2" value="값" />	
</jsp:include>
  • 컴파일된 java, class 파일 위치 :: workspace>.metadata>.plugins>org.eclipse.wst.server.core>tmp0>work>Catalina>localhost>pro13>org>aparch>jsp

자바 빈 :: Java EE 프로그래밍 시 여러 객체를 거치면서 만들어지는 데이터를 저장하거나 전달하는 데 사용되는 클래스 ex) VO 클래스와 같은 개념

  • 속성의 접근 제한자는 private임
  • 각 속성은 각각의 setter/getter를 가짐
  • setter/getter의 이름의 첫 글자는 반드시 소문자
  • 인자 없는 생성자를 반드시 가지면 다른 생성자도 추가할 수 있음

14장 표현 언어와 JSTL

  • 액션 태그를 사용해도 아직까지 자바 코드가 많이 남아 있음 –> 표현언어, JSTL로 대체함

표현언어

  • 표현언어(EL: expression language)의 형식 :: ${ 표현식 or 값 }
  • 표현언어를 사용하기 위해서는 <%@ page 속성에 isELIgnored=”false” 를 설정해 줘야함
  • empty 연산자 많이 사용함 – 자바 빈이 비어 있는지 확인
  • 빈 속성 접근 방법 :: ${ 빈이름.속성이름 }
  • 내장객체를 이용하여 사용 ex)param, …

커스텀 태그 :: JSTL(Jsp Standard Tag Library) + 개발자 커스텀 태그

JSTL 포매팅 태그 –> 다국어로 표시 / 가격, 날짜, 문자열 형식 변경가능

<fmt: …> 태그

<fn:…> 태그 :: 문자열 처리 기능 함수 제공함

15장 파일 업로드

관련 jar 파일을 다운받아 >WebContent>WEB-INF>lib에 복사붙여넣기 한다

<form action="${contextPath}/upload.do" method="post" enctype="multipart/form-data"> 
  • 파일 업로드시 반드시 encType=”multipart/form-data” 설정해야 함.

FileUpload.java

package sec01.ex01;

import java.io.File;
import java.io.IOException;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

/**
 * Servlet implementation class FileUpload
 */
@WebServlet("/upload.do")
public class FileUpload extends HttpServlet {
	private static final long serialVersionUID = 1L;

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
	 *      response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doHandle(request, response);
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
	 *      response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doHandle(request, response);
	}

	private void doHandle(HttpServletRequest request, HttpServletResponse response)	throws ServletException, IOException {
		request.setCharacterEncoding("utf-8");
			String encoding = "utf-8";
			File currentDirPath = new File("C:\\file_repo");
			DiskFileItemFactory factory = new DiskFileItemFactory();
			factory.setRepository(currentDirPath);
			factory.setSizeThreshold(1024 * 1024);

			ServletFileUpload upload = new ServletFileUpload(factory);
			try {
				List items = upload.parseRequest(request);
				for (int i = 0; i < items.size(); i++) {
					FileItem fileItem = (FileItem) items.get(i);
	
					if (fileItem.isFormField()) {
						System.out.println(fileItem.getFieldName() + "=" + fileItem.getString(encoding));
					} else {
						System.out.println("매개변수이름:" + fileItem.getFieldName());
						System.out.println("파일이름:" + fileItem.getName());
						System.out.println("파일크기:" + fileItem.getSize() + "bytes");
	
						if (fileItem.getSize() > 0) {
							int idx = fileItem.getName().lastIndexOf("\\");
							if (idx == -1) {
								idx = fileItem.getName().lastIndexOf("/");
							}
							String fileName = fileItem.getName().substring(idx + 1);
							File uploadFile = new File(currentDirPath + "\\" + fileName);
							fileItem.write(uploadFile);
						} // end if
					} // end if
				} // end for
			} catch (Exception e) {
				e.printStackTrace();
			}
	}

}

16장 HTML5와 제이쿼리

Ajax의 정의

= Ajax란 Asynchronous Javascript (비동기 자바스크립트) + XML의 의미로 자바스크립트를 사용한 비동기 통신, 즉, 클라이언트와 서버 간의 XML이나 JSON 데이터를 주고 받는 기술 ⇒ Ajax 웹 페이지 동작 방식을 구현한다.

제이쿼리 Ajax 사용 형식

$.ajax( {
	type: "post 또는 get",
	async: "true 또는 false",
	url: "요청할 URL",
	data: {서버로 전송할 데이터}, // 서버에 요청할 때 보낼 매개변수 설정
	dataType: "서버에서 전송받을 데이터형식", // XML, TEXT, HTML, JSON 등
	success:{
		//정상 요청, 응답시 처리
	},
	error: function(xhr, status, error){
		// 오류 발생시 처리
	},
	complete:function(data,textStatus){
		// 작업 완료 후 처리
	}
});

json 처리

json 데이터 받기

String jsonInfo = request.getParameter("jsonInfo"); // 문자열로 넘어온다
try  { // 넘어온 문자열으로 파싱하여 정보를 받는다.
	JSONParser jsonParser =  new  JSONParser();
	JSONObject jsonObject =  (JSONObject) jsonParser.parse(jsonInfo); 
	System.out.println("*회원정보*");
	System.out.println(jsonObject.get("name"));
	System.out.println(jsonObject.get("age"));
	System.out.println(jsonObject.get("gender"));
	System.out.println(jsonObject.get("nickname"));
}  catch  (Exception e)  {
	e.printStackTrace();
}

json 데이터 보내기

PrintWriter writer = response.getWriter();
JSONObject totalObject =  new  JSONObject(); // 배열을 저장할 전체 객체
JSONArray membersArray =  new  JSONArray(); // JSON객체 저장할 배열

JSONObject memberInfo =  new  JSONObject();
memberInfo.put("name",  "박지성");
memberInfo.put("age",  "25");
memberInfo.put("gender",  "남자");
memberInfo.put("nickname",  "날센돌이");
membersArray.add(memberInfo);

memberInfo =  new  JSONObject();
memberInfo.put("name",  "김연아");
memberInfo.put("age",  "21");
memberInfo.put("gender",  "여자");
memberInfo.put("nickname",  "칼치");
membersArray.add(memberInfo);

totalObject.put("members", membersArray); //"members"라는 이름으로 정보저장

String jsonInfo = totalObject.toJSONString(); // JSONObject를 문자열로 변환
System.out.print(jsonInfo);
writer.print(jsonInfo); // JSON 데이터를 브라우저로 전송


17장 모델2 MVC

모델1 :: 모든 클라이언트 요청과 비즈니스 로직 처리를 JSP가 담당하는 구조. 기능 구현이 쉽고 편리하지만 유지보수가 어려움

– 클라이언트 <–> JSP with DAO 클래스 <–> DB

모델2 :: 클라이언트 요청 처리, 응답 처리, 비즈니스 로직 처리를 분리시킴. 각 기능이 분리되어 있어 유지보수가 쉬움. 재사용성이 높음. 디자이너와 개발자의 작업을 분업화해서 쉽게 개발할 수 있음

– 클라이언트 –> 요청처리 <–> 로직처리 <–> DB – 클라이언트 <– 화면기능 <– 요청처리

  • 컨트롤러는 HttpServletRequeset의 getPathInfo() 메서드를 이용해 URL 패턴에서 요청명을 받아와서 작업을 수행
  • URL 패턴을 이용해 컨트롤러에 요청하는 형식
  • http://localhost:8090/pro17/member/listMembers.do
  • 2단계 호출 :: /member - 회원 기능을 의미, /listMembers.do - 회원 기능 중 회원 조회 기능을 의미
  • 컨트롤러에서 MemberDAO에 대해 listMembers() 메서드를 호출함

실습 :: 수정가능한 게시판 만들기 (상세 페이지 포함)

18장 스프링 프레임워크 시작하기