열심히 끝까지

디바이스 융합 자바(Java) day71 - @RequestParam, @ModelAttribute, @SessionAttributes 본문

디바이스 융합 자바(Java)기반 풀스택 개발자 양성과정(수업내용)

디바이스 융합 자바(Java) day71 - @RequestParam, @ModelAttribute, @SessionAttributes

노유림 2022. 9. 22. 18:09

[오늘 수업]


<활용도가 높지는 않지만 중요하게 생각하는 것(개발자 입장), 
  별도의 더 나은 방향이 없는 어노테이션, 만날 확률이 높은 것>


> @(어노테이션)
    - @RequestParam : 커맨드 객체에는 없는 파라미터를 Controller 클래스에 전달해주기 위해 사용
    - @ModelAttribute : View에서 사용할 데이터를 Controller에서 설정하는 용도로 사용 
    - @SessionAttributes : 세션정보를 저장하지 않아도 @SessionAttribute를 이용하여 동일 이름의 

                                         데이터 값을 Model 객체에 새팅하게 되면 필요한 값을 Null값이 아닌 값으로 

                                         저장하도록 설정

 


 



[@RequestParam]


   >> 검색하는 것의 값을 자동매핑 불가(커맨드 객체에는 없기 때문에 불가)
           java에서만 사용할 목적으로 BoardVO에 추가
           >> 하지만 전체에서 딱 한번 쓰는 등의 너무 비효율적일 때, 사용하는 @
                 ==> @RequestParam
                         : 커맨드(command) 객체에는 없는 파라미터를 Controller 클래스에 전달해주기 위해 사용

>> 최적은 아님. requestParam 안쓰고 vo에 추가하는 것이 더 나음
@RequestParam(value="searchCondition", defaultValue="TITLE", required=false)String searchCondition
ex ) 

public String xx(@RequestParam(value="sc", defaultValue="TITLE", required=false)String SearchCondition)
               >> required : 필수인가 아닌가?
                                 : API에서 필수로 받아 넣음

// 메인 페이지
@RequestMapping("/main.do")
public String main(@RequestParam(value="searchCondition", defaultValue="TITLE", required=false)String searchCondition, @RequestParam(value="searchContent", defaultValue="", required=false)String searchContent,BoardVO bVO, BoardDAO bDAO,Model model){
	// 검색하는 것의 값을 자동매핑 불가(커맨드 객체에는 없기 때문에 불가)
	// java에서만 사용할 목적으로 BoardVO에 추가
	// >> 하지만 전체에서 딱 한번 쓰는 등의 너무 비효율적일 때, 사용하는 @
	//    ==> @RequestParam
	//        : 커맨드 객체에는 없는 파라미터를 Controller 클래스에 전달해주기 위해 사용
	System.out.println("검색조건: "+searchCondition);
	 System.out.println("검색어: "+searchContent);
	List<BoardVO> datas = bDAO.selectAllBoard(bVO);
		
	model.addAttribute("datas", datas);
	return "main.jsp";
}



 


 

 


[@ModelAttribute]


- View 작업자 입장에서...
       > 검색 기능이 있습니다. 라는 회의를 진행
          > 음.... 검색할 공간을 확보해야겠군.....
             제목/내용/작성자/... => 칼럼을 알아야 만들 수 있는 걸 나에게 맡기는 상황
    이런 애매한 중간 중재를 해주는 @ 존재==[@ModelAttribute]

- Controller 작업자가
       > View 작업자야, 신경쓰지마.
          내가 값들 넘겨줄게! 라고 요청
             
  >> View에서 사용할 데이터를 Controller에서 설정하는 용도로 사용 
  >> @RequestMapping 메서드보다 먼저 호출됨
  >> @ModelAttribute 메서드는 실행 이후에 객체를 반환하는데, 이 반환값은 Model에 자동 저장됨
  >> Model에 자동저장되기 때문에, View에서 사용 가능!!!

 

// main에 넣을 구분값
@ModelAttribute("scMap")
public Map<String,String> searchConditionMap(){
	// 인자 없고 맵 반환 예정
	// 검색 조건에 들어가야 할 맵
	Map<String,String> scMap = new HashMap<String,String>();
	// 옵션에 들어갈 내용 관리 : View에 어떻게 보여야 할지 Model이 어떤 값을 받아야 할지
	scMap.put("제목", "TITLE");
	scMap.put("작성자", "WRITER");
	// modeladdattribute 된 상태
	return scMap;
}

-- main에 검색 로직에서 위의 값 받아서 출력

<form action="main.do" method="post">
	<table>
		<thead>
			<tr>
				<th>
					<select name="searchCondition">
						<c:forEach var="v" items="${scMap}">
						<!-- 키 값과 VALUE값 볼수 있게 작업 -->
							<option value="${v.value}">${v.key}</option>
						</c:forEach>
						<!-- 
						<option value="TITLE">제목</option>
						<option value="WRITER">작성자</option>
						-->
						</select>
				</th>
				<th><input type="text" name="searchContent" placeholder="검색어를 입력하세요..."></th>
				<th><input type="submit" class="button" value="search"></th>
			</tr>	
		</thead>
	</table>
</form>

 

 

 


 



[@SessionAttributes]


>> NULL 업데이트 이슈 : @SessionAttributes  
   ex ) 
       > 업무 사이즈가 커지면 커질 수록 MVC가 서로 관여 안하고 자기 파트에 신경 씀
       > View 작업자
          - mypage 작업 중
            >> ID, ROLE(계정권한)은 마이페이지에서 바꿀 수 없음

      : View 작업자가 기능만 알고, 내부 로직은 모름
      : 때문에 필요한 데이터인데 전달되지 않는 파라미터 발생
      : 전달되지 않은 파라미터의 값은 null이 됨
        >> null값이 업데이트 될 수도 있음!


그 때 사용하는 것이 "@SessionAttribute"


"NULL 업데이트 방지"
     : @SessionAttributes를 사용하게 됨 
     : class 위에 작성
           1) 사용자 요청 시, @SessionAttributes에 설정된 이름으로 Model에 저장
           2) Model에 메서드 수행 후 @SessionAttribute에 설정한 이름으로 저장된 데이터가 존재한다면,
                해당 데이터를 세션에도 자동으로 저장하겠다는 설정
     : @ModelAttribute("이름") -> Controller의 메서드 인자 == Command 객체 앞에 붙이면
          해당 "이름"을 가진 데이터와 메서드 인자(==Command 객체)가 동일하다는 설정이 됨

   ex ) public String bupdate(@ModelAttribute("data")BoardVO bVO, BoardDAO bDAO)
      >> data라는 이름을 가진 데이터는 BoardVO bVO다? 라고 말하는 것
     : 만약 로그인으로 사용하게 되면  
     
     [순서]
    1. @SessionAttributes를 달고 난 후,
              사용자 요청이 들어오면, 메서드는 @SessionAttributes에 설정된 이름으로 Model에 저장
    2. Model에 @SessionAttribute에 설정된 이름으로 저장된 데이터가 존재하면
              그 데이터를 세션에도 자동저장해줘~ 라는 설정
           ex ) 
              상세 화면이 출력되면 model에 데이터란 이름으로 등록하기 때문에 
               Model에서는 저장할게~ 가 되는 것
    3. NULL 업데이트 이슈가 발생할 법한 메서드의 인자에게 @ModelAttribute를 설정하면,
              @SessionAttribute에 의해 저장되어 있던 데이터가 자동매핑됨
              : 그 위에 사용자가 추가하는 값을 얹어서 저장(총 매핑을 두번 진행)

 

 


  >> 순서를 도저히 모르겠으면 로그를 몇개씩 찍어 볼 것
    1. 데이터를 저장하기 때문에 엄청 무거움
    2. Null 업데이트를 마구 걸어놓으면 데이터가 지워져있어야 할 때, 지워지지 않음
    3. 세션정보를 저장하지 않아도 @SessionAttribute을 하게 되면 자동 저장됨

 

@Controller
@SessionAttributes("data") // "data"라는 이름의 데이터가 Model 객체에 세팅이 된다면, 그 것을 session에 기억시키겠다.
public class BoardController{

	// 글 업데이트
	@RequestMapping("/bupdate.do")
	public String bupdate(@ModelAttribute("data")BoardVO bVO, BoardDAO bDAO) {
		
		bDAO.updateBoard(bVO);
		
		return "redirect:main.do";
	}
}
@Controller
@SessionAttributes("member")
public class MemberController {
	
	// 멤버 업데이트
	@RequestMapping("/mupdate.do")
	public String mupdate(@ModelAttribute("member")MemberVO mVO, MemberDAO mDAO) { // MemberVO mVO, MemberDAO mDAO,HttpSession session
		
		System.out.println("데이터 확인 : " + mVO);
		
		mDAO.updateMember(mVO);
		// session.setAttribute("user", mVO);
		return "redirect:main.do";
	}
	// 마이페이지
	@RequestMapping("/mypage.do")
	public String mypage(HttpSession session, Model model) { // (MemberVO mVO, MemberDAO mDAO)
		// mVO = mDAO.selectOneMember(mVO);
		model.addAttribute("member",session.getAttribute("user"));
		return "mypage.jsp";
	}
}

 

>> 좀 더 이해하고 MemberDelete를 @ModelAttribute로 바꿔 볼려고 함

 

 


 

 

[오늘 바뀐 코드 정리]

>> 비교하고싶으면 디바이스 융합 자바 day70 보고 올 것

-------BoardController.java << mainController 넣어서 하나로 묶음

package com.ryo.biz.controller;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

//import javax.servlet.http.HttpServletRequest;
//import javax.servlet.http.HttpServletResponse;
//import javax.servlet.http.HttpSession;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.SessionAttributes;
//import org.springframework.web.servlet.ModelAndView;

import com.ryo.biz.board.BoardVO;
import com.ryo.biz.board.impl.BoardDAO;

@Controller
@SessionAttributes("data") // "data"라는 이름의 데이터가 Model 객체에 세팅이 된다면, 그 것을 session에 기억시키겠다.
public class BoardController{

	// main에 넣을 구분값
	@ModelAttribute("scMap")
	public Map<String,String> searchConditionMap(){
		// 인자 없고 맵 반환 예정
		// 검색 조건에 들어가야 할 맵
		Map<String,String> scMap = new HashMap<String,String>();
		// 옵션에 들어갈 내용 관리 : View에 어떻게 보여야 할지 Model이 어떤 값을 받아야 할지
		scMap.put("제목", "TITLE");
		scMap.put("작성자", "WRITER");
		// modeladdattribute 된 상태
		return scMap;
	}
	
	// main
	// API 분석 때 필요할 것, VO에 넣는 것이 좋음
	@RequestMapping("/main.do")
	public String main(@RequestParam(value="searchCondition", defaultValue="TITLE", required=false)String searchCondition, @RequestParam(value="searchContent", defaultValue="", required=false)String searchContent,BoardVO bVO, BoardDAO bDAO,Model model){
		// 검색하는 것의 값을 자동매핑 불가(커맨드 객체에는 없기 때문에 불가)
		// java에서만 사용할 목적으로 BoardVO에 추가
		// >> 하지만 전체에서 딱 한번 쓰는 등의 너무 비효율적일 때, 사용하는 @
		//    ==> @RequestParam
		//        : 커맨드 객체에는 없는 파라미터를 Controller 클래스에 전달해주기 위해 사용
		System.out.println("검색조건: "+searchCondition);
	    System.out.println("검색어: "+searchContent);
		List<BoardVO> datas = bDAO.selectAllBoard(bVO);
		
		
		model.addAttribute("datas", datas);
		// mVO = mDAO.selectOneMember(mVO);
		// model.addAttribute("userName", mVO.getName());
		return "main.jsp";
	}
	
	// 글 하나 선택
	@RequestMapping("/board.do")
	public String board(BoardVO bVO, BoardDAO bDAO,Model model){

		bVO=bDAO.selectOneBoard(bVO);
		// mav.addObject("data", bVO);
		model.addAttribute("data", bVO);
		return "board.jsp";
	}
	
	// 글 추가.jsp로 이동
	@RequestMapping(value="/binsert.do", method=RequestMethod.GET)
	public String binsertin() {
		return "insertBoard.jsp";
	}
	
	// 글 추가
	// get과 post일 때로 나눌 것 get은 이동 post일 때는 
	@RequestMapping(value="/binsert.do", method=RequestMethod.POST)
	public String binsert(BoardVO bVO, BoardDAO bDAO) {
		
		bDAO.insertBoard(bVO);
		
		return "redirect:main.do";
	}

	// 글 삭제
	@RequestMapping("/bdelete.do")
	public String bdelete(BoardVO bVO, BoardDAO bDAO) {
		
		bDAO.deleteBoard(bVO);
		
		return "redirect:main.do";
	}
	
	// 글 업데이트
	@RequestMapping("/bupdate.do")
	public String bupdate(@ModelAttribute("data")BoardVO bVO, BoardDAO bDAO) {
		
		bDAO.updateBoard(bVO);
		
		return "redirect:main.do";
	}

}

-------MemberController.java

package com.ryo.biz.controller;

import javax.servlet.http.HttpServletRequest;
// import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
//import org.springframework.web.bind.annotation.SessionAttributes;
//import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.bind.annotation.SessionAttributes;

import com.ryo.biz.member.MemberVO;
import com.ryo.biz.member.impl.MemberDAO;

@Controller
@SessionAttributes("member")
public class MemberController {

	// 로그인으로 들어가는 index
	@RequestMapping(value="/login.do", method=RequestMethod.GET)
	public String index() {
		// 로그인 화면을 보여줘!
		// 기본이 포워드 방식
		// 데이터를 넣어서 보낼 때는 그냥 쓰면 됨
		return "login.jsp";
	}
	// POST 요청에서만 할 수 있게 가능
	// 로그인 및 세션에 정보 저장
	@RequestMapping(value="/login.do", method=RequestMethod.POST)
	public String selectOneMember(MemberVO mVO, MemberDAO mDAO, HttpSession session) {
		System.out.println("로그 : 로그인컨트롤러 들어옴");
		//ModelAndView mav = new ModelAndView();
		mVO = mDAO.selectOneMember(mVO);
		if(mVO == null){
			return "login.jsp";
		}
		else {
			session.setAttribute("user", mVO);
			return "redirect:main.do";
		}
	}

	// 로그아웃
	@RequestMapping("/logout.do")
	public String logout(HttpServletRequest request) {
		HttpSession session = request.getSession();
		session.invalidate();
		//view Resolver는 기본이 forward 방식이구나!
		return "redirect:login.do";
	}
	// 회원가입
	@RequestMapping("/signin.do")
	public String signin(MemberVO mVO, MemberDAO mDAO) {

		mDAO.insertMember(mVO);

		return "redirect:login.do";
	}
	
	// 멤버 삭제
	@RequestMapping("/mdelete.do")
	public String mdelete(HttpServletRequest request,MemberVO mVO, MemberDAO mDAO) {
		System.out.println(mVO.getMid());

		System.out.println("삭제하려는 mVO의 값 : " + mVO.getMid());
		mDAO.deleteMember(mVO);
		HttpSession session = request.getSession();
		session.invalidate();
		return "redirect:login.do";
	}
	
	// 멤버 업데이트
	@RequestMapping("/mupdate.do")
	public String mupdate(@ModelAttribute("member")MemberVO mVO, MemberDAO mDAO) { 
		
		System.out.println("데이터 확인 : " + mVO);
		
		mDAO.updateMember(mVO);
		return "redirect:main.do";
	}
	// 마이페이지
	@RequestMapping("/mypage.do")
	public String mypage(HttpSession session, Model model) { 
		model.addAttribute("member",session.getAttribute("user"));
		return "mypage.jsp";
	}
}

>> BoardVO, BoardDAO : 검색을 위해 searchCondition & searcthContent 작성

package com.ryo.biz.board;

public class BoardVO {
	private int bid;
	private String title;
	private String writer;
	private String content;
	private int cnt;
	private String regdate;
	private String searchCondition;
	private String searchContent;
	
	public int getBid() {
		return bid;
	}
	public void setBid(int bid) {
		this.bid = bid;
	}
	public String getTitle() {
		return title;
	}
	public void setTitle(String title) {
		this.title = title;
	}
	public String getWriter() {
		return writer;
	}
	public void setWriter(String writer) {
		this.writer = writer;
	}
	public String getContent() {
		return content;
	}
	public void setContent(String content) {
		this.content = content;
	}
	public int getCnt() {
		return cnt;
	}
	public void setCnt(int cnt) {
		this.cnt = cnt;
	}
	public String getRegdate() {
		return regdate;
	}
	public void setRegdate(String regdate) {
		this.regdate = regdate;
	}
	public String getSearchCondition() {
		return searchCondition;
	}
	public void setSearchCondition(String searchCondition) {
		this.searchCondition = searchCondition;
	}
	public String getSearchContent() {
		return searchContent;
	}
	public void setSearchContent(String searchContent) {
		this.searchContent = searchContent;
	}
	@Override
	public String toString() {
		return "BoardVO [bid=" + bid + ", title=" + title + ", writer=" + writer + ", content=" + content + ", cnt="
				+ cnt + ", regdate=" + regdate + "]";
	}
	
}

 

-----BoardDAO는 추가된 부분만 작성

final String sql_selectAll_T="SELECT * FROM BOARD WHERE TITLE LIKE '%'||?||'%' ORDER BY BID DESC";
final String sql_selectAll_W="SELECT * FROM BOARD WHERE WRITER LIKE '%'||?||'%' ORDER BY BID DESC";
    
public List<BoardVO> selectAllBoard(BoardVO vo) {
	List<BoardVO> datas=new ArrayList<BoardVO>();
	conn=JDBCUtil.connect();
	try {
		System.out.println("vo.getSearchCondition() : " + vo.getSearchCondition());
		if(vo.getSearchCondition()==null) {
			vo.setSearchCondition("TITLE");
		}
		if(vo.getSearchContent()==null) {
			vo.setSearchContent("");
		}
		String sql_selcetAll=sql_selectAll_T;
		if(vo.getSearchCondition().equals("WRITER")){
			sql_selcetAll=sql_selectAll_W;
		}
			
		//System.out.println("로그 : "+ sql_selcetAll);
		pstmt=conn.prepareStatement(sql_selcetAll);
		//System.out.println("로그 : "+ vo.getSearchContent());
		pstmt.setString(1, vo.getSearchContent());
			
		//pstmt=conn.prepareStatement(sql_selectAll);
		ResultSet rs=pstmt.executeQuery();
		while(rs.next()) {
			BoardVO data=new BoardVO();
			data.setBid(rs.getInt("BID"));
			data.setContent(rs.getString("CONTENT"));
			data.setTitle(rs.getString("TITLE"));
			data.setWriter(rs.getString("WRITER"));
			data.setCnt(rs.getInt("CNT"));
			data.setRegdate(rs.getString("REGDATE"));
			datas.add(data);
		}
	} catch (SQLException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	} finally {
		JDBCUtil.disconnect(pstmt, conn);
	}		
	return datas;
}

 

-----insertBoard.jsp 새로 작성

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE HTML>
<!--
	Stellar by HTML5 UP
	html5up.net | @ajlkn
	Free for personal and commercial use under the CCA 3.0 license (html5up.net/license)
-->
<html>
	<head>
		<title>insertBoard</title>
		<meta charset="utf-8" />
		<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" />
		<link rel="stylesheet" href="assets/css/main.css" />
		<noscript><link rel="stylesheet" href="assets/css/noscript.css" /></noscript>
	</head>
	<body class="is-preload">

		<!-- Wrapper -->
			<div id="wrapper">

				<!-- Main -->
					<div id="main">

						<!-- Introduction -->
							<section id="intro" class="main">
								<div class="spotlight">
									<div class="content">
										<header class="major">
											<h2>write</h2>
										</header>
										<form action="binsert.do" method="post">
										<table class="alt">
												<tbody>
													<tr>
														<td>제목</td>
														<td colspan="2"><input type="text" name="title" value="제목" required></td>
													</tr>
													<tr>
														<td>작성자</td>
														<td colspan="2"><input type="text" name="writer" value="${member.name}" required readonly></td>
													</tr>
													<tr>
														<td>내용</td>
														<td colspan="2"><input type="text" name="content" value="글쓰기" required></td>
													</tr>
													<tr>
														<td colspan="3" align="right"><input type="submit" class="button primary" value="글쓰기"> </td>
													</tr>
												</tbody>
										</table>
										</form>
										<a href="main.do">메인으로</a>
									</div>
									<span class="image"><img src="images/pic01.jpg" alt="" /></span>
								</div>
							</section>

					</div>

				<!-- Footer -->
					<footer id="footer">
						<section>
							<h2>Aliquam sed mauris</h2>
							<p>Sed lorem ipsum dolor sit amet et nullam consequat feugiat consequat magna adipiscing tempus etiam dolore veroeros. eget dapibus mauris. Cras aliquet, nisl ut viverra sollicitudin, ligula erat egestas velit, vitae tincidunt odio.</p>
							<ul class="actions">
								<li><a href="generic.html" class="button">Learn More</a></li>
							</ul>
						</section>
						<section>
							<h2>Etiam feugiat</h2>
							<dl class="alt">
								<dt>Address</dt>
								<dd>1234 Somewhere Road &bull; Nashville, TN 00000 &bull; USA</dd>
								<dt>Phone</dt>
								<dd>(000) 000-0000 x 0000</dd>
								<dt>Email</dt>
								<dd><a href="#">information@untitled.tld</a></dd>
							</dl>
							<ul class="icons">
								<li><a href="#" class="icon brands fa-twitter alt"><span class="label">Twitter</span></a></li>
								<li><a href="#" class="icon brands fa-facebook-f alt"><span class="label">Facebook</span></a></li>
								<li><a href="#" class="icon brands fa-instagram alt"><span class="label">Instagram</span></a></li>
								<li><a href="#" class="icon brands fa-github alt"><span class="label">GitHub</span></a></li>
								<li><a href="#" class="icon brands fa-dribbble alt"><span class="label">Dribbble</span></a></li>
							</ul>
						</section>
						<p class="copyright">&copy; Untitled. Design: <a href="https://html5up.net">HTML5 UP</a>.</p>
					</footer>

			</div>

		<!-- Scripts -->
			<script src="assets/js/jquery.min.js"></script>
			<script src="assets/js/jquery.scrollex.min.js"></script>
			<script src="assets/js/jquery.scrolly.min.js"></script>
			<script src="assets/js/browser.min.js"></script>
			<script src="assets/js/breakpoints.min.js"></script>
			<script src="assets/js/util.js"></script>
			<script src="assets/js/main.js"></script>

	</body>
</html>

 

------main.jsp : @ModelAttribute("scMap") 추가

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE HTML>
<!--
	Stellar by HTML5 UP
	html5up.net | @ajlkn
	Free for personal and commercial use under the CCA 3.0 license (html5up.net/license)
-->
<html>
	<head>
		<title>main</title>
		<meta charset="utf-8" />
		<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" />
		<link rel="stylesheet" href="assets/css/main.css" />
		<noscript><link rel="stylesheet" href="assets/css/noscript.css" /></noscript>
	</head>
	<body class="is-preload">

		<!-- Wrapper -->
			<div id="wrapper">

				<!-- Main -->
					<div id="main">

						<!-- Introduction -->
							<section id="intro" class="main">
								<div class="spotlight">
									<div class="content">
										<header class="major">
											<h2>main</h2>
										</header>
										<h2>HELLO , <a href="mypage.do">${user.name}</a> !&nbsp;&nbsp;:D &nbsp;&nbsp;<a href="logout.do">로그아웃</a></h2>
										
										<table>
											<thead>
												<tr>
													<th> <a href="binsert.do"><input type="button" class="button small" style="float: right;" value="글쓰기"></a></th>
												</tr>
											</thead>
										</table>
										<!-- 검색 -->
										<!-- main.do를 하는 이유는 메인 페이지를 보기 위해서 -->
										<form action="main.do" method="post">
											<table>
												<thead>
													<tr>
														<th>
															<select name="searchCondition">
															<c:forEach var="v" items="${scMap}">
															<!-- 키 값과 VALUE값 볼수 있게 작업 -->
																<option value="${v.value}">${v.key}</option>
															</c:forEach>
														    <!-- 
																<option value="TITLE">제목</option>
																<option value="WRITER">작성자</option>
															-->
															</select>
														</th>
														<th><input type="text" name="searchContent" placeholder="검색어를 입력하세요..."></th>
														<th><input type="submit" class="button" value="search"></th>
													</tr>	
												</thead>
											</table>
										</form>
										
										<div class="table-wrapper">
										<!-- 
										<form action="binsert.do" method="post">
											<table>
												<tr>
													<td><input type="text" name="title" value="제목" required></td>
													<td><input type="text" name="writer" value="${name}" required readonly></td>
													<td><input type="text" name="content" value="글쓰기" required></td>
													<td><input type="submit" class="button primary" value="글쓰기"></td>
												</tr>
											</table>
										</form>
										 -->
											<table>
												<thead>
													<tr>
														<th>num</th>
														<th>title</th>
														<th>writer</th>
														<th>content</th>
														<th>cnt</th>
														<th>regdate</th>
													</tr>	
												</thead>
												<tbody>
												<c:forEach var="b" items="${datas}">
													<tr>
														<td><a href="board.do?bid=${b.bid}">${b.bid}</a></td>
														<td>${b.title}</td>
														<td>${b.writer}</td>
														<td>${b.content}</td>
														<td>${b.cnt}</td>
														<th>${b.regdate}</th>
													</tr>
												</c:forEach>
												</tbody>
												<tfoot>
													<tr>
														<td colspan="5"></td>
														<td align="right"><a href="logout.do">logout</a></td>
													</tr>
												</tfoot>
											</table>
										</div>
									</div>
								</div>
							</section>

					</div>

				<!-- Footer -->
					<footer id="footer">
						<section>
							<h2>Aliquam sed mauris</h2>
							<p>Sed lorem ipsum dolor sit amet et nullam consequat feugiat consequat magna adipiscing tempus etiam dolore veroeros. eget dapibus mauris. Cras aliquet, nisl ut viverra sollicitudin, ligula erat egestas velit, vitae tincidunt odio.</p>
							<ul class="actions">
								<li><a href="generic.html" class="button">Learn More</a></li>
							</ul>
						</section>
						<section>
							<h2>Etiam feugiat</h2>
							<dl class="alt">
								<dt>Address</dt>
								<dd>1234 Somewhere Road &bull; Nashville, TN 00000 &bull; USA</dd>
								<dt>Phone</dt>
								<dd>(000) 000-0000 x 0000</dd>
								<dt>Email</dt>
								<dd><a href="#">information@untitled.tld</a></dd>
							</dl>
							<ul class="icons">
								<li><a href="#" class="icon brands fa-twitter alt"><span class="label">Twitter</span></a></li>
								<li><a href="#" class="icon brands fa-facebook-f alt"><span class="label">Facebook</span></a></li>
								<li><a href="#" class="icon brands fa-instagram alt"><span class="label">Instagram</span></a></li>
								<li><a href="#" class="icon brands fa-github alt"><span class="label">GitHub</span></a></li>
								<li><a href="#" class="icon brands fa-dribbble alt"><span class="label">Dribbble</span></a></li>
							</ul>
						</section>
						<p class="copyright">&copy; Untitled. Design: <a href="https://html5up.net">HTML5 UP</a>.</p>
					</footer>

			</div>

		<!-- Scripts -->
			<script src="assets/js/jquery.min.js"></script>
			<script src="assets/js/jquery.scrollex.min.js"></script>
			<script src="assets/js/jquery.scrolly.min.js"></script>
			<script src="assets/js/browser.min.js"></script>
			<script src="assets/js/breakpoints.min.js"></script>
			<script src="assets/js/util.js"></script>
			<script src="assets/js/main.js"></script>

	</body>
</html>

 

-----board.jsp : 글쓴이 혹은 운영자만 글 변경, 삭제 가능

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE HTML>
<!--
	Stellar by HTML5 UP
	html5up.net | @ajlkn
	Free for personal and commercial use under the CCA 3.0 license (html5up.net/license)
-->
<html>
	<head>
		<title>board</title>
		<meta charset="utf-8" />
		<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" />
		<link rel="stylesheet" href="assets/css/main.css" />
		<noscript><link rel="stylesheet" href="assets/css/noscript.css" /></noscript>
	</head>
	<body class="is-preload">

		<!-- Wrapper -->
			<div id="wrapper">

				<!-- Main -->
					<div id="main">

						<!-- Introduction -->
							<section id="intro" class="main">
								<div class="spotlight">
									<div class="content">
										<header class="major">
											<h2>board</h2>
										</header>
										<div class="table-wrapper">
											<form action="bupdate.do" method="post">
											<table>
												<thead>
													<tr>
														<th>title</th>
														<th>content</th>
														<th>writer</th>
														<th>regdate</th>
													</tr>	
												</thead>
												<tbody>
													<tr>
														<td><input type="text" name="title" value="${data.title}" required></td>
														<td><input type="text" name="content" value="${data.content}" required></td>
														<td>${data.writer}</td>
														<td><input type="datetime-local"  name="regdate" value="${data.regdate}"></td>
													</tr>
												</tbody>
												<tfoot>
												<c:if test="${data.writer==member.name || member.role == 'ADMIN'}">
													<tr>
														<td colspan="4" align="right"><input type="submit" class="button primary" value="글 변경">&nbsp;<a href="bdelete.do?bid=${data.bid}"><input type="button" class="button primary" value="글 삭제"></a> </td>
													</tr>
												</c:if>
													<tr>
														<td colspan="3"></td>
														<td><a href="main.do">main</a></td>
													</tr>
												</tfoot>
											</table>
											</form>
										</div>
									</div>
								</div>
							</section>

					</div>

				<!-- Footer -->
					<footer id="footer">
						<section>
							<h2>Aliquam sed mauris</h2>
							<p>Sed lorem ipsum dolor sit amet et nullam consequat feugiat consequat magna adipiscing tempus etiam dolore veroeros. eget dapibus mauris. Cras aliquet, nisl ut viverra sollicitudin, ligula erat egestas velit, vitae tincidunt odio.</p>
							<ul class="actions">
								<li><a href="generic.html" class="button">Learn More</a></li>
							</ul>
						</section>
						<section>
							<h2>Etiam feugiat</h2>
							<dl class="alt">
								<dt>Address</dt>
								<dd>1234 Somewhere Road &bull; Nashville, TN 00000 &bull; USA</dd>
								<dt>Phone</dt>
								<dd>(000) 000-0000 x 0000</dd>
								<dt>Email</dt>
								<dd><a href="#">information@untitled.tld</a></dd>
							</dl>
							<ul class="icons">
								<li><a href="#" class="icon brands fa-twitter alt"><span class="label">Twitter</span></a></li>
								<li><a href="#" class="icon brands fa-facebook-f alt"><span class="label">Facebook</span></a></li>
								<li><a href="#" class="icon brands fa-instagram alt"><span class="label">Instagram</span></a></li>
								<li><a href="#" class="icon brands fa-github alt"><span class="label">GitHub</span></a></li>
								<li><a href="#" class="icon brands fa-dribbble alt"><span class="label">Dribbble</span></a></li>
							</ul>
						</section>
						<p class="copyright">&copy; Untitled. Design: <a href="https://html5up.net">HTML5 UP</a>.</p>
					</footer>

			</div>

		<!-- Scripts -->
			<script src="assets/js/jquery.min.js"></script>
			<script src="assets/js/jquery.scrollex.min.js"></script>
			<script src="assets/js/jquery.scrolly.min.js"></script>
			<script src="assets/js/browser.min.js"></script>
			<script src="assets/js/breakpoints.min.js"></script>
			<script src="assets/js/util.js"></script>
			<script src="assets/js/main.js"></script>

	</body>
</html>