11.17일 (model-1 employee-story/ model-2)
이전에 했던 model-1 employee-story 연동 계속
ch05-ServletMain
src/main/java
kr.employee.dao
EmployeeDAO
package kr.employee.dao;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import kr.employee.vo.EmployeeVO;
import kr.util.DBUtil;
public class EmployeeDAO {
//싱글턴 패턴
private static EmployeeDAO instance = new EmployeeDAO();
public static EmployeeDAO getInstance() {
return instance;
}
private EmployeeDAO() {}
public void insertEmployee(EmployeeVO vo)throws Exception{
Connection conn = null;
PreparedStatement pstmt = null;
String sql = null;
try{
//커넥션풀로부터 커넥션을 할당
conn = DBUtil.getConnection();
//SQL문
sql = "INSERT INTO semployee (snum,id,name,passwd,salary"
+ ",job) VALUES "
+ "(semployee_seq.nextval,?,?,?,?,?)";
//PreparedStatement 객체 생성
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, vo.getId());
pstmt.setString(2, vo.getName());
pstmt.setString(3, vo.getPasswd());
pstmt.setInt(4, vo.getSalary());
pstmt.setString(5, vo.getJob());
//SQL문 반영
pstmt.executeUpdate();
}catch(Exception e){
throw new Exception(e);
}finally{
DBUtil.executeClose(null, pstmt, conn);
}
}
//사원상세정보
public EmployeeVO getEmployee(int snum)throws Exception{
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
EmployeeVO vo = null;
String sql = null;
try{
//커넥션풀로부터 커넥션을 할당
conn = DBUtil.getConnection();
//SQL문
sql = "SELECT * FROM semployee WHERE snum=?";
//PreparedStatement 객체 생성
pstmt = conn.prepareStatement(sql);
pstmt.setInt(1, snum);
//SQL문 반영하고 결과행을 ResultSet에 담음
rs = pstmt.executeQuery();
if(rs.next()){
vo = new EmployeeVO(); //자바빈 객체 생성
vo.setSnum(rs.getInt("snum"));
vo.setId(rs.getString("id"));
vo.setPasswd(rs.getString("passwd"));
vo.setName(rs.getString("name"));
vo.setSalary(rs.getInt("salary"));
vo.setJob(rs.getString("job"));
vo.setReg_date(rs.getDate("reg_date"));
}
}catch(Exception e){
throw new Exception(e);
}finally{
DBUtil.executeClose(rs, pstmt, conn);
}
return vo;
}
//아이디 중복 체크, 로그인 체크
public EmployeeVO checkEmployee(String id)throws Exception{
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
EmployeeVO vo = null;
String sql = null;
try{
//커넥션풀로부터 커넥션을 할당
conn = DBUtil.getConnection();
//SQL문
sql = "SELECT * FROM semployee WHERE id=?";
//PreparedStatement 객체 생성
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, id);
//SQL문 반영하고 결과행을 ResultSet에 담음
rs = pstmt.executeQuery();
if(rs.next()){
vo = new EmployeeVO(); //자바빈 객체 생성
vo.setId(rs.getString("id"));
vo.setSnum(rs.getInt("snum"));
vo.setPasswd(rs.getString("passwd"));
}
}catch(Exception e){
throw new Exception(e);
}finally{
DBUtil.executeClose(rs, pstmt, conn);
}
return vo;
}
//사원정보수정
public void updateEmployee(EmployeeVO vo)throws Exception{
Connection conn = null;
PreparedStatement pstmt = null;
String sql = null;
try{
//커넥션풀로부터 커넥션을 할당
conn = DBUtil.getConnection();
//SQL문
sql = "UPDATE semployee SET name=?,passwd=?,"
+ "salary=?,job=? "
+ "WHERE snum=?";
//PreparedStatement 객체를 생성
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, vo.getName());
pstmt.setString(2, vo.getPasswd());
pstmt.setInt(3, vo.getSalary());
pstmt.setString(4, vo.getJob());
pstmt.setInt(5, vo.getSnum());
//SQL문 반영
pstmt.executeUpdate();
}catch(Exception e){
throw new Exception(e);
}finally{
DBUtil.executeClose(null, pstmt, conn);
}
}
//사원정보삭제
public void deleteEmployee(int snum)throws Exception{
Connection conn = null;
PreparedStatement pstmt = null;
PreparedStatement pstmt2 = null;
String sql = null;
try{
//커넥션풀로부터 커넥션을 할당
conn = DBUtil.getConnection();
conn.setAutoCommit(false);
//SQL문
sql = "DELETE FROM story WHERE snum=?";
//PreparedStatement 객체 생성
pstmt = conn.prepareStatement(sql);
pstmt.setInt(1, snum);
//SQL문 반영
pstmt.executeUpdate();
sql = "DELETE FROM semployee WHERE snum=?";
pstmt2 = conn.prepareStatement(sql);
pstmt2.setInt(1, snum);
pstmt2.executeUpdate();
conn.commit();
}catch(Exception e){
conn.rollback();
throw new Exception(e);
}finally{
DBUtil.executeClose(null, pstmt2, null);
DBUtil.executeClose(null, pstmt, conn);
}
}
}
사원 정보 삭제 (퇴사) 시 자동으로 게시판 글을 지우게 만들었음
snum이 fk로 들어가있기 때문에 가능
conn.setAutocommit(false) -> pstmt를 따로 설정
pstmt 1 sql = "DELETE FROM story WHERE snum=?";
pstmt 2 sql = "DELETE FROM semployee WHERE snum=?";
conn.commit()
이후 catch문에서 conn.rollback(); 넣어줘야함
ch05-ServletMain
src/main/java
kr.story.dao
StoryDAO
package kr.story.dao;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;
import kr.story.vo.StoryVO;
import kr.util.DBUtil;
public class StoryDAO {
//싱글턴 패턴
private static StoryDAO instance = new StoryDAO();
public static StoryDAO getInstance() {
return instance;
}
private StoryDAO() {}
//글 저장
public void insert(StoryVO vo)throws Exception{
Connection conn = null;
PreparedStatement pstmt = null;
String sql = null;
int cnt = 0;
try{
//커넥션풀로부터 커넥션을 할당
conn = DBUtil.getConnection();
//SQL문
sql = "insert into story (num,title,"
+ "content,ip,snum) "
+ "values (story_seq.nextval,?,?,?,?)";
//PreparedStatement 객체 생성
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, vo.getTitle());
pstmt.setString(2, vo.getContent());
pstmt.setString(3, vo.getIp());
pstmt.setInt(4, vo.getSnum());
//SQL문 실행
pstmt.executeUpdate();
}catch(Exception e){
throw new Exception(e);
}finally{
DBUtil.executeClose(null, pstmt, conn);
}
}
//글의 총 개수
public int getCount()throws Exception{
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
String sql = null;
int count = 0;
try{
//커넥션풀로부터 커넥션을 할당
conn = DBUtil.getConnection();
//SQL문 작성
sql = "SELECT COUNT(*) FROM story";
//PreparedStatement 객체 생성
pstmt = conn.prepareStatement(sql);
//SQL문을 실행해서 결과행을 ResultSet에 담음
rs = pstmt.executeQuery();
if(rs.next()){
count = rs.getInt(1);
}
}catch(Exception e){
throw new Exception(e);
}finally{
DBUtil.executeClose(rs, pstmt, conn);
}
return count;
}
//글 목록
public List<StoryVO> getList(int startRow, int endRow)
throws Exception{
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
List<StoryVO> list = null;
String sql = null;
try{
//커넥션풀로부터 커넥션을 할당
conn = DBUtil.getConnection();
//SQL문 작성
sql = "SELECT * FROM (SELECT a.*, rownum rnum "
+ "FROM(SELECT * FROM story JOIN semployee USING(snum) ORDER BY "
+ "num desc)a) WHERE rnum >= ? AND rnum <= ?";
//PreparedStatement 객체
pstmt = conn.prepareStatement(sql);
pstmt.setInt(1, startRow);
pstmt.setInt(2, endRow);
//SQL문 실행하고 결과행을 ResultSet에 담음
rs = pstmt.executeQuery();
list = new ArrayList<StoryVO>();
while(rs.next()){
StoryVO vo = new StoryVO();
vo.setNum(rs.getInt("num"));
vo.setTitle(rs.getString("title"));
vo.setReg_date(rs.getDate("reg_date"));
vo.setId(rs.getString("id"));
//자바빈을 ArrayList에 등록
list.add(vo);
}
}catch(Exception e){
throw new Exception(e);
}finally{
DBUtil.executeClose(rs, pstmt, conn);
}
return list;
}
//글 상세
public StoryVO getStory(int num)throws Exception{
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
StoryVO vo = null;
String sql = null;
try{
//커넥션풀로부터 커넥션을 할당
conn = DBUtil.getConnection();
//SQL문 작성
sql = "SELECT * FROM story JOIN semployee USING(snum) where num=?";
//PreparedStatement 객체 생성
pstmt = conn.prepareStatement(sql);
//?에 데이터 매칭
pstmt.setInt(1, num);
//SQL문 반영하고 결과행을 ResultSet에 담음
rs = pstmt.executeQuery();
if(rs.next()){
vo = new StoryVO();
vo.setNum(rs.getInt("num"));
vo.setTitle(rs.getString("title"));
vo.setContent(rs.getString("content"));
vo.setIp(rs.getString("ip"));
vo.setReg_date(rs.getDate("reg_date"));
vo.setSnum(rs.getInt("snum"));
vo.setId(rs.getString("id"));
}
}catch(Exception e){
throw new Exception(e);
}finally{
DBUtil.executeClose(rs, pstmt, conn);
}
return vo;
}
//글 수정
public void update(StoryVO vo)throws Exception{
Connection conn = null;
PreparedStatement pstmt = null;
String sql = null;
try{
//커넥션풀로부터 커넥션을 반환
conn = DBUtil.getConnection();
//SQL문 작성
//name,email,content,ip 변경 가능 num으로 식별
sql = "UPDATE story SET title=?, "
+ "content=?,ip=? WHERE num=?";
//PreparedStatement 객체 생성
pstmt = conn.prepareStatement(sql);
//?에 데이터 매칭
pstmt.setString(1, vo.getTitle());
pstmt.setString(2, vo.getContent());
pstmt.setString(3, vo.getIp());
pstmt.setInt(4, vo.getNum());
//SQL문 반영
pstmt.executeUpdate();
}catch(Exception e){
throw new Exception(e);
}finally{
DBUtil.executeClose(null, pstmt, conn);
}
}
//글 삭제
public void delete(int num)throws Exception{
Connection conn = null;
PreparedStatement pstmt = null;
String sql = null;
try{
//커넥션풀로부터 커넥션 할당
conn = DBUtil.getConnection();
//SQL문 작성
sql = "delete from story where num=?";
//PreparedStatement 객체 생성
pstmt = conn.prepareStatement(sql);
//?에 값 매칭
pstmt.setInt(1, num);
//SQL문 반영
pstmt.executeUpdate();
}catch(Exception e){
throw new Exception(e);
}finally{
DBUtil.executeClose(null, pstmt, conn);
}
}
}
webapp
ch19-employee
list.jsp (글 목록 / 사원게시판 목록)
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ page import="kr.story.dao.StoryDAO" %>
<%@ page import="kr.story.vo.StoryVO" %>
<%@ page import="kr.util.PagingUtil" %>
<%@ page import="java.util.List" %>
<%
//선택한 페이지 번호
String pageNum = request.getParameter("pageNum");
if(pageNum==null){
pageNum = "1";
}
//한 화면에 몇 개의 글(행,레코드)을 보여줄 지 지정
int rowCount = 10;
//한 화면에 몇 개의 페이지 수를 보여줄 지 지정
int pageCount = 10;
//현재 선택한 페이지(String -> int)
int currentPage = Integer.parseInt(pageNum);
StoryDAO dao = StoryDAO.getInstance();
int count = dao.getCount();
PagingUtil util = new PagingUtil(currentPage,count,rowCount,pageCount,"list.jsp");
List<StoryVO> list = null;
if(count > 0){
list = dao.getList(util.getStartRow(), util.getEndRow());
}
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>사원이야기 목록</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="page-main">
<h1>사원이야기 목록</h1>
<div class="align-right">
<%
Integer user_num = (Integer)session.getAttribute("user_num");
if(user_num!=null){
%>
<input type="button" value="글쓰기"
onclick="location.href='writeForm.jsp'">
<%
}
%>
<input type="button" value="홈으로"
onclick="location.href='main.jsp'">
</div>
<%
if(count == 0){
%>
<div class="result-display">저장된 글이 없습니다.</div>
<%
}else{
%>
<!-- 목록 출력 시작 -->
<table>
<tr>
<th>글번호</th>
<th>제목</th>
<th>작성자</th>
<th>작성일</th>
</tr>
<%
for(StoryVO storyVO : list){
%>
<tr>
<td><%= storyVO.getNum() %></td>
<td><a href="detail.jsp?num=<%= storyVO.getNum() %>"><%= storyVO.getTitle() %></a></td>
<td><%= storyVO.getId() %></td>
<td><%= storyVO.getReg_date() %></td>
</tr>
<%
}
%>
</table>
<!-- 목록 출력 끝 -->
<!-- 페이지 표시 시작 -->
<div class="align-center">
<%= util.getPage() %>
</div>
<!-- 페이지 표시 끝 -->
<%
}
%>
</div>
</body>
</html>
writeForm.jsp (글 작성 폼)
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
Integer user_num = (Integer)session.getAttribute("user_num");
if(user_num==null){//로그인이 되지 않은 경우
response.sendRedirect("loginForm.jsp");
}else{
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>글쓰기</title>
<link rel="stylesheet" href="style.css" type="text/css">
<script type="text/javascript">
window.onload=function(){
let myForm = document.getElementById('write_form');
myForm.onsubmit=function(){
let items = document.querySelectorAll('input[type="text"],textarea');
for(let i=0;i<items.length;i++){
if(items[i].value.trim()==''){
let label = document.querySelector('label[for="'+items[i].id+'"]');
alert(label.textContent + ' 항목은 필수 입력');
items[i].value = '';
items[i].focus();
return false;
}
}
};
};
</script>
</head>
<body>
<div class="page-main">
<h1>글쓰기</h1>
<form id="write_form" action="write.jsp" method="post">
<ul>
<li>
<label for="title">제목</label>
<input type="text" name="title" id="title" size="30"
maxlength="50">
</li>
<li>
<label for="content">내용</label>
<textarea rows="5" cols="40" name="content"
id="content"></textarea>
</li>
</ul>
<div class="align-center">
<input type="submit" value="글쓰기">
<input type="button" value="목록"
onclick="location.href='list.jsp'">
</div>
</form>
</div>
</body>
</html>
<%
}
%>
글 작성폼
로그인이 되지 않은경우 loginForm으로 redirect
write.jsp (글 작성)
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ page import="kr.story.dao.StoryDAO" %>
<%
Integer user_num = (Integer)session.getAttribute("user_num");
if(user_num==null){//로그인이 되지 않은 경우
response.sendRedirect("loginForm.jsp");
}else{
//전송된 데이터 인코딩 처리
request.setCharacterEncoding("utf-8");
%>
<jsp:useBean id="story" class="kr.story.vo.StoryVO"/>
<jsp:setProperty property="*" name="story"/>
<%
//작성자 번호
story.setSnum(user_num);
//클라이언트의 ip 주소 저장
story.setIp(request.getRemoteAddr());
StoryDAO dao = StoryDAO.getInstance();
dao.insert(story);
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>글쓰기 완료</title>
<link rel="stylesheet" href="style.css" type="text/css">
</head>
<body>
<div class="page-main">
<h1>글쓰기 완료</h1>
<div class="result-display">
<div class="align-center">
게시판에 글을 등록했습니다. <br>
<button onclick="location.href='list.jsp'">목록</button>
</div>
</div>
</div>
</body>
</html>
<%
}
%>
detail.jsp (글 상세보기)
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ page import="kr.story.dao.StoryDAO" %>
<%@ page import="kr.story.vo.StoryVO" %>
<%
int num = Integer.parseInt(request.getParameter("num"));
StoryDAO dao = StoryDAO.getInstance();
StoryVO vo = dao.getStory(num);
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>게시판 글 상세</title>
<link rel="stylesheet" href="style.css" type="text/css">
</head>
<body>
<div class="page-main">
<h1>게시판 글상세</h1>
<ul>
<li>글번호 : <%=vo.getNum() %></li>
<li>제목 : <%=vo.getTitle() %></li>
<li>작성자 : <%=vo.getId() %></li>
</ul>
<hr size="1" noshade width="100%">
<p>
<%=vo.getContent() %>
</p>
<div class="align-right">
작성일 : <%=vo.getReg_date() %>
<%
Integer user_num = (Integer)session.getAttribute("user_num");
//로그인 한 사원 번호와 작성자의 사원 번호가 일치하는지 체크
if(user_num!=null && user_num == vo.getSnum()){
%>
<input type="button" value="수정"
onclick="location.href='updateForm.jsp?num=<%=vo.getNum() %>'">
<input type="button" value="삭제" id="delete_btn">
<script type="text/javascript">
let delete_btn = document.getElementById('delete_btn');
//이벤트 연결
delete_btn.onclick=function(){
let choice = confirm('삭제하시겠습니까?');
if(choice){
location.replace('delete.jsp?num=<%=vo.getNum() %>');
}
};
</script>
<%
}
%>
<input type="button" value="목록"
onclick="location.href='list.jsp'">
</div>
</div>
</body>
</html>
snum을 받아서 로그인한 사원번호와 글쓴 번호가 일치하는지 확인
-> 일치 시 수정/삭제 button 보이게 함
updateForm.jsp (글 수정)
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ page import="kr.story.dao.StoryDAO" %>
<%@ page import="kr.story.vo.StoryVO" %>
<%
Integer user_num = (Integer)session.getAttribute("user_num");
if(user_num==null){
response.sendRedirect("loginForm.jsp");
}else{
int num = Integer.parseInt(request.getParameter("num"));
StoryDAO dao = StoryDAO.getInstance();
StoryVO vo = dao.getStory(num);
if(user_num!=vo.getSnum()){
response.sendRedirect("notice.jsp");
}else{
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>글 수정</title>
<link rel="stylesheet" href="style.css" type="text/css">
<script type="text/javascript">
window.onload=function(){
const myForm = document.getElementById('update_form');
myForm.onsubmit=function(){
let items = document.querySelectorAll('input[type="text"],input[type="password"],textarea');
for(let i=0;i<items.length;i++){
if(items[i].value.trim()==''){
let label = document.querySelector('label[for="'+items[i].id+'"]');
alert(label.textContent + ' 항목은 필수 입력');
items[i].value = '';
items[i].focus();
return false;
}
}
};
};
</script>
</head>
<body>
<div class="page-main">
<h1>글 수정</h1>
<form id="update_form" action="update.jsp" method="post">
<input type="hidden" name="num" value="<%= num %>">
<ul>
<li>
<label for="title">제목</label>
<input type="text" name="title" id="title" size="30"
value="<%= vo.getTitle() %>" maxlength="50">
</li>
<li>
<label for="content">내용</label>
<textarea rows="5" cols="40" name="content"
id="content"><%= vo.getContent() %></textarea>
</li>
</ul>
<div class="align-center">
<input type="submit" value="글수정">
<input type="button" value="목록"
onclick="location.href='list.jsp'">
</div>
</form>
</div>
</body>
</html>
<%
}
}
%>
만약 주소를 바꿔서 들어갔어도 user_num==null 이라면 loginForm으로 리다이렉트
update.jsp (글 수정)
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ page import="kr.story.dao.StoryDAO" %>
<%@ page import="kr.story.vo.StoryVO" %>
<%
Integer user_num = (Integer)session.getAttribute("user_num");
if(user_num==null){
response.sendRedirect("loginForm.jsp");
}else{
request.setCharacterEncoding("utf-8");
%>
<jsp:useBean id="vo" class="kr.story.vo.StoryVO"/>
<jsp:setProperty property="*" name="vo"/>
<%
StoryDAO dao = StoryDAO.getInstance();
StoryVO db_vo = dao.getStory(vo.getNum());
if(user_num!=db_vo.getSnum()){
response.sendRedirect("notice.jsp");
}else{
vo.setIp(request.getRemoteAddr());
dao.update(vo);
%>
<script>
alert('글 수정을 완료했습니다.');
location.href='detail.jsp?num=<%=vo.getNum()%>';
</script>
<%
}
}
%>
notice.jsp (잘못된 접근 페이지)
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>공지</title>
<link rel="stylesheet" href="style.css" type="text/css">
</head>
<body>
<div class="page-main">
<h1>공지</h1>
<div class="result-display">
<div class="align-center">
잘못된 접속입니다.<br>
<button onclick="location.href='list.jsp'">사원이야기 목록</button>
</div>
</div>
</div>
</body>
</html>
delete (글 삭제)
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ page import="kr.story.dao.StoryDAO" %>
<%@ page import="kr.story.vo.StoryVO" %>
<%
Integer user_num = (Integer)session.getAttribute("user_num");
if(user_num==null){
response.sendRedirect("loginForm.jsp");
}else{
int num = Integer.parseInt(request.getParameter("num"));
StoryDAO dao = StoryDAO.getInstance();
StoryVO db_vo = dao.getStory(num);
if(user_num!=db_vo.getSnum()){
response.sendRedirect("notice.jsp");
}else{
dao.delete(num);
%>
<script>
alert('글 삭제를 완료했습니다.');
location.replace('list.jsp');
</script>
<%
}
}
%>
detail에서 user_num이 일치해야 삭제, 수정 버튼이 보이게 했는데
get방식으로 snum을 보냈기 때문에 번호를 바꿔서 수정/삭제에 들어올 가능성 o
특히 삭제는 form없이 알림창 확인을 누르면 삭제할거기 때문에 user_num 조건을 한번 더 걸었음
user_num == null > response.sendRedirect("loginForm.jsp");
user_num!=db_vo.getSnum() > response.sendRedirect("notice.jsp")
model-1
- 소규모 회사 홈페이지 처럼 작은 규모의 사이트를 만들 때 쓰임
- 회원 로그인/ 간단한 글 정도만 가능한 정도
model-2
- model-1보다 규모가 큰 사이트를 만들고 싶을 때 사용
- servlet 이용 - jsp (디자인) dao (db연동) 별도의 모델 클래스 추가 작업
mvc패턴
- 대규모 상용화된 사이트
1) EL
(1) EL 특징
- JSP의 네가지 기본 객체가 제공하는 영역의 속성 사용
- page, request, session, application
- 집합 객체에 대한 접근 방법 제공
- 수치 연산, 관계 연산, 논리 연산자 제공
- 자바 클래스 메서드 호출 기능 제공
- 표현 언어만의 기본 객체 제공
(2) EL 표기법
${expr}
ch20-el
s01_el.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>표현언어(EL) 예제</title>
</head>
<body>
<table border="1" style="width:40%;">
<tr>
<th>표현식</th>
<th>값</th>
</tr>
<tr>
<td>\${2+5}</td> <%-- \넣어서 ${}를 일반문자로 바꿈 --%>
<td>${2+5}</td>
</tr>
<tr>
<td>\${"10"+5}</td>
<td>${"10"+5}</td>
</tr>
<tr>
<td>\${"10"+"5"}</td>
<td>${"10"+"5"}</td>
</tr>
<tr>
<td>\${"십"+5}</td>
<td>에러발생(EL에서의 +는 연산만)</td>
</tr>
<tr><%-- 자바에서는 정수 연산 외에는 다 에러였는데 여기선 정상출력됨(js와 비슷) --%>
<td>\${4/5}</td>
<td>${4/5}</td>
</tr>
<tr>
<td>\${5/0}</td>
<td>${5/0}</td> <%-- Infinity (js처럼 출력됨/에러가 안남- 그래서 가급적 나눗셈을 안하는게좋음) --%>
</tr>
<tr>
<td>\${2+=5}</td>
<td>${2+=5}(문자열로 연결)</td>
</tr>
<tr>
<td>\${"한국"+="서울"}</td>
<td>${"한국"+="서울"}</td>
</tr>
</table>
</body>
</html>
2 + 5 >>7
"10" + 5 >>15
"10" + "5" >>15
모두 정수 연산
-------
4/5 >>Infinity / 실수 나눗셈 가능
-------
2 += 5 >>25 / 문자열로 연결
"한국" += "서울" >>한국서울
(3) EL의 연산자
- 수치 연산자 : +, - , *, / 또는 div, % 또는 mod
- 비교 연산자 : == 또는 eq, != 또는 ne, < 또는 lt, > 또는 gt, <= 또는 le, >= 또는 ge
- 논리 연산자 : && 또는 and, || 또는 or, ! 또는 not
- empty 연산자
1) 값이 null이면 true 반환
2) 값이 빈 문자열(“”)이면 true 반환
3) 값이 길이가 0인 배열이면 true 반환
3) 값이 빈 Map이면 true를 반환
4) 값이 빈 Collection이면 true를 반환
5) 이외의 경우에는 false를 반환
(4) EL의 기본객체
기본객체 | 설명 |
pageContext | JSP의 page 기본 객체와 동일 |
pageScope | pageContext 기본 객체에 저장된 속성의 <속성,값>매핑을 저장한 Map 객체 |
requestScope | request 기본 객체에 저장된 속성의 <속성,값> 매핑을 저장한 Map 객체 |
sessionScope | session 기본 객체에 저장된 속성의 <속성,값> 매핑을 저장한 Map객체 |
applicationScope | application 기본 객체에 저장된 속성의 <속성,값>매핑을 저장한 Map객체 |
param | 요청 파라미터의 <파라미터이름,값> 매핑을 저장한 Map객체 |
paramValues | 요청 정보의 <파라미터이름,값 배열> 매핑을 저장한 Map 객체 |
header | 요청 정보의 <헤더이름,값> 매핑을 저장한 Map 객체 |
headerValues | 요청 정보의 <헤더이름,값 배열> 매핑을 저장한 Map 객체 |
cookie | <쿠키 이름, Cookie> 매핑을 저장한 Map 객체 |
initParam | 초기화 파라미터의 <이름,값> 매핑을 저장한 Map 객체 |
내장객체1 (param)
s02_el.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
//전송받은 데이터 인코딩 처리 (아래에서 post로 자기 자신에게 보냈기 때문에)
request.setCharacterEncoding("utf-8");
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>EL의 내장객체</title>
</head>
<body>
<h3>EL의 사용 - 파라미터값 처리</h3>
<form action="s02_el.jsp" method="post">
이름 : <input type="text" name="name">
<input type="submit" value="확인">
</form>
<p>
이름은 <%= request.getParameter("name") %><br>
이름은 ${param.name}<br>
이름은 ${param["name"]}
</p>
</body>
</html>
el은 param이라는 내장객체로 값을 빼냄
보통 {param.name} 형태를 많이 씀
request와 param의 차이점
name 값이 없을 때
request = null
param = '' / 빈문자열
param이 null일 경우 자동으로 ''로 대체해서 출력해줌 (간편)
내장객체2 (scope)
s03_el.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>EL의 내장객체</title>
</head>
<body>
<%
pageContext.setAttribute("msg", "봄");
request.setAttribute("msg2", "여름");
session.setAttribute("msg3", "가을");
application.setAttribute("msg4", "겨울");
//내장객체 외에 다른걸 보려면 데이터를 세팅해야함 애초에 위 네개의 jsp 영역에 있는 것들을 읽기 위해 만들어진 거라서
String str = "겨울왕국";
%>
page 영역 : <%= pageContext.getAttribute("msg") %>, ${pageScope.msg}, ${msg}<br> <%-- 내장객체 생략 가능하기 때문에 ${변수명} 가능 --%>
request 영역 : <%= request.getAttribute("msg2") %>, ${requestScope.msg2}, ${msg2}<br>
session 영역 : <%= session.getAttribute("msg3") %>, ${sessionScope.msg3}, ${msg3}<br>
application 영역 : <%= application.getAttribute("msg4") %>, ${applicationScope.msg4}, ${msg4}<br>
str의 값 : <%= str %>, ${str}<br> <%-- 영역에 저장되어 있지 않아서 값을 빼내지 못함 --%>
</body>
</html>
el은 4개의 jsp 영역에 있는 데이터를 읽기 위해 만들어진거라
위처럼 String str="겨울왕국"; 이라고만 넣으면 값을 빼내지 못함
page, request, session, application 중에 하나에 값을 넣어야함
pageScope.msg 라고 빼낼 수있는데 scope내장객체는 생략이 가능해서 msg라고만 기재해도 데이터를 뽑아올 수 있음
jstl을 통해 데이터 셋팅 후 el을 사용하면 둘 다 이해가 쉽고 빠르게 되기 때문에 jstl+el 동시에 공부할 거임
jstl 공부하기 위해선 jar파일 필요
선생님이 공유해준 mbox에서 jstl-1.2.jar 파일 받고 lib안에 넣기
2) JSTL
- core 라이브러리
jsp 페이지에 core 라이브러리를 사용할 수 있도록 taglib 디렉티브 명시 (액션 태그가 아니라서 taglib 필수적으로 사용)
<%@ taglib prefix="c" uri=http://java.sun.com/jsp/jstl/core %>
prefix : 접두사
uri : core 라이브러리가 존재하는 위치 (핵심 lib가 들어가있는 유니크한 식별자)
ch21-jstls01_set.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>set 태그</title>
</head>
<body>
<%-- 속성명 속성값 저장영역 --%>
<c:set var="msg" value="봄" scope="page"/>
${pageScope.msg}, ${msg}<br>
</body>
</html>
(1) <c:set var="변수명" value="설정값" target="객체" property="값" scope="범위" />
<c:set></c:set> or <c:set/> 단독태그 가능
- 지정된 변수에 값을 할당하는 태그
target은 값을 설정하고자 하는 객체를 명시한다. target에 객체를 명시하면 명시된 객체에 값을 셋팅할 수 있다.
property는 taregt에 명시된 객체의 프로퍼티를 의미하며 명시된 프로퍼티에 value에 명시한 설정값을 셋팅합니다.
scope은 값을 셋팅한 범위를 의미(page,request,session,application), 생략하면 scope="page"
set태그로 자바빈을 만들 수도 있음
set태그 > 자바빈 넣기 > el의 get태그로 데이터 빼내기
간단하게 넣을거라 name만 짧게 명시 + getters sestters
ch05-ServletMain
src/main/java
kr.web.member (package)
Member (class)
package kr.web.member;
public class Member {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
다시 s01_set.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ page import="kr.web.member.Member" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>set 태그</title>
</head>
<body>
<%-- 속성명 속성값 저장영역(기본값:page) --%>
<c:set var="msg" value="봄" scope="page"/>
${pageScope.msg}, ${msg}<br>
<%
Member member = new Member();
%>
<c:set var="member" value="<%= member %>"/> <%-- scope을 명시하지 않으면 기본으로 page영역에 저장됨 --%>
<%-- 타겟객체 타객객체의멤버변수(프로퍼티) 저장할값--%>
<c:set target="${member}" property="name" value="홍길동"/>
회원 이름 : ${member.name}, ${member.getName()}<br>
</body>
</html>
Member 객체 생성
<c:set var="member" value="<%= %>"/> scope 명시 없으면 4개 영역 중 자동으로 page영역에 저장
<c:set target="${member}" property="name" value="홍길동"/> 객체/ 멤버변수/ 값 > 저장
${member.name} , ${member.getName()} 이 있는데 원래는 name으로 바로 빼내는 게 아니라
private이라서 getName()으로 빼내는 게 맞음
근데 el특성상 짧게 명시하기 위해 get없이 생략해서 빼낼 수 있도록 한 것