BACKEND/아파치 스트럿츠 1 , 2

[struts2] 스트럿츠2 + iBatis를 이용한 답변형 게시판 중 1 (글쓰기 , 수정 , 이전글 , 다음글 )

꾸준히개발하자 2022. 3. 14. 02:11

 

 

 

스트럿츠 2를 적용하여  게시판을 만들어보았습니다.

 

 

스트럿츠2 환경설정 세팅

기존에 struts1 에서 만들었던 com.util.dao(db연결)와 com.util 패키지(페이징 처리)를 가져온다. 

src에는 ibatis 환경세팅 , WEB-INF 에 라이브러리 파일에는 스트럿츠2 를 세팅했다.
WEB-INF 파일에서 class파일에 struts.properties 화일을 생성하여 환경 세팅 파일을 생성한다.

struts.i18n.encoding=UTF-8 : UTF-8로 인코딩

struts.action.extention=action : 스트럿츠에 움직이는 확장자는 기본적으로 action 이다.action이다.   나중에 Spring도 action이다.

struts.multipart.saveDir=c:\\temp : 아파치에서 파일 업로드하는 클래스에 파일업로드 하는 경로  
struts.configuration.files=struts-default.xml, struts.xml : 기본 환경 세팅 파일 2개

 

struts.xml : 우리가 만드는 환경설정 화일 

struts-default.xml : 기본적인 환경설정 화일 

 

 

struts-default.xml 의 가장 기본적인 환경설정 화일 

 

<?xml version="1.0" encoding="UTF-8"?>
<!-- 스트럿츠2 사용하기 위해 선언 -->
<!DOCTYPE struts
PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<!--  struts-default  : xml 파일을 불러옴  -->
<struts>
	<!-- extends = struts-default 는 struts.xml 화일를  불러온다. -->
	<package name="default" extends="struts-default" namespace="">
		<global-results>
			<result name="error">/exception/error.jsp</result>
		</global-results>
	</package>
    
    <!--  include : 또 다른 환경설정을 불러옴 여기다가 새로운 화일설정을 선언해주면 된다.  -->
	<include file="struts-test.xml"/>
	<include file="struts-board.xml"/>
</struts>

struts.xml 에서 환경설정을 등록해준다.

 

 

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts
PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">

<struts>
	<!-- temp는 이 패키지의 고유 이름을 적는 곳 -->
	<package name="temp" extends="default" namespace="/temp">
	
	
	</package>
    
    <!-- 패키지는 여러개 만들수있다. -->
</struts>

 

복사용 struts-temp.xml를 만들어놓는다.

 

<%@ page contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> 
<%
	request.setCharacterEncoding("UTF-8");
	String cp = request.getContextPath();
%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>

<h3>Struts2 Framework</h3>

</body>
</html>

index.jsp 웹서버 테스트

 

일단 기본적인 웹서버로 start 시켜본다. (톰켓 서버 자체는 이상이 없다)

 

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE tiles-definitions
PUBLIC "-//Apache Software Foundation//DTD Tiles Configuration 2.0//EN"
"http://tiles.apache.org/dtds/tiles-config_2.0.dtd">


<tiles-definitions>
	

</tiles-definitions>

tiles.xml :  나중에 쓰기 위한 설정 파일

 

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
  <display-name>struts2</display-name>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>default.html</welcome-file>
    <welcome-file>default.htm</welcome-file>
    <welcome-file>default.jsp</welcome-file>
  </welcome-file-list>
    
  <filter>
  	<filter-name>struts2</filter-name>
    
     <!-- StrutsPrepareAndExecuteFilter  2016년에 바뀜 -->
  	<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
  </filter>
  
  <filter-mapping>
  	<filter-name>struts2</filter-name>
  	  <!-- /* 모든주소가 오면 StrutsPrepareAndExecuteFilter에서 문법검사를 한다.-->
      <!-- struts2 로 환경세팅을 할것이다 -->
  	<url-pattern>/*</url-pattern>
  </filter-mapping>
</web-app>

web.xml 에서 struts2 환경 세팅을 한다.

 

2016년에 filterDispatcher에서 StrutsPrepareAndExecuteFilter로 바뀌었다

 

이제 콘솔에서 struts-default.xml 이랑  struts.xml 파일을 읽어낸다.

 

<%@ page contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> 
<%
	request.setCharacterEncoding("UTF-8");
	String cp = request.getContextPath();
%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>

<!-- 입력창  -->

<!-- 보내기버튼을 누르면 namespace:itwill 주소가 들어오면 struts-test.xml 로 찾아가라는 소리이다.-->


<form action="<%=cp%>/itwill/write_ok.action" method="post">
	
아이디 : <input type="text" name="userId"/><br/> 
이름 : <input type="text" name="userName"/><br/>
<input type="submit" value="보내기"/><br/>



</form>


</body>
</html>

write.jsp의 입력창

 

<%@ page contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> 
<%
	request.setCharacterEncoding("UTF-8");
	String cp = request.getContextPath();
%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
아이디 : ${userId }<br/>
이름 : ${userName }<br/>
메세지 : ${message }<br/>
</body>
</html>

view.jsp의 출력 창

 

package com.test;

import com.opensymphony.xwork2.ActionSupport;

// 스트럿츠2에서는 ActionSupport를 상속받는다 그러면 TestAction 이 Action 이 된다.

public class TestAction extends ActionSupport{

	private static final long serialVersionUID = 1L;
	
	private String userId;
	private String userName;
	private String message;
	
	public String getUserId() {
		return userId;
	}
	public void setUserId(String userId) {
		this.userId = userId;
	}
	public String getUserName() {
		return userName;
	}
	public void setUserName(String userName) {
		this.userName = userName;
	}
	public String getMessage() {
		return message;
	}
	public void setMessage(String message) {
		this.message = message;
	}
	
	//struts1 에 비해 struts2는 필요할때만 request,form,response 달라고 요청하면 됨 (경량컨테이너)
	public String execute() throws Exception {
		
		message = userName + "님 방가방가...";

		return SUCCESS; // 작업이 잘실행되면 SUCCESS쓰라고 제시 
						// 반드시 대문자 안에 "success" 소문자가 들어간 상수 
		
	}
}

 

스트럿츠 2는 필요한 것만 가져온다. 

기존 스트럿츠 1에서는 안 쓰는 response request를 매개변수로 받아왔지만 

스트럿츠 2는 필요한 것만 받아온다.

나중에 스프링에서도 이방식을 사용하는데 경량 컨테이너라고 한다.

코딩 자체가 단순해진다. 

spring이 스트럿츠 2의 좋은 장점을 가져가서 만들어진 것이다. 

 

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts
PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">

<!--  struts-test.xml 은 분배기 같은 역할이다 mvc 에서 controll 역할이다. -->


<!-- name : 이 패키지의 고유 이름 (호출해서쓰진않음 내맘대로 써주면됨)  -->
<!-- 패키지는 여러개 만들수있고 name이라는 곳에 고유이름을 써주면 됨 -->

<!--  namespace : /itwill 주소로 들어오면 struts-test.xml로 들어와라 -->
<!-- 사용자 주소를 내가 여기다가 써줄수있다. -->


<!-- action name : wirte.action 생략되어있음  -->

<!--  struts2/itwill/wirte.action 으로 오게됨
		result 로 진짜 주소로 이동하게됨  -->
		
<!--  extends 는 struts.xml에 default 맞춰줘야한다. -->
<!--  새롭게 추가 test2 method="created" 는 String created() 로  -->

<struts>

<!-- /struts2/itwill/write.action 이 오게 되면 이패키지로 이동한다 -->
<package name="test" extends="default" namespace="/itwill">

	<action name="write">
		<result>/test/write.jsp</result>
	</action>

	<action name="write_ok" class="com.test.TestAction">
		<result name="success">/test/view.jsp</result>
	</action>
	
	<action name="created">
		<result>/test1/created.jsp</result>
	</action>

	<action name="created_ok" class="com.test1.TestAction">
		<result name="ok">/test1/result.jsp</result>
	</action>
</package>

<!-- class 이동:  TestAction 를 거쳤다가  execute는 무조건실행되는 메소드에 실행된다음 return SUCESS를 가지고온다. -->		

<package name="test2" extends="default" namespace="/modelDri">
	<action name="write" class="com.test2.TestAction" method="created">
		<result name="input">/test2/write.jsp</result>
		<result name="success">/test2/view.jsp</result>
		
	</action> 

</package>

</struts>

struts-test.xml를 만든다.

 

write.jsp에서 입력을 하면 TestAction으로 이동을 하겠다는 뜻이다.

success 문자를 가지고 오면  view.jsp로 가겠다는 것

 

 

 

com.test1 에 TestAction 이랑 UserDTO를 만든다.

test 1 

package com.test1;

public class UserDTO {
	
	private String userId;
	private String userName;
	
	public String getUserId() {
		return userId;
	}
	public void setUserId(String userId) {
		this.userId = userId;
	}
	public String getUserName() {
		return userName;
	}
	public void setUserName(String userName) {
		this.userName = userName;
	}
}

UserDTO 생성 

 

package com.test1;

import com.opensymphony.xwork2.ActionSupport;

// 스트럿츠2는  ActionSupport를 상속받는다.
public class TestAction extends ActionSupport {

	private static final long serialVersionUID = 1L;
	
	// dto를 가지고 와서
	// dto를 한번더 감싸줘서 dto. 으로 접근하는걸 domain object라고 한다.
	// 폼에서 보낼때도 dto.  el태그로 받아낼때도 dto.
	private UserDTO dto; 
	
	// DTO에 만들지 않은 이유는 여기서 메세지에 관련된 처리를 보여주려고,..
	// 이 안에서만 만들 수 있는 변수값이 필요할때가 있기 때문에.
	private String message;
	
	
	// dto에 값을 넣고 싶으면 getter/setter
	public UserDTO getDto() {
		return dto;
	}

	public void setDto(UserDTO dto) {
		this.dto = dto;
	}

	public String getMessage() {
		return message;
	}
	
	public String execute() throws Exception {
		
		// userId를 다이렉트로 접근할수가 없다
		message = dto.getUserName() + "님 방가방가...";
		
		return "ok"; // SUCESS 말고 사용자 정의 문자를 써도됨
	}
	
}

TestAction.java

dto라는 껍데기가 써져서 dto.으로 접근해야 한다.

 

<%@ page contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> 
<%
	request.setCharacterEncoding("UTF-8");
	String cp = request.getContextPath();
%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
	
	<!-- action에 /itwill/ 적어주면 폴더가 달라도 찾아간다  -->
<form action="<%=cp%>/itwill/created_ok.action" method="post">

<!-- dto안에 getter ,setter 를 만들었으므로 
		dto의 껍데기가 하나 씌어져서 
			dto. 으로 접근해줘야 한다.  -->
아이디 : <input type="text" name="dto.userId"/><br/>
이름 : <input type="text" name="dto.userName"/><br/>
<input type="submit" value="보내기"/><br/>

</form>	
</body>
</html>

test 1.created.jsp

 

<%@ page contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> 
<%
	request.setCharacterEncoding("UTF-8");
	String cp = request.getContextPath();
%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>

<!--  dto안에 감싸져 있으므로 dto. 으로 접근해줘야 한다. -->
아이디:${dto.userId }<br/>
이름:${dto.userName }<br/>
매세지:${message }<br/>

</body>
</html>

test 1.result.jsp 

 

받아낼 때도 dto로 한 번 더 써줘야 한다.

 

extends의 default는 struts.xml에 package name="default" 와 같아야 한다.&amp;amp;amp;amp;amp;amp;amp;nbsp;

extends 확장이라는 의미로 패키지를 사용할 수 있게 된다.

 

 

com.test2

 

package com.test2;

public class UserDTO {
	
	private String userId;
	private String userPwd;
	private String userName;
	
	private String mode; // mode 하나가 필요하다
	
	public String getUserId() {
		return userId;
	}
	public void setUserId(String userId) {
		this.userId = userId;
	}
	public String getUserPwd() {
		return userPwd;
	}
	public void setUserPwd(String userPwd) {
		this.userPwd = userPwd;
	}
	public String getUserName() {
		return userName;
	}
	public void setUserName(String userName) {
		this.userName = userName;
	}
	public String getMode() {
		return mode;
	}
	public void setMode(String mode) {
		this.mode = mode;
	}
	
}

com.test2.UserDTO

 

package com.test2;

import javax.servlet.http.HttpServletRequest;

import org.apache.struts2.ServletActionContext;

import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
import com.opensymphony.xwork2.Preparable;

public class TestAction extends ActionSupport
implements Preparable, ModelDriven<UserDTO> {
	
	// 스트럿츠는 이구조를 반드시 써줘야 한다.
	// dto 안에있는 내용은 userId,pwd,name 를 struts2가 알아서 넘겨준다.
	// 바로 modelDriven<UserDTO> 한테 UserDTO를 맡긴것이다.(니가 알아서 DTO를 관리를 해!)
	// dto가 객체이기떄문에 객체생성을 prepare메소드를 통해 객체를 생성함
	// getModel() 를 통해 dto를 modelDriven이 가지고 간다.
	
	private static final long serialVersionUID = 1L;
	private UserDTO dto;
	
    // dto는 getter만 만든다.
    
	// getDTO()는 
	// struts1 에서 쓰인 보드액션에서 
	// request.setAttribute("dto",dto)를 안써줘도
	// 자동으로 보내게 된다.
	public UserDTO getDto() {
		return dto;
	}

	@Override
	public void prepare() throws Exception {
		dto = new UserDTO();
	}

	@Override
	public UserDTO getModel() {
		return dto;
	}
	
	// 이제부터 내가 원하는 메소드 이름으로 쓰면 된다.
	public String created() throws Exception {	
		// 모드 체크 
		// dto의 널값과 equals로 널을 두번 비교해준다 
		// equals가 앞에 오면 안됨 
		if(dto==null||dto.getMode()==null||dto.getMode().equals("")) {	
			return INPUT; // 아까 SUCESS와 비슷 내장된 반환값 소문자 input이 들어가있음
		}
		
		// dto가 널이아닐때
		// request를 이렇게 만들면 됨
		HttpServletRequest request = ServletActionContext.getRequest();
	
		request.setAttribute("message", "스트럿츠 2...");
		
//		request.setAttribute("dto", dto); dto도 원래 이렇게 넘겨야되는데
		//위에 getDTO()떄문에 자동으로 넘김
		
		return SUCCESS; // 사용자가 값을 입력할때
	}
	
}

 

com.test2.TestAction.java

자동으로 dto를 넘겨준다.

 

<%@ page contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> 
<%
	request.setCharacterEncoding("UTF-8");
	String cp = request.getContextPath();
%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>

<!-- 입력창 열때도 write.action 보낼때도 write.action  -->
<form action="<%=cp%>/modelDri/write.action" method="post">
	
아이디 : <input type="text" name="userId"/><br/>
패스워드 : <input type="password" name="userPwd"/><br/> 
이름 : <input type="text" name="userName"/><br/>

<input type="hidden" name="mode" value="save"/>
<input type="submit" value="보내기"/><br/>

</form>

</body>
</html>

write.jsp

 

<%@ page contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> 
<%
	request.setCharacterEncoding("UTF-8");
	String cp = request.getContextPath();
%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
아이디 : ${dto.userId }<br/>
패스워드 : ${dto.userPwd}<br/>
이름 : ${dto.userName}<br/>
메세지 : ${message }<br/> <!-- dto에 없는 내용을 보낼때 -->
</body>
</html>

view.jsp

 

 

 

패키지 name = test2 extends="default" namespace = "/modelDri"를 추가해준다.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts
PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">

<!--  struts-test.xml 은 분배기 같은 역할이다 mvc 에서 controll 역할이다. -->


<!-- name : 이 패키지의 고유 이름 (호출해서쓰진않음 내맘대로 써주면됨)  -->
<!-- 패키지는 여러개 만들수있고 name이라는 곳에 고유이름을 써주면 됨 -->

<!--  namespace : /itwill 주소로 들어오면 struts-test.xml로 들어와라 -->
<!-- 사용자 주소를 내가 여기다가 써줄수있다. -->


<!-- action name : wirte.action 생략되어있음  -->

<!--  struts2/itwill/wirte.action 으로 오게됨
		result 로 진짜 주소로 이동하게됨  -->
		
<!-- class 이동:  TestAction 를 거쳤다가  execute는 무조건실행되는 메소드에 실행된다음 return SUCESS를 가지고온다. -->		


<!--  extends 는 struts.xml에 default 맞춰줘야한다. -->
<!--  새롭게 추가 test2 method="created" 는 String created() 로  -->

<struts>

<package name="test" extends="default" namespace="/itwill">

	<action name="write">
		<result>/test/write.jsp</result>
	</action>

	<action name="write_ok" class="com.test.TestAction">
		<result name="success">/test/view.jsp</result>
	</action>
	
	<action name="created">
		<result>/test1/created.jsp</result>
	</action>

	<action name="created_ok" class="com.test1.TestAction">
		<result name="ok">/test1/result.jsp</result>
	</action>
</package>


<!-------------------------------패키지를 하나더 추가해준다. ----------------------------->

<!-- /modelDri/write 를 치면 TestAction 으로 가서 created메소드를 찾아서 결과값에 따라 jsp로 이동 -->
<package name="test2" extends="default" namespace="/modelDri">
	<action name="write" class="com.test2.TestAction" method="created">
		<result name="input">/test2/write.jsp</result>
		<result name="success">/test2/view.jsp</result>
		
	</action> 

</package>

</struts>

struts-test.xml 

 

 

 

 

 

 

 

 

 

prepare() 객체를 생성해주고 

getModel()를 가지고 ModelDriven <UserDTO>로 가지고 들어가고 

getDto()를 통해서 넘겨준다.

 

 

 

 

 

package com.board;

public class BoardDTO {
	
	private int listNum; // 일련번호 db에있는것이 아니므로 띄어서 만듬
	
	private int boardNum; 
	private String name;
	private String pwd;
	private String email;
	private String subject;
	private String content;
	private String ipAddr;
	private int groupNum;
	private int depth;
	private int orderNo;
	private int parent;
	private int hitCount;
	private String created;
	
	
	// dto에 있으면 자동으로 스트럿츠가 자동으로 넘겨준다. 
	private String searchKey; 
	private String searchValue;
	private String pageNum;
	
	private String mode; // 입력 수정 댓글 

	public int getListNum() {
		return listNum;
	}

	public void setListNum(int listNum) {
		this.listNum = listNum;
	}

	public int getBoardNum() {
		return boardNum;
	}

	public void setBoardNum(int boardNum) {
		this.boardNum = boardNum;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getPwd() {
		return pwd;
	}

	public void setPwd(String pwd) {
		this.pwd = pwd;
	}

	public String getEmail() {
		return email;
	}

	public void setEmail(String email) {
		this.email = email;
	}

	public String getSubject() {
		return subject;
	}

	public void setSubject(String subject) {
		this.subject = subject;
	}

	public String getContent() {
		return content;
	}

	public void setContent(String content) {
		this.content = content;
	}

	public String getIpAddr() {
		return ipAddr;
	}

	public void setIpAddr(String ipAddr) {
		this.ipAddr = ipAddr;
	}

	public int getGroupNum() {
		return groupNum;
	}

	public void setGroupNum(int groupNum) {
		this.groupNum = groupNum;
	}

	public int getDepth() {
		return depth;
	}

	public void setDepth(int depth) {
		this.depth = depth;
	}

	public int getOrderNo() {
		return orderNo;
	}

	public void setOrderNo(int orderNo) {
		this.orderNo = orderNo;
	}

	public int getParent() {
		return parent;
	}

	public void setParent(int parent) {
		this.parent = parent;
	}

	public int getHitCount() {
		return hitCount;
	}

	public void setHitCount(int hitCount) {
		this.hitCount = hitCount;
	}

	public String getCreated() {
		return created;
	}

	public void setCreated(String created) {
		this.created = created;
	}

	public String getSearchKey() {
		return searchKey;
	}

	public void setSearchKey(String searchKey) {
		this.searchKey = searchKey;
	}

	public String getSearchValue() {
		return searchValue;
	}

	public void setSearchValue(String searchValue) {
		this.searchValue = searchValue;
	}

	public String getPageNum() {
		return pageNum;
	}

	public void setPageNum(String pageNum) {
		this.pageNum = pageNum;
	}

	public String getMode() {
		return mode;
	}

	public void setMode(String mode) {
		this.mode = mode;
	}
	
	
	
}

BoardDTO

 

package com.board;

import java.io.IOException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.apache.struts2.ServletActionContext;

import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
import com.opensymphony.xwork2.Preparable;
import com.util.MyUtil;
import com.util.dao.CommonDAO;
import com.util.dao.CommonDAOImpl;

public class BoardAction extends ActionSupport
implements Preparable, ModelDriven<BoardDTO>{

	private static final long serialVersionUID = 1L;

	private BoardDTO dto;
	
	
	// getDto 가 modelDriven에 의해서 원하는곳으로 넘어간다.
	public BoardDTO getDto() {
		return dto;
	}

	@Override
	public BoardDTO getModel() {
		return dto;
	}

	@Override
	public void prepare() throws Exception {
		// modelDriven이 객체를 넘기려면 객체를 생성해야한다.
		dto = new BoardDTO();
	}
	
	
	// 사용자가 created메소드로 찾아오면
	// 입력할때 쓸것인가
	// 겉모습만 보여줄것인가
	public String created() throws IOException {
		
		HttpServletRequest request = ServletActionContext.getRequest();
		
		// 앞뒤가 바뀌면 안된다. equals가 뒤에 와야된다.
		
		// 게시물 입력창을 띄운다.
		if(dto==null||dto.getMode()==null||dto.getMode().equals("")) {
			
			request.setAttribute("mode", "create");
			
			return INPUT;
		}
		
		// dto가 null이 아니면 입력이 된것이다.
		
		// 입력 코딩은 좀있다가 
		
		CommonDAO dao = CommonDAOImpl.getInstance();
		
		int maxBoardNum = dao.getIntValue("bbs.maxBoardNum");
		
		// 처음들어가는 데이터 
		dto.setBoardNum(maxBoardNum + 1);
		dto.setIpAddr(request.getRemoteAddr());
		dto.setGroupNum(dto.getBoardNum());
		dto.setDepth(0); 
		dto.setOrderNo(0);
		dto.setParent(0);
		
		dao.insertData("bbs.insertData", dto);
		
		return SUCCESS;
	}
	
	// 리스트 띄우기
	public String list() throws IOException {
		
		CommonDAO dao = CommonDAOImpl.getInstance();
		MyUtil myUtil = new MyUtil();
		
		
		// request 사용하기 위해  생성 
		HttpServletRequest request = ServletActionContext.getRequest();
		
		String cp = request.getContextPath();
		
		int numPerPage = 5;
		int totalPage = 0;
		int totalDataCount = 0;
		
		int currentPage = 1;
		
		if(dto.getPageNum()!=null && !dto.getPageNum().equals("")) {
			currentPage = Integer.parseInt(dto.getPageNum());
		}
		
		if(dto.getSearchValue()==null||dto.getSearchValue().equals("")) {
			dto.setSearchKey("subject");
			dto.setSearchValue("");
		}
	
		if(request.getMethod().equalsIgnoreCase("GET")) {
			dto.setSearchValue(URLDecoder.decode(dto.getSearchValue(),"UTF-8"));
		}
		// 전체페이지 MAP 필요
		Map<String, Object> hMap = new HashMap<String,Object>();
		hMap.put("searchKey", dto.getSearchKey());
		hMap.put("searchValue", dto.getSearchValue());
		
		// 전체 데이터 개수 구하기
		totalDataCount = dao.getIntValue("bbs.dataCount",hMap);
		
		if(totalDataCount!=0) {
			totalPage = myUtil.getPageCount(numPerPage, totalDataCount);
		}
		// 삭제가 있을때 문제가 생길때
		if(currentPage > totalPage) {
			currentPage = totalPage;
		}
		
		int start = (currentPage-1)*numPerPage+1;
		int end = currentPage*numPerPage;
		
		hMap.put("start", start);
		hMap.put("end", end);
		
		// hamp에는 4개가 들어가있다 키와벨류start,end
		
		List<Object> lists = (List<Object>)dao.getListData("bbs.listData",hMap);
		
		
		// 일련번호를 만들기
		int listNum,n=0;
		
		Iterator<Object> it = lists.iterator();
		
		while(it.hasNext()) {
			// dto를 하나꺼내서 만들어서 vo에 listNum에 넣어준다.
			BoardDTO vo = (BoardDTO)it.next();
			listNum = totalDataCount-(start+n-1);
			vo.setListNum(listNum); // 삭제가 되도 일련번호가 만들어짐
			n++;
			
		}
		String param = "";
		String urlList = "";
		String urlArticle = "";
		
		// 널이 아니면 검색을 했다.
		if(!dto.getSearchValue().equals("")) {
			
			param = "searchKey=" + dto.getSearchKey();
			param += "&searchValue="
					+ URLEncoder.encode(dto.getSearchValue(),"UTF-8");
		}
		
		urlList = cp + "/bbs/list.action";
		urlArticle = cp + "/bbs/article.action?pageNum="+currentPage;
		
		// param 널이 아니면 검색이 됐다.
		if(!param.equals("")) {
			
			urlList += "?" + param;
			urlArticle += "&" + param;
		}
		
		// 데이터 넘김
		// 이 내개 데이터와 success를 가지고 돌아감
		request.setAttribute("lists", lists);
		request.setAttribute("totalDataCount", totalDataCount);
		request.setAttribute("pageIndexList",
				myUtil.pageIndexList(currentPage, totalPage, urlList));
		
		request.setAttribute("urlArticle", urlArticle);
		return SUCCESS;
	}
	
	// 클릭해서 dto는 자동으로 넘어온다. 
	public String article() throws Exception {
		
		HttpServletRequest request = ServletActionContext.getRequest();
		CommonDAO dao = CommonDAOImpl.getInstance();
		
		
		// 스트럿츠2가 자동으로 dto를 넘겨줘서 pageNum과 boardNum이 나오게 된다.
		/*System.out.print(dto.getSearchKey());
		System.out.print(dto.getSearchValue());
		System.out.print(dto.getPageNum());
		System.out.print(dto.getBoardNum());*/
		
		// dao에서 하나의 데이터를 가져올것이다.
		// 넘어오는값을 변수에 빼놓는다.
		String searchKey = dto.getSearchKey();
		String searchValue = dto.getSearchValue();
		String pageNum = dto.getPageNum();
		int boardNum = dto.getBoardNum();
		
		if(searchValue==null||searchValue.equals("")) {
			searchKey = "subject";
			searchValue = "";
		}
		if(request.getMethod().equalsIgnoreCase("GET")) {
			searchValue = URLDecoder.decode(searchValue, "UTF-8");
		}
		
		// 조회수 증가 
		dao.updateData("bbs.hitCountUpdate", boardNum);
		
		// 하나의 데이터를 읽어와서 dto에 넣어준다.
		dto = (BoardDTO)dao.getReadData("bbs.readData",boardNum);
		
		// nullnullnull3  검색을 했는데도 key,value,pagenum 없어짐..
		// 위에는 있어서 출력이 됐는데
		// 진행하다 보니까 자동으로 넘어온 dto가 이 밑에서 
		// getReadData에 의해서 기존에 있는게 덮어져서 초기화됨
		// 맨 마지막에 boardNum만 보이게 된다.
		
		// 우리가 별도로 자동으로 넘어온 dto를 빼놔서
		// 아래에서 사용을 하게되는것이다.
		/*System.out.print(dto.getSearchKey());
		System.out.print(dto.getSearchValue());
		System.out.print(dto.getPageNum());
		System.out.print(dto.getBoardNum());*/
		
		if(dto==null) {
			return "read-error";
		}
		
		// dto에서 꺼냈으니 content는 있으나 키벨류페이지넘은 초기화되어있음..
		int lineSu = dto.getContent().split("\r\n").length;
		
		dto.setContent(dto.getContent().replaceAll("\r\n", "<br/>"));
		
		// 이전글 다음글보낼것임
		Map<String, Object> hMap = new HashMap<>();
//		hMap.put("searchKey", dto.getSearchKey()); 이렇게 넣어주면안됨 위에 자동으로 넣은 dto sk,sv,pn 이 초기화 되어있어서
											// 널이 들어가면 검색이 안된다..
											
		hMap.put("searchKey", searchKey); // 그럼 여기다가 위에서 dto.getSearchKey 로
										  // 받은 searchKey변수 를 써줘야 한다.
		hMap.put("searchValue", searchValue);
		hMap.put("groupNum", dto.getGroupNum());
		hMap.put("orderNo", dto.getOrderNo());
		
		// 이전글
		BoardDTO preDTO = (BoardDTO)dao.getReadData("bbs.preReadData",hMap);
		int preBoardNum = 0;
		String preSubject = "";
		if(preDTO!=null) {
			preBoardNum = preDTO.getBoardNum();
			preSubject = preDTO.getSubject();
		}
		
		BoardDTO nextDTO = (BoardDTO)dao.getReadData("bbs.nextReadData",hMap);
		int nextBoardNum = 0;
		String nextSubject = "";
		if(nextDTO!=null) {
			nextBoardNum = nextDTO.getBoardNum();
			nextSubject = nextDTO.getSubject();
		}
		
		// 넘어가는 주소
		String params = "pageNum=" + pageNum;
		if(!searchValue.equals("")) {
			params += "&searchKey=" + searchKey;
			params += "&searchValue="
					+ URLEncoder.encode(searchValue,"UTF-8");
		}
		
		request.setAttribute("preBoardNum", preBoardNum);
		request.setAttribute("preSubject",preSubject);
		request.setAttribute("nextBoardNum", nextBoardNum);
		request.setAttribute("nextSubject",nextSubject);
		
		request.setAttribute("params",params);
		request.setAttribute("lineSu",lineSu);
		request.setAttribute("pageNum",pageNum);
		
		// 이제 sql에 이전글 다음글로 넘어가게 된다.
		return SUCCESS;	
	}
	
}

BoardAction.java

 

getReadData를 하면서 dto가 초기화됨  

 

초기화되기 전에  dto의 값들을 미리 꺼내서 변수에 담아둔다. (중요)

 

마지막에 hMap에 빼는 데이터를 넣어주면 된다.

 

 

<%@ page contentType="text/html; charset=UTF-8"%>
<%
	request.setCharacterEncoding("UTF-8");
	String cp = request.getContextPath();
%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>게 시 판</title>

<link rel="stylesheet" type="text/css" href="<%=cp%>/board/css/style.css"/>
<link rel="stylesheet" type="text/css" href="<%=cp%>/board/css/created.css"/>

<script type="text/javascript" src="<%=cp%>/board/js/util.js"></script>
<script type="text/javascript">

	function sendIt(){
		
		var f = document.myForm;
		
		str = f.subject.value;
		str = str.trim();
		if(!str){
			alert("\n제목을 입력하세요.");
			f.subject.focus();
			return;
		}
		f.subject.value = str;
		
		str = f.name.value;
		str = str.trim();
		if(!str){
			alert("\n이름을 입력하세요.");
			f.name.focus();
			return;
		}		
		
	/* 	if(!isValidKorean(str)){
			alert("\n이름을 정확히 입력하세요.");
			f.name.focus()
			return;
		}		 */
		f.name.value = str;
		
		if(f.email.value){
			if(!isValidEmail(f.email.value)){
				alert("\n정상적인 E-Mail을 입력하세요.");
				f.email.focus();
				return;
			}
		}
		
		str = f.content.value;
		str = str.trim();
		if(!str){
			alert("\n내용을 입력하세요.");
			f.content.focus();
			return;
		}
		f.content.value = str;
		
		str = f.pwd.value;
		str = str.trim();
		if(!str){
			alert("\n패스워드를 입력하세요.");
			f.pwd.focus();
			return;
		}
		f.pwd.value = str;
		
		/*  입력  수정  댓글 */
		/* request.setAttribute("mode", "create"); */
		/* 주소를 분리해놨다.  */
		if(f.mode.value=="create") {
			f.action = "<%=cp%>/bbs/created.action";
		}else if(f.mode.value=="update") {
			f.action = "<%=cp%>/bbs/updated.action";
		}else if(f.mode.value=="reply") {
			f.action = "<%=cp%>/bbs/reply.action";
		}

		f.submit();
		
	}

</script>


</head>
<body>

<div id="bbs">
	<div id="bbs_title">
		게 시 판 (Struts2)
	</div>
	
	<form action="" method="post" name="myForm">
	<div id="bbsCreated">
		
		<div class="bbsCreated_bottomLine">
			<dl>
				<dt>제&nbsp;&nbsp;&nbsp;&nbsp;목</dt>
				<dd>
				<input type="text" name="subject" value="${dto.subject }" size="60" 
				maxlength="100" class="boxTF"/>
				</dd>
			</dl>		
		</div>
		
		<div class="bbsCreated_bottomLine">
			<dl>
				<dt>작성자</dt>
				<dd>
				<input type="text" name="name" value="${dto.name }" size="35" 
				maxlength="20" class="boxTF"/>
				</dd>
			</dl>		
		</div>
		
		<div class="bbsCreated_bottomLine">
			<dl>
				<dt>E-Mail</dt>
				<dd>
				<input type="text" name="email" value="${dto.email }" size="35" 
				maxlength="50" class="boxTF"/>
				</dd>
			</dl>		
		</div>
		
		<div id="bbsCreated_content">
			<dl>
				<dt>내&nbsp;&nbsp;&nbsp;&nbsp;용</dt>
				<dd>
				<textarea rows="12" cols="63" name="content"
				class="boxTA">${dto.content }</textarea>
				</dd>
			</dl>
		</div>
		
		<div class="bbsCreated_noLine">
			<dl>
				<dt>패스워드</dt>
				<dd>
				<input type="password" name="pwd" value="${dto.pwd }" size="35" 
				maxlength="7" class="boxTF"/>
				&nbsp;(게시물 수정 및 삭제시 필요!!)
				</dd>
			</dl>		
		</div>	
	
	</div>
	
	<div id="bbsCreated_footer">
	
		<!-- 수정으로 쓸곳 , 수정하기 위해서 필요한것이다. -->
		<input type="hidden" name="boardNum" value="${dto.boardNum }"/>
		<input type="hidden" name="pageNum" value="${dto.pageNum }"/>
		
		<!-- 댓글달때 필요하므로 써놓음 -->
		<input type="hidden" name="groupNum" value="${dto.groupNum }"/>
		<input type="hidden" name="orderNo" value="${dto.orderNo }"/>
		<input type="hidden" name="depth" value="${dto.depth }"/>
		<input type="hidden" name="parent" value="${dto.parent }"/>
		
		<!--  입력용인지 수정용인지 댓글용인지 -->
        
        <!-- BoardAction에서 입력창은 
        request.setAttribute("mode","create") 로 담겨서 넘어오므로 -->
		<input type="hidden" name="mode" value="${mode }"/>
	
		<input type="button" value=" 등록하기 " class="btn2" onclick="sendIt();"/>
		<input type="reset" value=" 다시입력 " class="btn2" 
		onclick="document.myForm.subject.focus();"/>
		<input type="button" value=" 작성취소 " class="btn2"
		 onclick="javascript:location.href='<%=cp%>/bbs/list.action';"/>
	</div>
	
	</form>

</div>


</body>
</html>

created.jsp

 

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts
PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<!--  struts-default  : xml 파일을 불러옴  -->
<!--  include : 또 다른 환경설정을 불러옴 -->
<struts>
	<package name="default" extends="struts-default" namespace="">
		<global-results>
			<result name="error">/exception/error.jsp</result>
		</global-results>
	</package>
	<include file="struts-test.xml"/>
	<include file="struts-board.xml"/>
</struts>

struts.xml 에 include file로 등록해준다.

 

<%@ page contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> 
<%
	request.setCharacterEncoding("UTF-8");
	String cp = request.getContextPath();
%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>게 시 판</title>

<link rel="stylesheet" type="text/css" href="<%=cp%>/board/css/style.css"/>
<link rel="stylesheet" type="text/css" href="<%=cp%>/board/css/list.css"/>

<script type="text/javascript">

	function searchData() {
		
		var f = document.searchForm;
		
		f.action = "<%=cp%>/bbs/list.action";
		f.submit();
	}

</script>



</head>
<body>

<div id="bbsList">
	<div id="bbsList_title">
		게 시 판(Struts2)
	</div>
	<div id="bbsList_header">
		<div id="leftHeader">
		<form action="" method="post" name="searchForm">
			<select name="searchKey" class="selectField">
				<option value="subject">제목</option>
				<option value="name">작성자</option>
				<option value="content">내용</option>
			</select>
			<input type="text" name="searchValue" class="textField"/>
            
            <!-- 검색 -->
			<input type="button" value=" 검 색 " class="btn2" onclick="searchData();"/>		
		</form>				
		</div>
		<div id="rightHeader">
			<input type="button" value=" 글올리기 " class="btn2"
			 onclick="javascript:location.href='<%=cp%>/bbs/created.action';"/>			
		</div>	
	</div>
	<div id="bbsList_list">
		<div id="title">
			<dl>
				<dt class="num">번호</dt>
				<dt class="subject">제목</dt>
				<dt class="name">작성자</dt>
				<dt class="created">작성일</dt>
				<dt class="hitCount">조회수</dt>
			</dl>
		</div>
		<div id="lists">
		<c:forEach var="dto" items="${lists }">
			<dl>
				<dd class="num">${dto.listNum }</dd>
				<dd class="subject">
				<a href="${urlArticle }&boardNum=${dto.boardNum }">
				${dto.subject }</a>
				</dd>
				<dd class="name">${dto.name }</dd>
				<dd class="created">${dto.created }</dd>
				<dd class="hitCount">${dto.hitCount }</dd>
			</dl>
		</c:forEach>
		</div>
		<div id="footer">
			<p>
				<c:if test="${totalDataCount!=0 }">
					${pageIndexList }
				</c:if>
				<c:if test="${totalDataCount==0 }">
					등록된 게시물이 없습니다.
				</c:if>
		</div>
		
	</div>
	
</div>

</body>
</html>

list.jsp

 

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts
PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">

<!--  Controller 역할  -->
<!--  extends 의 default 는 packagename 의 default   struts.xml과 연결되게끔함 -->
<!--  주소창을 여기서 친다 -->
<struts>

	<package name="board" extends="default" namespace="/bbs">
		
		<!-- /bbs에 created.Action 이 오면  BoardAction 으로 가서 created메소드를 실행해라 -->
		<action name="created" class="com.board.BoardAction" method="created">
			<result name="input">/board/created.jsp</result>
			<!-- 입력이 됬으므로 리다이랙트(수정,세션된건) -->
			<result name="success" type="redirectAction">list</result>
		</action>
	
		<action name="list" class="com.board.BoardAction" method="list">
			<result name="success">/board/list.jsp</result>
		</action>
		
		<action name="article" class="com.board.BoardAction" method="article">
			<result name="success">/board/article.jsp</result>
		</action>
		
	</package>
</struts>

struts-board.xml

 

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sqlMap
PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN"
"http://ibatis.apache.org/dtd/sql-map-2.dtd">

<sqlMap namespace="bbs">
	
<!--  별칭을줘서 간단하게 쓸수있다. -->
<typeAlias alias="boardDTO" type="com.board.BoardDTO"/>	
	
	
<select id="maxBoardNum" resultClass="int">
	select nvl(max(boardNum),0) from bbs
</select>	
	
<insert id="insertData" parameterClass="boardDTO">
	insert into bbs (boardNum,name,pwd,email,subject,content,
	ipAddr,groupNum,depth,orderNo,parent,hitCount,created) values
	(#boardNum#,#name#,#pwd#,#email#,#subject#,#content#,
	#ipAddr#,#groupNum#,#depth#,#orderNo#,#parent#,0,sysdate)
</insert>	

<select id="dataCount" resultClass="int" parameterClass="map">
	select nvl(count(*),0) from bbs
	where $searchKey$ like '%' || #searchValue# || '%'
</select>


<!-- boardDTO 위에서 별칭으로 만든걸 반환할수있다. -->

<!-- 그룹은 큰순서로 정렬 , orderNo 작은순서로 정렬 -->
<select id="listData" resultClass="boardDTO" parameterClass="map">
	select * from (
	select rownum rnum, data.* from (
	select boardNum,name,subject,depth,hitCount,
	to_char(created,'YYYY-MM-DD') created from bbs
	where $searchKey$ like '%' || #searchValue# || '%'
	order by groupNum desc,orderNo asc) data)
<![CDATA[
	where rnum>=#start# and rnum<=#end#
]]>	
</select>
	
	
<!-- Article   -->	
<!-- 조회수 증가 -->
<update id="hitCountUpdate" parameterClass="int">
	update bbs set hitCount=hitCount+1 where boardNum=#boardNum#
</update>

<!-- 하나의 데이터 가져옴 -->
<select id="readData" parameterClass="int" resultClass="boardDTO">

	select boardNum,name,pwd,email,subject,content,ipAddr,
	groupNum,depth,orderNo,parent,hitCount,created
	from bbs where boardNum=#boardNum#
</select>

<!--  이전글 다음글  -->
<!--  그룹넘버가 같으면서 orderNo가 현재보다 작아야한다. -->

<!--  이전글이 최신글이다. -->
<select id="preReadData" parameterClass="map" resultClass="boardDTO">
	select data.* from (
	select boardNum,subject from bbs
	where ($searchKey$ like '%' || #searchValue# || '%')
<![CDATA[	
	and ((groupNum=#groupNum# and orderNo<#orderNo#)
	or(groupNum>#groupNum#))
	order by groupNum asc,orderNo desc) data
	where rownum=1
]]>		
</select>


<!--  다음글이 예전에 쓴글  -->
<select id="nextReadData" parameterClass="map" resultClass="boardDTO">
	select data.* from (
	select boardNum,subject from bbs
	where ($searchKey$ like '%' || #searchValue# || '%')
<![CDATA[
	and ((groupNum=#groupNum# and orderNo>#orderNo#)
	or(groupNum<#groupNum#))
	order by groupNum desc,orderNo asc) data
	where rownum=1
]]>	
</select>	
</sqlMap>

board_sqlMap.xml  dao 작업을 하기 위한 쿼리문 

 

<%@ page contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> 
<%
	request.setCharacterEncoding("UTF-8");
	String cp = request.getContextPath();
%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>게 시 판</title>

<link rel="stylesheet" type="text/css" href="<%=cp%>/board/css/style.css"/>
<link rel="stylesheet" type="text/css" href="<%=cp%>/board/css/article.css"/>

</head>
<body>

<div id="bbs">
	
	<div id="bbs_title">
		게 시 판 (Struts2)
	</div>
	<div id="bbsArticle">
		
		<div id="bbsArticle_header">
			${dto.subject }
		</div>
		
		<div class="bbsArticle_bottomLine">
			<dl>
				<dt>작성자</dt>
				<dd>${dto.name }</dd>
				<dt>줄수</dt>
				<dd>${lineSu }</dd>
			</dl>		
		</div>
		
		<div class="bbsArticle_bottomLine">
			<dl>
				<dt>등록일</dt>
				<dd>${dto.created }</dd>
				<dt>조회수</dt>
				<dd>${dto.hitCount }</dd>
			</dl>		
		</div>
		
		<div id="bbsArticle_content">
			<table width="600" border="0">
			<tr>
				<td style="padding-left: 20px 80px 20px 62px;" 
				valign="top" height="200">
				${dto.content }
				</td>
			</tr>			
			</table>
		</div>
		
		<div class="bbsArticle_bottomLine">
			이전글:
			<!-- 제목이 있을때만 보여준다.  -->
		<c:if test="${!empty preSubject }">
		<a href="<%=cp %>/bbs/article.action?${params }&boardNum=${preBoardNum }">
		${preSubject }</a>
		</c:if>	
		</div>
		
		<div class="bbsArticle_noLine">
			다음글:
			<!-- 제목이 있을때만 보여준다.  -->
		<c:if test="${!empty nextSubject }">
		<a href="<%=cp%>/bbs/article.action?${params}&boardNum=${nextBoardNum}">
		${nextSubject }</a>
		</c:if>		
		</div>
	</div>
	<div class="bbsArticle_noLine" style="text-align: right">
	From : ${dto.ipAddr }
	</div>
	
	<div id="bbsArticle_footer">
		<div id="leftFooter">
			<input type="button" value=" 수정 " class="btn2" onclick=""/>
			<input type="button" value=" 삭제 " class="btn2" onclick=""/>
		</div>
		<div id="rightFooter">
			<input type="button" value=" 리스트 " class="btn2"
			 onclick="javascript:location.href='<%=cp%>/bbs/list.action?${params }'"/>
		</div>	
	</div>
	
</div>
</body>
</html>

게시물을 클릭했을 때  article.jsp 페이지

 

 

 

 

 

다음 시간에는 스트럿츠 2 + 아이 바티스를 이용한  수정 삭제 답변를 해서 올릴 것이다.