오늘부터 struts 프레임워크를 배웠다
먼저 프레임워크란? 복잡한 문제를 해결하거나 서술하는 데 사용되는 기본 개념 구조이다.
간단한 뼈대 , 골조 , 프레임워크라고도 한다.
참고
스트럿츠 프레임 워크는 무엇인가?
자바 기반의 JSP만을 위한 프레임워크 다양한 운영체제에서 활용
오픈소스를 사용하기 때문에 개발에 필요한 부분 수정하여 사용
웹 개발은 프론트와 백앤드로 나뉘는데 디자이너의 프런트엔드 영역과 개발자의 백엔드 영역으로 분리하여
개발을 하자는 목적으로 만들어진 MVC 모델 2 (Model, view, Controller)이다.
이러한 MVC 기반으로 나온 프레임워크가 스트럿츠 프레임워크이며 MVC 모델을 이용하여 웹 구축을 매우 용이하기 때문에 초기에 스트럿츠 프레임워크 기반의 개발이 많이 이루어졌다.
Java EE 웹 애플리케이션을 개발하기 위한 오픈 소스 프레임워크이다.
참고
https://www.castingn.com/sourcing/kkultip_detail/110
struts 1 struts 2를 배우고 나중에 스프링을 배울 예정이다.
Struts 1.3.10 다운로드
https://struts.apache.org/download.cgi#struts2529
이클립스로 이동
다운로드한 struts 라이브러리 파일들을 lib 폴더에 추가한다
jstl 즉 , HTML 코드 내에 java 코드인 스크립틀릿 <%= student%>를 ${student}로 <%=if%> 문을
<c:if> <%=for%> 문을 <c:forEach>로 대체하여 사용하기 위한 자바서버 페이지 표준 태그 라이브러리 JSTL도 추가한다.
db연동을 하기 위한 JDBC 드라이버인 ojdbc6 , standard jstl의 표준 라이브러리 도 추가한다.
총개수는 23개가 된다.
이미 jstl ojdbc6 이 스트럿츠에서도 사용하지만 카피해놓은 이유는 이미 있는 것은 버전이 낮으므로
그래서 덮어 씌운 것이다.
스트럿츠가 워낙 옛날것이므로 카피해놓은 것이다.
com.util 폴더를 생성하여
DBConn DB 연결 객체
FileManager 파일 업로드
페이징 처리를 위한 MyUtil
추가한다.
UTF-8로 바꾸는 인코딩 필터도 추가한다.
테스트
<%@ 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>
<h1>Struts Framework</h1>
</body>
</html>
웹서버가 잘 실행되는 것을 볼 수 있다.
이제 환경설정 파일을 만들 것인데 xml로 만들어야 한다.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts-config
PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.3//EN"
"http://struts.apache.org/dtds/struts-config_1_3.dtd">
<struts-config> // 스트럿츠 모든설정은 이 엘리먼트안에서 설정된다.
<global-forwards> // 공용적인 환경세팅을 하기위함
<forward name="welcome" path="/Welcome.do"/> // welcome이라는 이름이 오면 welcom.do로 찾아가라
</global-forwards>
</struts-config>
struts-config.xml 추가 ( 공통 세팅을 하는 곳 )
스트럿츠를 사용하기 위해서는
PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.3//EN"
"http://struts.apache.org/dtds/struts-config_1_3.dtd">
추가해줘야 한다.
이제부터 struts-confing를 사용할 수 있다. 왜냐하면 위에서 추가한 소스가 문법 검사를 해주기 때문이다.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts-config
PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.3//EN"
"http://struts.apache.org/dtds/struts-config_1_3.dtd"> // 그대로 복사하여 붙여넣기 한다
<!-- 각각의 기능에 대한 환경설정 -->
<struts-config>
</struts-config>
struts-config_temp.xml 파일 추가 (각각의 프로젝트에 각각의 환경 세팅 샘플 파일)
temp로 준 이유는 복사해서 그대로 이름 똑같이 쓰고 _board.xml , 또 복사하여 _file.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>struts</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>
<servlet>
<servlet-name>action</servlet-name>
<servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
<init-param>
<param-name>config</param-name>
<param-value> // 환경설정을 사용하기 위해 추가한다.
/WEB-INF/struts-config.xml, // 공통적인 환경 설정
/WEB-INF/struts-config_test.xml, // 각각 개인프로그램의 환경 세팅
/WEB-INF/struts-config_board.xml
</param-value>
</init-param>
<load-on-startup>2</load-on-startup> // servlet을 지정한것 블록범위 우선순위를 2번째로 둔다
// 나중 어노테이션을쓰면서 코딩을하는데
// 어노테이션이 1순위
</servlet>
// 매핑작업
<servlet-mapping>
<servlet-name>action</servlet-name> // 서블릿네임은 위에 action과 같아야 한다.
<url-pattern>*.do</url-pattern> // 파일의 이름이 .do 주소가오면 무조건 action으로 찾아가서
// ActionServlet 으로 문법검사를 하고
// config.xml , confing_board.xml로 가라는 소리이다.
</servlet-mapping>
<!-- 인코딩 필터 -->
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>com.filter.EncodingFilter</filter-class>
<init-param>
<param-name>charset</param-name>
<param-value>utf-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
web.xml 파일
<servlet-class> org.apache.struts.action.ActionServlet </servlet-class>
ActionServlet : 스트럿츠에 대한 문법 검사를 해준다. (문법 검사를 위해서 찾아가기 위해 세팅해준다 )
이제 데이터를 넘기는 작업을 해본다
결과를 입력하는 write.jsp 와 결과를 뿌려주는 write_ok.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>
// action에 내맘대로 정하는 주소
<form action="<%=cp%>/test_ok.do" method="post"> // method생략시 post방식이다.
아이디:<input type="text" name="userId"/><br/>
패스워드:<input type="password" name="userPwd"/><br/>
이름:<input type="text" name="userName"/><br/>
<input type="submit" value="전송"/><br/>
</form>
</body>
</html>
데이터가 넘어가는 방식을 이해한다.
이제 DTO를 만들어본다.
package com.test;
import org.apache.struts.action.ActionForm;
// 프레임워크는 모든 데이터를 넘겨받고 하는 모든 방법을 스트럿츠 1 , 2 방식을 지켜야된다.
// DTO를 관리하는 클래스가 있는데 스트럿츠가 관리해주는 클래스가 있다.
// 스트럿츠한테 관리를 맡길 것이다. 바로 ActionForm 이 있다.
public class TestForm extends ActionForm{ // ActionForm이라는 애가 TestDTO를 관리하게 된다.
// 폼이라고 쓴 이유 ActionForm이 관리하므로
private static final long serialVersionUID = 1L;//DTO
private String userId;
private String userPwd;
private String userName;
// getter / setter
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;
}
}
DTO를 Form이라고 한다.
package com.test;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
// 일반클래스가 액션의 역할을 하기 위해서 Action 상속받음
// 이번에 한번만 쓰고 앞으로는 안쓸것이다. 나중 좀더 좋은얘를 쓸것이다.
public class TestAction extends Action {
@Override
// excute :
// ActionForm 위에서 상속받은 ActionForm 3개의 데이터를 form으로 넣어준다.
// 데이터 타입은 무조건 object 로 넣어준다.
public ActionForward execute(ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response) throws Exception {
String uri = request.getRequestURI(); // 주소를 읽어온다.
if(uri.indexOf("/test_ok.do")!=-1) { // 서블릿과 비슷
TestForm f = (TestForm)form; // object -> 다운캐스팅 하여 사용한다.
request.setAttribute("vo", f); // f를 넘겨준다. dto를 안쓰므로 vo로 일단 변수명으로 저장
return mapping.findForward("ok"); // ok라는 문자를 가지고 돌아가라
}
// 만약에 실행되지 않으면
return mapping.findForward("error"); // error라는 문자를 가지고 돌아가라
}
}
TestAction.java 추가
<%@ 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>
// $ 달러 el로 받아낸다.
// 넘어오는 데이터는 vo로 받아낸다
아이디: ${vo.userId }<br/>
패스워드 : ${vo.userPwd }<br/>
이름 : ${vo.userName }<br/>
<a href="javascript:location.href='<%=cp %>/test.do';">돌아가기</a>
</body>
</html>
받아내는 클래스 write_ok.jsp
test.do를 입력하게 되면 write.jsp가 나온다.
write.jsp에 값을 입력하고 ok버튼을 누르면 만든 데이터를 TestAction으로 넘겼다가
Action에서 처리 작업을 하고 write_ok.jsp로 데이터를 넘긴다
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts-config
PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.3//EN"
"http://struts.apache.org/dtds/struts-config_1_3.dtd">
<!-- 각각의 기능에 대한 환경설정 -->
<struts-config>
// 갈때 사용자가 입력한 데이터를 자동으로 testForm에 담겨서 넘어와야하는데
// testForm은 ActionForm이 관리한다 스스로 객체생성할수없으므로 작업을 해줘야한다.
<form-beans>
// 객체 생성 이름은 com.test.TestForm이라는 클래스를 testForm이라는 이름으로
// 객체를 생성해라
// 데이터가 3개(아이디,이름,패스워드) 가 들어가게됨
<form-bean name="testForm" type="com.test.TestForm"/>
</form-beans>
<action-mappings>
// test.do는 web.xml 에 *.do에 의해 .do 생략됨
// forward = 실제주소로 이동 시킴
<action path="/test" forward="/test/write.jsp"/>
// 사용자가 아이디 패스워드 이름 까지 입력하고 ok버튼을 누를때
// com.test.TestAction 으로 가라
// 갈때 사용자가 입력한 데이터를 자동으로 testForm에 담겨서 넘어와야하는데
// testForm은 ActionForm이 관리한다 스스로 객체생성할수없으므로 작업을 해줘야한다.
// 위에서 객체를 생성해준다
// 이제 TestAction으로 갈때 name=testForm을 가지고 가면 된다.
<action path="/test_ok" type="com.test.TestAction"
name="testForm" scope="request"> // request 1:1관계에서의 데이터를 넘겨줄때
<forward name="ok" path="/test/write_ok.jsp"/>
<forward name="error" path="/test/error.jsp"/>
</action>
</action-mappings>
</struts-config>
mapping.findForward("ok") -> ActionMapping mapping
잘 실행되면 ok라는 문자를 가지고 잘못 실행되면 error라는 문자를 가지고
request> 끝으로 돌아오게 된다.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts-config
PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.3//EN"
"http://struts.apache.org/dtds/struts-config_1_3.dtd">
<!-- 각각의 기능에 대한 환경설정 -->
<struts-config>
<form-beans>
<form-bean name="testForm" type="com.test.TestForm"/>
</form-beans>
<action-mappings>
<action path="/test" forward="/test/write.jsp"/>
<action path="/test_ok" type="com.test.TestAction"
name="testForm" scope="request">
// 가지고온 값이 ok 이면 write_ok.jsp로 간다.
// 만약 돌아온 값이 error이면 error.jsp로 간다.
<forward name="ok" path="/test/write_ok.jsp"/>
<forward name="error" path="/test/error.jsp"/>
</action>
</action-mappings>
</struts-config>
돌아오는 값의 문자에 의해서 이동하게 된다.
기존 서블릿의 약점이 있다
프로젝트가 작아서 이문제가 없었는데
프로젝트의 크기가 커지게 되면 은행권 이면 엄청나게 복잡하다
주소도 굉장히 복잡해질수록 else if가 늘어나게 된다.
path를 수도 없이 비교하게 됨 -> 속도가 느려진다
디렉트로 찾아서 실행하고 싶으면
메서드로 바꿔주면 된다.
전자정부 프레임워크 포털 사이트
package com.board;
import org.apache.struts.action.ActionForm;
public class BoardForm extends ActionForm {
private static final long serialVersionUID = 1L;
private int num;
private String name;
private String subject;
private String content;
private String pwd;
private String email;
private int hitCount;
private String ipAddr;
private String created;
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
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 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 int getHitCount() {
return hitCount;
}
public void setHitCount(int hitCount) {
this.hitCount = hitCount;
}
public String getIpAddr() {
return ipAddr;
}
public void setIpAddr(String ipAddr) {
this.ipAddr = ipAddr;
}
public String getCreated() {
return created;
}
public void setCreated(String created) {
this.created = created;
}
}
BoardForm 추가
ActionForm이 9개의 변수를 Action에다가 넘겨준다.
이번이 마지막 jdbc 이가 다음번에는 아이 바티스를 할 것이다.
package com.board;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.sql.Connection;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.actions.DispatchAction;
import com.util.DBConn;
import com.util.MyUtil;
public class BoardAction extends DispatchAction{
// Action을 상속받았을때는 excute는 if문으로 구분했지만
// DispatchAction은 else if문을 메소드 단위로 만들겠다는 소리다.
// 사용자정의 write 메소드 지정 가능
// findForward("사용자정의")
public ActionForward write(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws Exception {
return mapping.findForward("created"); //created라는 문자를 가지고 돌아가게하면 된다.
}
public ActionForward write_ok(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws Exception {
Connection conn = DBConn.getConnection();
BoardDAO dao = new BoardDAO(conn);
BoardForm f = (BoardForm)form;
f.setNum(dao.getMaxNum() + 1);
f.setIpAddr(request.getRemoteAddr());
dao.insertData(f);
return mapping.findForward("save");
}
public ActionForward list(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws Exception {
Connection conn = DBConn.getConnection();
BoardDAO dao = new BoardDAO(conn);
String cp = request.getContextPath();
MyUtil myUtil = new MyUtil();
String pageNum = request.getParameter("pageNum");
int currentPage = 1;
if(pageNum!=null)
currentPage = Integer.parseInt(pageNum);
String searchKey = request.getParameter("searchKey");
String searchValue = request.getParameter("searchValue");
if(searchValue==null||searchValue.equals("")) {
searchKey = "subject";
searchValue = "";
}else {
if(request.getMethod().equalsIgnoreCase("GET")) {
searchValue = URLDecoder.decode(searchValue, "UTF-8");
}
}
int dataCount = dao.getDataCount(searchKey, searchValue);
int numPerPage = 5;
int totalPage = myUtil.getPageCount(numPerPage, dataCount);
if(currentPage>totalPage)
currentPage = totalPage;
int start = (currentPage-1)*numPerPage+1;
int end = currentPage*numPerPage;
List<BoardForm> lists =
dao.getLists(start, end, searchKey, searchValue);
String param = "";
if(searchValue!=null&&!searchValue.equals("")) {
param = "searchKey=" + searchKey;
param+= "&searchValue=" + URLEncoder.encode(searchValue, "UTF-8");
}
String listUrl = cp + "/board.do?method=list";
// ? -> & 로바꿈 (키와벨류값을 전달하기위해)
if(!param.equals("")) {
listUrl += "&" + param;
}
String pageIndexList =
myUtil.pageIndexList(currentPage, totalPage, listUrl);
String articleUrl = cp + "/board.do?method=article&pageNum=" + currentPage;
if(!param.equals("")) {
articleUrl += "&" + param;
}
//포워딩 페이지에 데이터 넘기기
request.setAttribute("lists", lists);
request.setAttribute("articleUrl", articleUrl);
request.setAttribute("pageIndexList", pageIndexList);
request.setAttribute("pageNum", pageNum);
request.setAttribute("totalPage", totalPage);
request.setAttribute("dataCount", dataCount);
return mapping.findForward("list");
}
public ActionForward article(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws Exception {
Connection conn = DBConn.getConnection();
BoardDAO dao = new BoardDAO(conn);
int num = Integer.parseInt(request.getParameter("num"));
String pageNum = request.getParameter("pageNum");
String searchKey = request.getParameter("searchKey");
String searchValue = request.getParameter("searchValue");
if(searchValue != null) {
searchValue = URLDecoder.decode(searchValue, "UTF-8");
}
dao.updateHitCount(num);
BoardForm dto = dao.getReadData(num);
if(dto==null) {
return mapping.findForward("list");
}
int lineSu = dto.getContent().split("\n").length;
dto.setContent(dto.getContent().replace("\n", "<br/>"));
String param = "pageNum=" + pageNum;
if(searchValue != null && !searchValue.equals("")) {
param += "&searchKey=" + searchKey;
param += "&searchValue=" + URLEncoder.encode(searchValue, "UTF-8");
}
// param으로 담지않은이유 > 다른곳에서 param을 쓰고있어서
request.setAttribute("dto", dto);
request.setAttribute("params", param);
request.setAttribute("linSu", lineSu);
request.setAttribute("pageNum", pageNum);
return mapping.findForward("article");
}
public ActionForward updated(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws Exception {
Connection conn = DBConn.getConnection();
BoardDAO dao = new BoardDAO(conn);
int num = Integer.parseInt(request.getParameter("num"));
String pageNum = request.getParameter("pageNum");
String searchKey = request.getParameter("searchKey");
String searchValue = request.getParameter("searchValue");
if(searchValue != null) {
searchValue = URLDecoder.decode(searchValue, "UTF-8");
}
BoardForm dto = dao.getReadData(num);
if(dto==null) {
return mapping.findForward("list");
}
String param = "pageNum=" + pageNum;
if(searchValue != null&& !searchValue.equals("")) {
param += "&searchKey=" + searchKey;
param += "&searchValue=" + URLEncoder.encode(searchValue, "UTF-8");
}
//이제 데이터 넘김
request.setAttribute("dto", dto);
request.setAttribute("pageNum", pageNum);
request.setAttribute("params", param);
request.setAttribute("searchKey", searchKey);
request.setAttribute("searchValue", searchValue);
return mapping.findForward("updated");
}
public ActionForward updated_ok(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws Exception {
Connection conn = DBConn.getConnection();
BoardDAO dao = new BoardDAO(conn);
// getparameter 요청 = 나 이거 줘 !
String pageNum = request.getParameter("pageNum");
String searchKey = request.getParameter("searchKey");
String searchValue = request.getParameter("searchValue");
// 5개의 데이터가 자동으로 넘어온다.
// 다운캐스팅 해서 받아낸다.
BoardForm f = (BoardForm)form;
f.setNum(Integer.parseInt(request.getParameter("num")));
//수정된 데이터를 보낸다
dao.updateData(f);
//되돌아올때
// &붙여준다 밑에서 + 값을 보내기위해서
String param = "&pageNum=" + pageNum;
if(searchValue != null&& !searchValue.equals("")) {
param += "&searchKey=" + searchKey;
param += "&searchValue=" + URLEncoder.encode(searchValue, "UTF-8");
}
// 데이터를 넘겨주면 됨
//request.setAttribute("params", param);
//request.setAttribute("pageNum", pageNum);
// return mapping.findForward("updated_ok");
// 수정버튼 누르면 원래 검색페이지로 돌아오게 하기위한 방법
// 파라미터 값을 보내려면 xml에서는 못보냄
// 그래서 여기서 처리해줘야함
ActionForward af = new ActionForward();
af.setRedirect(true);
af.setPath("/board.do?method=list"+ param);
return af;
}
public ActionForward deleted_ok(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws Exception {
Connection conn = DBConn.getConnection();
BoardDAO dao = new BoardDAO(conn);
// pagenum , 설치키 , 설치 벨류 가져와
int num = Integer.parseInt(request.getParameter("num"));
String pageNum = request.getParameter("pageNum");
String searchKey = request.getParameter("searchKey");
String searchValue = request.getParameter("searchValue");
dao.deleteData(num);
// 돌아갈곳
String param = "&pageNum="+pageNum;
if(searchValue!=null&&!searchValue.equals("")) {
param += "&searchKey=" + searchKey;
param += "&searchValue=" +
URLEncoder.encode(searchValue,"UTF-8");
}
// 리스트로 바로간다.
ActionForward af = new ActionForward();
af.setRedirect(true);
af.setPath("/board.do?method=list"+ param);
return af;
}
}
if문을 메서드로 만들었다.
파일을 추가했으면 web.xml에 추가해줘야 한다.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts-config
PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.3//EN"
"http://struts.apache.org/dtds/struts-config_1_3.dtd">
boardForm가져가라
parameter : a.jsp?a=10&b=20 딸려가면서 어느메소드 찾아가라고 명시해줌
메소드에 담을 메소드가 필요하다.
scope = request : "영역 이객체가 충돌될수있으니 request한도내에서 인식 1:1 관계에서만 boardAction 까지만
http://localhost:8080/struts/board.do?method=write
parameter = method = > ?method=write
parameter="method" -> method 에 wrtie 가 들어오게된다.
created 문자를 가져오면 /board/created.jsp 로 이동해라
forward일때 실제주소 , redirect 일때 가상주소
insert delete update 할때는 redirect준다.
-->
<struts-config>
<form-beans>
// dto 객체 생성 한다
<form-bean name="boardForm" type="com.board.BoardForm"/>
</form-beans>
<action-mappings>
// /board.do가 오면 com.board.BoardAction으로 가라
// 갈때 boardForm을 가져가라
<action path="/board" type="com.board.BoardAction"
name="boardForm" scope="request" parameter="method">
<!-- return mapping.findForward("created"); -->
<forward name="created" path="/board/created.jsp"/>
<forward name="save" redirect="true"
path="/board.do?method=list"/>
<forward name="list" path="/board/list.jsp"/>
<forward name="article" path="/board/article.jsp"/>
<forward name="updated" path="/board/updated.jsp"/>
<!-- <forward name="updated_ok" redirect="true"
path="/board.do?method=list"/> -->
</action>
</action-mappings>
</struts-config>
메서드로 디렉트로 찾아가기 때문에 이 방법을 쓰게 된다.
parameter 란?
a.jsp? a= 10 & b= 20 넘어오는 값을 파라미터라고 하는데
파라미터가 항상 딸려가면서 어느 메서드가 찾아가 라고 명시해준다
getParameter에서 쓰이는데
write를 찾아가라고 그 메서드를 담을 변수가 필요한데
그 변수 이름을 method라고 했다 다른 이름으로 해도 된다.
BoardAction에 가서 처리 작업을 하러 가는데
created라는 문자를 가지고 돌아간다
created라는 문자가 돌아오면
path /board/created.jsp를 띄어라
이게 스트럿츠이다.
흐름
/board.do 가 오면 BoardAction으로 가라
갈 때 위에 boardForm의 객체를 가져가라
만약에 데이터가 없으면 아무것도 입력하지 않고 객체만 만들고 null 값이 넘어감
boardForm를 가지고 BoardAction에 가서 write를 찾아라
parameter=method 안에 있는 값을 찾는다
우리는 method="write"를 가르쳐줬으므로 파라미터 안에 write라는 메서드를 BoardAction에서 찾으라는 소리이다.
BoardAction으로 가서
디렉트로 write라는 메서드를 찾게 된다.
form의 값을 가지고 처리하지 않으므로
write라는 메서드를 찾아왔으면 created라는 문자를 가지고 돌아가라고 하는 것이다.
created라는 문자를 가지고 왔으니까
/board/created.jsp로 이동해라
그래서 jsp사이트가 뜨게 된다.
scope 영역 이란 뜻으로 객체가 만들어지면서 웹은 동시에 수만 명이 접속할 수 있으므로
이 이름이 충돌 날 수 있으므로
객체 생성 이름을 request 한도 내에서만 인식할 수 있도록 했다
request는 1:1의 관계 즉, BoardAction으로 넘어가는 순간까지만 이고 돌아올 때는 이름을 잃어버린다.
여러 사람이 객체를 같은 이름으로 생성해도 충돌 나지 않는다
<%@ 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;
f.action = "<%=cp%>/board.do"; // 무조건 board.do로 찾아가라 거기서 주소를 구분한다.
f.submit();
}
</script>
</head>
<body>
<div id="bbs">
<div id="bbs_title">
게 시 판 (Struts1)
</div>
<form action="" method="post" name="myForm">
<div id="bbsCreated">
<div class="bbsCreated_bottomLine">
<dl>
<dt>제 목</dt>
<dd>
<input type="text" name="subject" size="60"
maxlength="100" class="boxTF"/>
</dd>
</dl>
</div>
<div class="bbsCreated_bottomLine">
<dl>
<dt>작성자</dt>
<dd>
<input type="text" name="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" size="35"
maxlength="50" class="boxTF"/>
</dd>
</dl>
</div>
<div id="bbsCreated_content">
<dl>
<dt>내 용</dt>
<dd>
<textarea rows="12" cols="63" name="content"
class="boxTA"></textarea>
</dd>
</dl>
</div>
<div class="bbsCreated_noLine">
<dl>
<dt>패스워드</dt>
<dd>
<input type="password" name="pwd" size="35"
maxlength="7" class="boxTF"/>
(게시물 수정 및 삭제시 필요!!)
</dd>
</dl>
</div>
</div>
<div id="bbsCreated_footer">
<input type="hidden" name="method" value="write_ok"/>
<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%>/board.do?method=list';"/>
</div>
</form>
</div>
</body>
</html>
created.jsp
f.action = "<%=cp%>/board.do에 의해서 board.do로 이동하게 된다.
최소한 뒤에 파라미터가 와야 한다.
method , num , pageNum , serachKey, searchValue 검색까지 했으면 무조건 5개가 넘어가야 한다.
무슨 메서드를 찾아갈지 지정해주지 않으면
parameter = "method" 안에는 null 값이 들어가게 된다.
f.action="<%=cp%>/board.do?method=write_ok"; 써주면 되는데 그런데
이렇게 써주는 것보단 고급진 방법이 있다
hidden으로 넘겨주면 된다.
히든으로 메서드 wrtie_ok가 담겨서 보내지게 된다.
우리 눈에는 안 보이지만 파라미터에 wrtie_ok가 담겨서 보내지는데
write_ok라는 메서드가 없다는 오류가 나타난다.
우리는 BoardAction에다가 wrtie_ok라는 메서드를 만들어줘야 한다.
돌아올 때 save를 가지고 돌아온다
돌아오는 save를 forward로 적어주면 된다.
save라는 값이 돌아오면
insert , update , delete , 세션이 바뀌었을 때 redirect 시켜야 한다.
path는 가상의 주소로 이동시킨다. 이때 method에는 list값을 넣어준다
리스트 메서드를 찾아가게 되고 list라는 문자 가지고 돌아간다.
parameter = "method"로 떨어진다.
redirect 일 때는 가상의 주소
forward 일때는 진짜 주소
<%@ 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%>/board.do?method=list";
f.submit();
}
</script>
</head>
<body>
<div id="bbsList">
<div id="bbsList_title">
게 시 판 (struts)
</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%>/board.do?method=write';"/> // 메소드는 write로 가게한다.
</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">
<!-- lists를 하나씩꺼내서 dto라는 변수에 넣음 -->
<!-- lists를 하나씩꺼내서 dto라는 변수에 넣음 -->
<!-- jstl를 사용한다 -->
<c:forEach var="dto" items="${lists }">
<dl>
<dd class="num">${dto.num }</dd>
<dd class="subject">
<a href="${articleUrl}&num=${dto.num}">
${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="${datacount!=0 }">
${pageIndexList }
</c:if>
<c:if test="${datacount==0 }">
등록된 게시물이 없습니다.
</c:if>
</div>
</div>
</div>
</body>
</html>
list.jsp
글 올리기 누르면 wrtie 가 뜨게 된다.
created에서 입력한 5개의 데이터가 boardForm에 담겨서 BoardAction으로 넘겨온다
boardForm은 ActionFrom이 관리하므로
BoardAction에서 ActionForm form 부분이다.
form에는 5개의 데이터가 있는 것이다
데이터 타입이 object이므로 BoardForm으로 다운 캐스팅해줘야 함
form에서의 5개의 데이터와 maxNum , request.getRemoteAddr 2 개의 데이터를 합쳐 7개의 데이터를 넘겨주면 된다.
<%@ 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>게 시 판(Struts1)</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">
게 시 판(Struts1)
</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>
<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="javascript:location.href='<%=cp%>/board.do?method=updated&num=${dto.num }&${params }'"/>
<input type="button" value=" 삭제 " class="btn2"
onclick="javascript:location.href='<%=cp%>/board.do?method=deleted&num=${dto.num }&${params }'"/>
</div>
<div id="rightFooter">
<input type="button" value=" 리스트 " class="btn2"
onclick="javascript:location.href='<%=cp%>/board.do?method=list&${params }'"/>
</div>
</div>
</div>
</body>
</html>
article.jsp
/sboard/ 물음표가 없을 때
/board.do?method=article&pageNum=" + currentPage
앞에? 가 있을 때
<%@ 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>게 시 판(Struts1)</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;
f.action = "<%=cp%>/board.do";
f.submit();
}
</script>
</head>
<body>
<div id="bbs">
<div id="bbs_title">
게 시 판 (Struts1)
</div>
<form action="" method="post" name="myForm">
<div id="bbsCreated">
<div class="bbsCreated_bottomLine">
<dl>
<dt>제 목</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>내 용</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"/>
(게시물 수정 및 삭제시 필요!!)
</dd>
</dl>
</div>
</div>
<div id="bbsCreated_footer">
<!-- value = "updated_ok" 로 알아서 넘어간다. -->
<input type="hidden" name="method" value="updated_ok"/>
<input type="hidden" name="num" value="${dto.num }">
<input type="hidden" name="pageNum" value="${pageNum }">
<input type="hidden" name="searchKey" value="${searchKey }">
<input type="hidden" name="searchValue" value="${searchValue }">
<input type="button" value=" 수정하기 " class="btn2" onclick="sendIt();"/>
<input type="button" value=" 수정취소 " class="btn2"
onclick="javascript:location.href='<%=cp%>/board.do?method=list&${params }';"/>
</div>
</form>
</div>
</body>
</html>
updated.jsp
board.do?method=updated&num=46&pageNum=1
2페이지 눌렀을 때 URL
스트럿츠는 경로에 &pageNum=${pageNum} el를 해도 못 붙인다.
다른 방법으로 처리해줘야 한다.
update에서 데이터를 넘길 때는
xml로 돌아와서 list 뒤에 붙일 수가 없어서 여기로 돌아오면 안 되고
return mapping.findForward("updated_ok")를 고쳐서 여기서 끝내버려야 된다
주석 처리하고
ActionForward af = new ActionForward() 객체 생성하고
af.setRedirect(true); 리디렉트 시키고
af.setPath("/board.do?method=list&pageNum="+pageNum + param)
게시물을 눌렀을 시 수정, 삭제, 리스트의 하이퍼링크
모든 주소 매핑은 xml에서 다해준다
무조건 BoardAction으로 가면서 내가 찾고 자하는 메서드를 반드시 가지고 간다.
그래서 주소에 메서드가 따라붙어야 한다.
메서드라는 변수 parameter="method" 내 맘대로 변수명을 만들면 된다.
혼동되지 않게 method라고 지었고 다른 이름으로 사용해도 된다.
지금까지 스트럿츠를 가지고 jdbc를 연결하여서 게시판을 만들어봤다
jdbc로 중복되는 데이터가 너무 많다 보니
db 연결하는 ibatis 가 나오게 되었고
다음 시간은 스트럿츠에 ibatis를 사용하는 방법을 배워보겠다
이제 jdbc는 스프링 할 때 잠깐 쓰일 것이다.
'BACKEND > 아파치 스트럿츠 1 , 2' 카테고리의 다른 글
[struts2] 스트럿츠2 + iBatis를 이용한 답변형 게시판 중 (2) (답변형 게시판 , 수정 , 삭제 ) (0) | 2022.03.14 |
---|---|
[Struts2] 스트럿츠2 + iBatis 파일업로드/다운로드/보기 기능 (0) | 2022.03.14 |
[Struts1] 스트럿츠1 + iBatis 파일업로드 (2) | 2022.03.14 |
[struts2] 스트럿츠2 + iBatis를 이용한 답변형 게시판 중 1 (글쓰기 , 수정 , 이전글 , 다음글 ) (0) | 2022.03.14 |