1. 개발 환경
- 운영체제(OS) : Window 7 Ultimate 64bit
- 이클립스(Eclipse Java EE IDE for Web Developers) : Kepler Release
- 웹 컨테이너(Web Container) : 톰캣(Tomcat) 6
- 오라클(ORACLE) : Oracle 10g XE
2. 프로젝트 파일
3. 프로젝트 구조
- Board_MVC : Dynamic Web Project
- Java Resources > src : 서블릿(Servlet), 빈(DAO, DTO) 객체, 커맨드(Command) 패턴 처리 클래스,
- WebContent : CSS 파일, JavaScript 파일, JSP 파일, SQL 파일
- WEB-INF : 커맨드(Command) 패턴 처리 설정(properties)파일, context.xml(DBCP), web.xml
- WEB-INF > lib : jstl 라이브러리, 오라클(oracle) 라이브러리, dbcp 라이브러리
4. DB 테이블 - board.sql
-- board.sql create table board( no number not null, -- 글번호 id varchar2(50) not null, -- 아이디 pwd varchar2(20) not null, -- 비밀번호 title varchar2(100) not null, -- 제목 content varchar2(4000) not null, -- 내용 regdate date not null, -- 작성일 hit number not null, -- 조회수 parent number not null, -- 부모 글 번호 sort number not null, -- 답글 정렬 번호 tab number not null, -- 들여 쓰기 constraint pk_board primary key(no) -- 글번호를 기본키로 설정 );
5. 자바스크립트 - board.js
// board.js function email_check() { if (boardform.email3.value == "self") { boardform.email2.style.display = "inline"; boardform.email2.value = ""; boardform.email2.readOnly = false; } else if (boardform.email3.value == "naver.com") { boardform.email2.style.display = "inline"; boardform.email2.value = boardform.email3.value; boardform.email2.readOnly = true; } else if (boardform.email3.value == "nate.com") { boardform.email2.style.display = "inline"; boardform.email2.value = boardform.email3.value; boardform.email2.readOnly = true; } else if (boardform.email3.value == "dreamwiz.com") { boardform.email2.style.display = "inline"; boardform.email2.value = boardform.email3.value; boardform.email2.readOnly = true; } else if (boardform.email3.value == "yahoo.co.kr") { boardform.email2.style.display = "inline"; boardform.email2.value = boardform.email3.value; boardform.email2.readOnly = true; } else if (boardform.email3.value == "empal.com") { boardform.email2.style.display = "inline"; boardform.email2.value = boardform.email3.value; boardform.email2.readOnly = true; } else if (boardform.email3.value == "unitel.co.kr") { boardform.email2.style.display = "inline"; boardform.email2.value = boardform.email3.value; boardform.email2.readOnly = true; } else if (boardform.email3.value == "gmail.com") { boardform.email2.style.display = "inline"; boardform.email2.value = boardform.email3.value; boardform.email2.readOnly = true; } else if (boardform.email3.value == "korea.com") { boardform.email2.style.display = "inline"; boardform.email2.value = boardform.email3.value; boardform.email2.readOnly = true; } else if (boardform.email3.value == "chol.com") { boardform.email2.style.display = "inline"; boardform.email2.value = boardform.email3.value; boardform.email2.readOnly = true; } else if (boardform.email3.value == "paran.com") { boardform.email2.style.display = "inline"; boardform.email2.value = boardform.email3.value; boardform.email2.readOnly = true; } else if (boardform.email3.value == "freechal.com") { boardform.email2.style.display = "inline"; boardform.email2.value = boardform.email3.value; boardform.email2.readOnly = true; } else if (boardform.email3.value == "hanmail.net") { boardform.email2.style.display = "inline"; boardform.email2.value = boardform.email3.value; boardform.email2.readOnly = true; } else if (boardform.email3.value == "hotmail.com") { boardform.email2.style.display = "inline"; boardform.email2.value = boardform.email3.value; boardform.email2.readOnly = true; } // if } // email_check function board_check(boardform) { var msg = null; var foc = null; if (boardform.email1.value == "") { msg = "이메일 앞자리를 입력해주세요"; foc = boardform.email1; } else if (boardform.email2.value == "") { msg = "이메일 뒷자리를 입력해주세요"; foc = boardform.email2; } else if (boardform.pwd.value == "") { msg = "비밀번호를 입력해주세요"; foc = boardform.pwd; } else if (boardform.title.value == "") { msg = "제목을 입력해주세요"; foc = boardform.title; } else if (boardform.content.value == "") { msg = "내용을 입력해주세요"; foc = boardform.content; } if (msg != null) { alert(msg); foc.focus(); return false; } boardform.id.value = boardform.email1.value + "@" + boardform.email2.value; // 이메일 합치기 boardform.submit(); } // board_check function board_list(boardform) { alert("리스트로 이동합니다"); document.location.href = "list.do" ; } // board_list function board_update_check(boardform) { var msg = null; var foc = null; if (boardform.pwd.value == "") { msg = "비밀번호를 입력해주세요"; foc = boardform.pwd; } else if (boardform.title.value == "") { msg = "제목을 입력해주세요"; foc = boardform.title; } else if (boardform.content.value == "") { msg = "내용을 입력해주세요"; foc = boardform.content; } if (msg != null) { alert(msg); foc.focus(); return false; } boardform.submit(); } // board_update_check function board_delete_check(boardform) { var msg = null; var foc = null; if (boardform.pwd.value == "") { msg = "비밀번호를 입력해주세요"; foc = boardform.pwd; } if (msg != null) { alert(msg); foc.focus(); return false; } boardform.submit(); } // board_delete_check function board_cancle() { alert("이전 페이지로 돌아 갑니다."); history.back(); } // board_cancle
6. CSS - board.css
/* board.css */ @CHARSET "UTF-8"; * { margin: 0; padding: 0; } li { list-style: none; } a { text-decoration: none; } img { border: 0; } th { text-align: right; width: 120px; padding-right: 5px; color: #ffffff; font-size: 12px; text-shadow: 2px 2px 10px #000000; filter: dropshadow(color=#000000, offx=2, offy=2); background: #7d7e7d; /* Old browsers */ background: -moz-linear-gradient(top, #7d7e7d 0%, #0e0e0e 100%); /* FF3.6+ */ background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#7d7e7d), color-stop(100%,#0e0e0e)); /* Chrome,Safari4+ */ background: -webkit-linear-gradient(top, #7d7e7d 0%,#0e0e0e 100%); /* Chrome10+,Safari5.1+ */ background: -o-linear-gradient(top, #7d7e7d 0%,#0e0e0e 100%); /* Opera 11.10+ */ background: -ms-linear-gradient(top, #7d7e7d 0%,#0e0e0e 100%); /* IE10+ */ background: linear-gradient(to bottom, #7d7e7d 0%,#0e0e0e 100%); /* W3C */ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#7d7e7d', endColorstr='#0e0e0e',GradientType=0 ); /* IE6-9 */ } th.list { text-align: center; height: 30px; color: #ffffff; font-size: 12px; text-shadow: 2px 2px 10px #000000; filter: dropshadow(color=#000000, offx=2, offy=2); background: #7d7e7d; /* Old browsers */ background: -moz-linear-gradient(top, #7d7e7d 0%, #0e0e0e 100%); /* FF3.6+ */ background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#7d7e7d), color-stop(100%,#0e0e0e)); /* Chrome,Safari4+ */ background: -webkit-linear-gradient(top, #7d7e7d 0%,#0e0e0e 100%); /* Chrome10+,Safari5.1+ */ background: -o-linear-gradient(top, #7d7e7d 0%,#0e0e0e 100%); /* Opera 11.10+ */ background: -ms-linear-gradient(top, #7d7e7d 0%,#0e0e0e 100%); /* IE10+ */ background: linear-gradient(to bottom, #7d7e7d 0%,#0e0e0e 100%); /* W3C */ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#7d7e7d', endColorstr='#0e0e0e',GradientType=0 ); /* IE6-9 */ } th.read { text-align: center; height: 20px; color: #ffffff; font-size: 12px; text-shadow: 2px 2px 10px #000000; filter: dropshadow(color=#000000, offx=2, offy=2); background: #7d7e7d; /* Old browsers */ background: -moz-linear-gradient(top, #7d7e7d 0%, #0e0e0e 100%); /* FF3.6+ */ background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#7d7e7d), color-stop(100%,#0e0e0e)); /* Chrome,Safari4+ */ background: -webkit-linear-gradient(top, #7d7e7d 0%,#0e0e0e 100%); /* Chrome10+,Safari5.1+ */ background: -o-linear-gradient(top, #7d7e7d 0%,#0e0e0e 100%); /* Opera 11.10+ */ background: -ms-linear-gradient(top, #7d7e7d 0%,#0e0e0e 100%); /* IE10+ */ background: linear-gradient(to bottom, #7d7e7d 0%,#0e0e0e 100%); /* W3C */ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#7d7e7d', endColorstr='#0e0e0e',GradientType=0 ); /* IE6-9 */ } td.center { text-align: center; font-size: 14px; } td.left { text-align: left; font-size: 14px; } input[type=button], input[type=reset], button.linkbutton { color: #ffffff; font-size: 14px; padding: 10px; text-shadow: 2px 2px 10px #000000; filter: dropshadow(color=#000000, offx=2, offy=2); background: #7d7e7d; /* Old browsers */ background: -moz-linear-gradient(top, #7d7e7d 0%, #0e0e0e 100%); /* FF3.6+ */ background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#7d7e7d), color-stop(100%,#0e0e0e)); /* Chrome,Safari4+ */ background: -webkit-linear-gradient(top, #7d7e7d 0%,#0e0e0e 100%); /* Chrome10+,Safari5.1+ */ background: -o-linear-gradient(top, #7d7e7d 0%,#0e0e0e 100%); /* Opera 11.10+ */ background: -ms-linear-gradient(top, #7d7e7d 0%,#0e0e0e 100%); /* IE10+ */ background: linear-gradient(to bottom, #7d7e7d 0%,#0e0e0e 100%); /* W3C */ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#7d7e7d', endColorstr='#0e0e0e',GradientType=0 ); /* IE6-9 */ }
7. 웹 컨테이너 설정 - web.xml(서블릿 설정), context.xml(DBCP)
Board_MVC BoardController BoardController controller.com.tistory.gangzzang.BoardController configFile /WEB-INF/board.properties BoardController *.do
WEB-INF/web.xml
8. Model - BoardDAO(CRUD 데이터 로직 처리), BoardDTO(데이터 저장 반환), UtillDB(DBCP 연결, DB 연결 종료)
// BoardDAO.java - 싱글톤 패턴 사용 package model.com.tistory.gangzzang; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; public class BoardDAO { private static BoardDAO instance = new BoardDAO(); public static BoardDAO getInstance() { return instance; } private BoardDAO() {} public int insertBoard(BoardDTO dto) { int re = 0; Connection con = null; PreparedStatement ps = null; String sql = "INSERT INTO board(no,id,pwd,title,content,regdate,hit,parent,sort,tab) " + "VALUES((SELECT NVL(MAX(no),0)+1 FROM board),?,?,?,?,SYSDATE,0,(SELECT NVL(MAX(no),0)+1 FROM board),0,0)"; try { con = UtillDB.getCon(con); ps = con.prepareStatement(sql); ps.setString(1, dto.getId()); ps.setString(2, dto.getPwd()); ps.setString(3, dto.getTitle()); ps.setString(4, dto.getContent()); re = ps.executeUpdate(); } catch (SQLException e) { e.printStackTrace(); } finally { UtillDB.closeDB(con, ps); } // try - catch - finally return re; } // insertBoard() : 게시글쓰기 public ArrayListlistBoard(int begin, int end) { ArrayList list = new ArrayList (); Connection con = null; PreparedStatement ps = null; ResultSet rs = null; String sql = "SELECT rn,no,id,pwd,title,content,regdate,hit,parent,sort,tab FROM " + "(SELECT Rownum as rn,no,id,pwd,title,content,regdate,hit,parent,sort,tab FROM " + "(SELECT no,id,pwd,title,content,regdate,hit,parent,sort,tab FROM board ORDER BY parent DESC, sort ASC)) WHERE rn >=? AND rn <=?"; try { con = UtillDB.getCon(con); ps = con.prepareStatement(sql); ps.setInt(1, begin); ps.setInt(2, end); rs = ps.executeQuery(); while (rs.next()) { BoardDTO dto = new BoardDTO(); dto.setNo(rs.getInt("no")); dto.setId(rs.getString("id")); dto.setPwd(rs.getString("pwd")); dto.setTitle(rs.getString("title")); dto.setContent(rs.getString("content")); dto.setRegdate(rs.getDate("regdate")); dto.setHit(rs.getInt("hit")); dto.setParent(rs.getInt("parent")); dto.setSort(rs.getInt("sort")); dto.setTab(rs.getInt("tab")); list.add(dto); } // while } catch (SQLException e) { e.printStackTrace(); } finally { UtillDB.closeDB(con, ps, rs); } // try - catch - finally return list; } // listBoard() : 게시글 목록 public int getTotal() { int cnt = 0; Connection con = null; PreparedStatement ps = null; ResultSet rs = null; String sql = "SELECT COUNT(*) cnt FROM board"; try { con = UtillDB.getCon(con); ps = con.prepareStatement(sql); rs = ps.executeQuery(); if (rs.next()) cnt = rs.getInt("cnt"); } catch (SQLException e) { e.printStackTrace(); } finally { UtillDB.closeDB(con, ps, rs); } // try - catch - finally return cnt; } // getTotal() : 총 게시글의 수 public BoardDTO getBoard(String no) { BoardDTO dto = new BoardDTO(); Connection con = null; PreparedStatement ps = null; ResultSet rs = null; String sql = "SELECT no,id,pwd,title,content,regdate,hit,parent,sort,tab FROM board WHERE no=?"; try { con = UtillDB.getCon(con); ps = con.prepareStatement(sql); ps.setString(1, no); rs = ps.executeQuery(); if (rs.next()) { dto.setNo(rs.getInt("no")); dto.setId(rs.getString("id")); dto.setPwd(rs.getString("pwd")); dto.setTitle(rs.getString("title")); dto.setContent(rs.getString("content")); dto.setRegdate(rs.getDate("regdate")); dto.setHit(rs.getInt("hit")); dto.setParent(rs.getInt("parent")); dto.setSort(rs.getInt("sort")); dto.setTab(rs.getInt("tab")); } // if } catch (SQLException e) { e.printStackTrace(); } finally { UtillDB.closeDB(con, ps, rs); } // try - catch - finally return dto; } // getBoard() : 하나의 게시글 가져오기 public void updateHit(String no) { Connection con = null; PreparedStatement ps = null; String sql = "UPDATE board SET hit=hit+1 WHERE no=?"; try { con = UtillDB.getCon(con); ps = con.prepareStatement(sql); ps.setString(1, no); ps.executeUpdate(); } catch (SQLException e) { e.printStackTrace(); } finally { UtillDB.closeDB(con, ps); } // try - catch - finally } // updateHit() : 조회수 증가 public int updateBoard(BoardDTO dto) { int re = 0; Connection con = null; PreparedStatement ps = null; String sql = "UPDATE board SET title=?, content=?, regdate=SYSDATE WHERE no=? AND pwd=?"; try { con = UtillDB.getCon(con); ps = con.prepareStatement(sql); ps.setString(1, dto.getTitle()); ps.setString(2, dto.getContent()); ps.setInt(3, dto.getNo()); ps.setString(4, dto.getPwd()); re = ps.executeUpdate(); } catch (SQLException e) { e.printStackTrace(); } finally { UtillDB.closeDB(con, ps); } // try - catch - finally return re; } // updateBoard() : 게시글 수정 public int deleteBoard(String no, String pwd) { int re = 0; Connection con = null; PreparedStatement ps = null; String sql = "DELETE FROM board WHERE no=? AND pwd=?"; try { con = UtillDB.getCon(con); ps = con.prepareStatement(sql); ps.setString(1, no); ps.setString(2, pwd); re = ps.executeUpdate(); } catch (SQLException e) { e.printStackTrace(); } finally { UtillDB.closeDB(con, ps); } return re; } // deleteBoard() : 게시글 삭제 public void updateReplySort(BoardDTO dto) { Connection con = null; PreparedStatement ps = null; String sql ="UPDATE board SET sort=sort+1 WHERE parent=? AND sort>?"; try { con = UtillDB.getCon(con); ps = con.prepareStatement(sql); ps.setInt(1, dto.getParent()); ps.setInt(2, dto.getSort()); ps.executeUpdate(); } catch (SQLException e) { e.printStackTrace(); } finally { UtillDB.closeDB(con, ps); } // try - catch - finally } // updateReplySort() : 답글 정렬 public int insertReply(BoardDTO dto) { int re = 0; Connection con = null; PreparedStatement ps = null; String sql = "INSERT INTO board(no,id,pwd,title,content,regdate,hit,parent,sort,tab) " + "VALUES((SELECT NVL(MAX(no),0)+1 FROM board),?,?,?,?,SYSDATE,0,?,?,?)"; try { con = UtillDB.getCon(con); ps = con.prepareStatement(sql); ps.setString(1, dto.getId()); ps.setString(2, dto.getPwd()); ps.setString(3, dto.getTitle()); ps.setString(4, dto.getContent()); ps.setInt(5, dto.getParent()); ps.setInt(6, dto.getSort()); ps.setInt(7, dto.getTab()); System.out.println("re " + re); re = ps.executeUpdate(); System.out.println("re " + re); } catch (SQLException e) { e.printStackTrace(); } finally { UtillDB.closeDB(con, ps); } // try - catch - finally return re; } // insertReply() : 답글 쓰기 } // BoardDAO
// BoardDTO.java package model.com.tistory.gangzzang; import java.util.Date; public class BoardDTO { private int no; // 글번호 private String id; // 아이디 private String pwd; // 비밀번호 private String title; // 제목 private String content; // 내용 private Date regdate; // 작성일 private int hit; // 조회수 private int parent; // 글 그룹 번호 private int sort; // 답글 정렬 번호 private int tab; // 들여 쓰기 public BoardDTO() { super(); } public BoardDTO(int no, String id, String pwd, String title, String content, Date regdate, int hit, int parent, int sort, int tab) { super(); this.no = no; this.id = id; this.pwd = pwd; this.title = title; this.content = content; this.regdate = regdate; this.hit = hit; this.parent = parent; this.sort = sort; this.tab = tab; } public int getNo() { return no; } public void setNo(int no) { this.no = no; } public String getId() { return id; } public void setId(String id) { this.id = id; } public String getPwd() { return pwd; } public void setPwd(String pwd) { this.pwd = pwd; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getContent() { return content; } public void setContent(String content) { this.content = content; } public Date getRegdate() { return regdate; } public void setRegdate(Date regdate) { this.regdate = regdate; } public int getHit() { return hit; } public void setHit(int hit) { this.hit = hit; } public int getParent() { return parent; } public void setParent(int parent) { this.parent = parent; } public int getSort() { return sort; } public void setSort(int sort) { this.sort = sort; } public int getTab() { return tab; } public void setTab(int tab) { this.tab = tab; } } // BoardDTO
// UtillDB.java package model.com.tistory.gangzzang; 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; public class UtillDB { public static Connection getCon(Connection con) { try { Context context = new InitialContext(); DataSource dataSource = (DataSource) context.lookup("java:comp/env/jdbc/oracle"); con = dataSource.getConnection(); } catch (NamingException e) { System.out.println("NamingException : " + e.getMessage()); } catch (SQLException e) { System.out.println("SQLException : " + e.getMessage()); } catch (Exception e) { System.out.println("Exception : " + e.getMessage()); } // try - catch return con; } // getCon() : Connection 객체를 DBCP 연결 후에 리턴 public static void closeDB(Connection con, PreparedStatement ps, ResultSet rs) { if (rs != null) { try { rs.close(); } catch (Exception e) { } } if (ps != null) { try { ps.close(); } catch (Exception e) { } } if (con != null) { try { con.close(); } catch (Exception e) { } } } // closeDB() : SELECT DB 연결 종료 public static void closeDB(Connection con, PreparedStatement ps) { if (ps != null) { try { ps.close(); } catch (Exception e) { } } if (con != null) { try { con.close(); } catch (Exception e) { } } } // closeDB() : SELECT 외 DB 연결 종료 } // UtillDB
9. Controller - BoardController.java
// BoardController.java package controller.com.tistory.gangzzang; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Properties; import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import action.com.tistory.gangzzang.Action; import action.com.tistory.gangzzang.NullAction; public class BoardController extends HttpServlet { private static final long serialVersionUID = 1L; private MapcommandHandlerMap = new HashMap (); @Override public void init() throws ServletException { String configFile = getInitParameter("configFile"); Properties prop = new Properties(); FileInputStream fis = null; try { String configFilePath = getServletContext().getRealPath(configFile); fis = new FileInputStream(configFilePath); prop.load(fis); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { if (fis != null) {try { fis.close(); } catch (IOException ex) { } } } // try - catch - finally Iterator keyIter = prop.keySet().iterator(); while (keyIter.hasNext()) { String command = (String) keyIter.next(); String actionClassName = prop.getProperty(command); try { Class actionClass = Class.forName(actionClassName); Action actionInstance = (Action) actionClass.newInstance(); commandHandlerMap.put(command, actionInstance); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } // try - catch } // while } // init() public BoardController() { super(); } // BoardConroller 생성자 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { processRequest(request, response); } // doGet() protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { processRequest(request, response); } // doPost() private void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("UTF-8"); String command = request.getRequestURI(); if (command.indexOf(request.getContextPath()) == 0) command = command.substring(request.getContextPath().length()); Action action = commandHandlerMap.get(command); if (action == null) action = new NullAction(); String viewPage = null; viewPage = action.process(request, response); RequestDispatcher dispatcher = request.getRequestDispatcher(viewPage); dispatcher.forward(request, response); } // processRequest() } // BoardConroller
10. 요청 URI 처리 클래스 지정 - board.properties
# board.properties
/list.do=action.com.tistory.gangzzang.ListAction
/writeForm.do=action.com.tistory.gangzzang.WriteProcAction
/write.do=action.com.tistory.gangzzang.WriteAction
/read.do=action.com.tistory.gangzzang.ReadAction
/reply.do=action.com.tistory.gangzzang.ReplyAction
/update.do=action.com.tistory.gangzzang.UpdateAction
/delete.do=action.com.tistory.gangzzang.DeleteAction
/updateProc.do=action.com.tistory.gangzzang.UpdateProcAction
/deleteProc.do=action.com.tistory.gangzzang.DeleteProcAction
/replyProc.do=action.com.tistory.gangzzang.ReplyProcAction
11. View - JSP 파일들 (너무많아서 생략합니다.)
12. 실행화면 - 주소표시줄 맨뒤에 list.do 또는 writeform.jsp 를 실행하세요
'Java > Java EE' 카테고리의 다른 글
톰캣(Tomcat) 커넥션풀(DBCP) 설정 (2) | 2013.10.01 |
---|---|
JSP 커스텀 태그(Custom Tag) - 태그파일 (0) | 2013.09.30 |
JSP JSTL(JSP Standard Tag Library) - 국제화 태그(포맷팅) (1) | 2013.09.30 |
JSP JSTL(JSP Standard Tag Library) - 함수 태그(functions) (2) | 2013.09.29 |
JSP JSTL(JSP Standard Tag Library) - 코어 태그(core) (6) | 2013.09.23 |