-
Strtus2 프레임웤WEB 2020. 7. 6. 21:36
라이브러리 설치
→
https://archive.apache.org/dist/struts/binaries/
2.0.14 버전을 설치할 것임
→
struts-2.0.14-all.zip
→
lib
→ 4개의 필수 라이브러리
- freemarker-2.3.8.jar
- ognl-2.6.11.jar
- struts2-core-2.0.14.jar
- xwork-2.0.7.jar
commons-logging-1.1.1.jar
web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0"> <display-name>StrutsToddler</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> <!-- 스트럿츠의 프론트 앤드 컨트롤러 선언 : 스트럿츠 프레임웤의 default url pattern의 확장자는 *.action 인데 do을 쓰기 위해서 url 에서 *.do 으로 해준다. url pattern 의 확장자 변경시 설정파일에서 설정 스트럿츠의 설정파일(xml) : (빌드 패스 | 클래스 패스 루트) 하위에 존재 파일명 - struts.xml 외부 설정파일 존재시 - struts.properties 이 이름으로 해서 쓰면 됨 --> <filter> <filter-name>struts2</filter-name> <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class> </filter> <filter-mapping> <filter-name>struts2</filter-name> <url-pattern>*.do</url-pattern> </filter-mapping> <!-- log4j를 패키지에 넣으면 작동이 안하는데 패키지에 넣어서 활용할수 있도록 default 패키지이기 때문에 --> <listener> <!-- Application(ServletContext) --> <listener-class>kr.or.ddit.listener.Log4jInitializeListener</listener-class> </listener> </web-app>
- 스트럿츠의 프론트 앤드 컨트롤러 선언 :
- 스트럿츠 프레임웤의 default url pattern의 확장자는 *.action 인데 do을 쓰기 위해서 url 에서 *.do 로 해준다.
- action은 기본이기 때문에 *.action으로 그대로 사용 가능 하지만 *.do를 사용하기 위해서는 struts.porperties 에서 사용할 수 있게 해줘야 한다.
- url pattern 의 확장자 변경시 설정파일에서 설정
- struts.action.extension=do => 이 파일이 있어야 do를 쓸 수 있다.
- 스트럿츠 프레임웤의 default url pattern의 확장자는 *.action 인데 do을 쓰기 위해서 url 에서 *.do 로 해준다.
- 스트럿츠의 설정파일(xml) : (빌드 패스 | 클래스 패스 루트) 하위에 존재
- 파일명 - struts.xml
- 외부 설정파일 존재시 - struts.properties 이 이름으로 해서 쓰면 됨
- log4j를 패키지에 넣기 위해서는 listenter 를 사용해야 한다.
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> <!-- <constant name="struts.enable.DynamicMethodInvocation" value="false" /> --> <!-- <constant name="struts.devMode" value="false" /> --> <!-- <constant name="struts.i18n.encoding" value="UTF-8" /> --> <!-- <constant name="struts.action.extension" value="do" /> --> <!-- 스트럿츠 설정파일 규칙 : 반드시 한개 이상의 패키지가 존재해야하고, 해당 패키지 내에는 반드시 한개의 액션이 선언되어잇어야 함. package : 모듈 단위. name - 다른 패키지와 구분을 위한 구분자(유일한 이름으로 명명이 요구됨) extends - 스트럿츠 프레임웤이 제공하는 자원들을 상속 다른 기타 패키지의 상속을 위해서도 활용 상속 가능한 패키지 -> abstract = true 선언 액션이 포함되지 않음(액션 선언 불가능) namespace - 클라이언트 요청시 URI 에서 해당 패키지에 접근이 가능한 URI 맵핑과 해당 패키지 내에 선언된 액션의 접근 맵핑 action - 클라이언트 요청시 URI 에서 해당 패키지에 접근으로 해당 패키지 내 선언된 액션 접근 맵핑 name - 클라이언트 요청시의 서블릿 맵핑 처리 class - 클라이언트 요청시 해당 요청을 처리하기 위한 비지니스 로직이 요구될때 패키지명. 클래스명 선언 * 단순한 정적인 응답 컨텐츠만을 클라이언트 제공시 생략 가능. result 라는 녀석을 받음 -> view를 결정한다. 다른 액션 대상의 리다이렉트 및 포워딩 처리 name - default success (생략 가능) type - dispatcher(생략 가능 : 포워딩 처리 선언) redirectAction(액션에서 동일 또는 다른 패키지 내 액션으로 리다이렉트 처리) chain(액션에서 동일 또는 다른 패키지 내 액션으로 포워딩 처리) --> <!-- http://localhost/StrutsToddler/hello/hello.do --> <package name="helloPKG" extends="struts-default" namespace="/hello"> <action name="hello" class="kr.or.ddit.hello.controller.HelloController"> <result name="success" type="dispatcher">/WEB-INF/views/user/hello/hello.jsp</result> </action> </package> <!-- 외부에 설정 파일을 만들고 참조 하게 만든다. 코드가 길어지면 유지보수 하기 힘들다. --> <include file="kr/or/ddit/struts/config/join.xml"></include> <include file="kr/or/ddit/struts/config/member.xml"></include> <!-- 밑에 전부 삭제 --> <!-- // 임시 index.do 생성 , 차후 삭제 --> <!-- <package name="default" extends="struts-default"> --> <!-- <action name="index"> --> <!-- <result name="success">/main.jsp</result> --> <!-- </action> --> <!-- </package> --> <!-- <include file="community/struts-join.xml" /> --> <!-- <include file="community/struts-mypage.xml" /> --> <!-- <include file="community/struts-note.xml" /> --> <!-- <include file="community/struts-mypage-admin.xml" /> --> <!-- 커뮤니티 관련 스트럿츠 파일 --> <!-- <include file="community/struts-community-board.xml"></include> --> <!-- <include file="community/struts-community.xml"></include> --> <!-- <include file="community/struts-fileupload.xml"></include> --> <!-- <include file="community/struts-filedownload.xml"></include> --> <!-- 포털 커뮤니티 메인 스트럿츠 파일 --> <!-- <include file="community/struts-portalcommunity-main.xml"></include> --> <!-- <include file="community/struts-portalcommunity-admin.xml"></include> --> </struts>
스트럿츠 설정파일
- 규칙 : 반드시 한개 이상의 패키지가 존재해야하고, 해당 패키지 내에는 반드시 한개의 액션이 선언되어잇어야 함.
- package : 모듈 단위.
- name - 다른 패키지와 구분을 위한 구분자(유일한 이름으로 명명이 요구됨)
- extends - 스트럿츠 프레임웤이 제공하는 자원들을 상속
- 다른 기타 패키지의 상속을 위해서도 활용
- 상속 가능한 패키지 -> abstract = true 선언
- 액션이 포함되지 않음(액션 선언 불가능)
- namespace - 클라이언트 요청시 URI 에서 해당 패키지에 접근이 가능한 URI 맵핑과 해당 패키지 내에 선언된 액션의 접근 맵핑
- action - 클라이언트 요청시 URI 에서 해당 패키지에 접근으로 해당 패키지 내 선언된 액션 접근 맵핑
- name - 클라이언트 요청시의 서블릿 맵핑 처리
- class - 클라이언트 요청시 해당 요청을 처리하기 위한 비지니스 로직이 요구될때 패키지명. 클래스명 선언
* 단순한 정적인 응답 컨텐츠만을 클라이언트 제공시 생략 가능. - result 라는 녀석을 받음 -> view를 결정한다.
- 다른 액션 대상의 리다이렉트 및 포워딩 처리
- name - default success (생략 가능)
- type
- dispatcher(생략 가능 : 포워딩 처리 선언)
- redirectAction(액션에서 동일 또는 다른 패키지 내 액션으로 리다이렉트 처리)
- chain(액션에서 동일 또는 다른 패키지 내 액션으로 포워딩 처리)
- package : 모듈 단위.
http://localhost/StrutsToddler/hello/hello.do 에 접근하는 방법
- context root 인 StrutsToddler 이하부터 기술
- package 에서 struts-default를 상속받아서 여기에 있는 자원들을 쓸수 있게 하고 namespace="/hello" 폴더를 찾는다.
- action 에서 확장자명을 제외한 hello를 찾으면 kr.or.ddit.hello.controller.HelloController 클래스를 찾아간다. 이 클래스를 action 메서드라고 부른다. 클래스를 수행한 후 밑의 4번과 매핑 된다.
- <result name="success" type="dispatcher">/WEB-INF/views/user/hello/hello.jsp</result>
package kr.or.ddit.hello.controller; // 커맨드 디자인 패턴이 적용된 커맨드 컨트롤러 // 스트럿츠 프레임웤 : 액션 클래스 public class HelloController { // 스트럿츠 프레임웤 내에서 : 액션 메서드 라고 부른다. // 반환 값 : <action> // <result name="액션 메서드의 반환값과 맵핑되는 값"> public String execute(){ System.out.println("HelloController의 execute() 콜백"); // if(true){ // return "success"; // }else{ // return "login"; // } return "success"; } }
/WEB-INF/views/user/hello/hello.jsp 에 값을 준다는 뜻
struts.xml 에 이러한 매핑을 전부 기술하면 코드의 길이가 길어지기 때문에 유지보수가 힘들어진다. 이러한 문제점을 해결하기 위해서 외부 설정 파일을 사용한다.
<include file="kr/or/ddit/struts/config/join.xml"></include>
<include file="kr/or/ddit/struts/config/member.xml"></include>
join.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> <!-- http://localhost/StrutsToddler/user/join/loginForm.do http://localhost/StrutsToddler/user/join/loginForm.do?message=회원이 아닙니다. --> <package name="joinPKG" extends="struts-default" namespace="/user/join"> <action name="loginForm"> <result>/WEB-INF/views/user/join/loginForm.jsp</result> </action> <action name="loginCheck" class="kr.or.ddit.join.controller.LoginCheckAction"> <!-- <result name="loginForm" type="redirectAction"> --> <!-- 로그 보기 싫다면 --> <!-- <param name="namespace">/user/join</param> --> <!-- <param name="actionName">loginForm</param> --> <!-- <param name="message">${message}</param> --> <!-- </result> --> <result name="loginForm" type="redirect"> <!-- 위에 주석 처리한거를 쓰면 로그를 볼수 있다.--> <![CDATA[/user/join/loginForm.do?message=${message}]]> </result> <result name="success" type="chain"> <!-- chain은 foward를 말한다 --> <!-- chain은 action 끼리 연결해 줄때 사용하고 dispather 은 action -> jsp 를 갈때 사용한다. --> <param name="namespace">/user/member</param> <param name="actionName">memberList</param> </result> </action> </package> </struts>
member.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> <package name="memberPKG" extends="struts-default" namespace="/user/member"> <action name="memberList" class="kr.or.ddit.member.controller.MemberListAction"> <!-- <result name="success" type="dispatcher">/WEB-INF/views/user/member/memberList.jsp</result> name="success" type="dispatcher" 생략 가능--> <result>/WEB-INF/views/user/member/memberList.jsp</result> </action> </package> </struts>
kr.or.ddit.join.controller.LoginCheckAction.java
package kr.or.ddit.join.controller; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.util.HashMap; import java.util.Map; import javax.servlet.RequestDispatcher; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import org.apache.struts2.ServletActionContext; import kr.or.ddit.member.service.IMemberService; import kr.or.ddit.member.service.IMemberServiceImpl; import kr.or.ddit.vo.MemberVO; // 요청은 이렇게 들어 온다. /StrutsToddler/user/join/loginCheck.do // ? mem_id=a001&mem_pass=asdfasdf public class LoginCheckAction { // 클라이언트로부터 전송되는 쿼리스트링 취득시 해당 쿼리스트링의 키와 일치하는 // 전역변수 선언 및 setter 선언하면 setter를 통해서 해당 전역변수에 쿼리스트링 // 값이 주입. private String mem_id; private String mem_pass; // 액션 클래스에서 View(jsp) 또는 다른 액션 대상의 리다이렉트 처리시 전달되는 // 값은 전역변수 선언 및 값 할당 후 해당 전역 변수의 getter를 통해 ValueStack 에 저장 후 <- 포워딩 할때에 의미가 있다. // 스트럿츠 설정파일(리다이렉트 또는 포워딩 처리와 무관) 및 View에서 EL 표기법으로 접근 활용이 가능. // ValueStack - HttpServletRequest의 확장된 스트럿츠 프레임웤의 저장 영역 // request.setAttribute() 처리와 동일 <- 포워딩 처리하면 el로 처리 가능 , (리다리렉트도 el 가능 할걸?) private String message; public String execute(){ HttpServletRequest request = ServletActionContext.getRequest(); HttpSession session = request.getSession(); // HttpSession session = request.getSession(true); // HttpServletResponse response = ServletActionContext.getResponse(); Map<String, String> params = new HashMap<String, String>(); params.put("mem_id", mem_id); params.put("mem_pass", mem_pass); IMemberService service = IMemberServiceImpl.getInstance(); MemberVO memberInfo = service.memberInfo(params); if(memberInfo == null){ // <param name="message">${message}</param> // this.message="회원이 아닙니다."; try { // <![CDATA[/user/join/loginForm.do?messgae=${message}]]> this.message = URLEncoder.encode("회원이 아닙니다.", "UTF-8"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } return "loginForm"; // action 이름이다. result 아님 }else{ session.setAttribute("LOGIN_MEMBERINFO", memberInfo); return "success"; // return "memberList"; } } public void setMem_id(String mem_id) { this.mem_id = mem_id; } public void setMem_pass(String mem_pass) { this.mem_pass = mem_pass; } public String getMessage() { return message; } }
type 에서 dispatcher, chain 은 forward 인데 둘의 차이
- dispatcher : action 메서드 -> jsp
- chain : action 메서드 -> action 메서드
loginForm.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!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" /> <link rel="stylesheet" href="${pageContext.request.contextPath }/css/admin.css" type="text/css"> <title>회원관리 관리자 로그인</title> <script type='text/javascript' src = 'http://code.jquery.com/jquery-latest.js'></script> <%-- <script type='text/javascript' src = '${pageContext.request.contextPath }/js/common/validation.js'></script> --%> <%-- <script type='text/javascript' src = '${pageContext.request.contextPath }/js/common/cookieControl.js'></script> --%> <script type="text/javascript"> $(function() { if (eval('${!empty param.message}')) { alert('${param.message}'); } $('.loginBtn').click(function() { const mem_id = $('input[name = mem_id]').val(); const mem_pass = $('input[name = mem_pass]').val(); const $frm = $('<form action="${pageContext.request.contextPath}/user/join/loginCheck.do" method="post"></form>'); const $inputID = $('<input type = "hidden" value ="' + mem_id + '" name = "mem_id"/>'); const $inputPWD = $('<input type = "hidden" value ="' + mem_pass + '" name = "mem_pass"/>'); $frm.append($inputID); $frm.append($inputPWD); $(document.body).append($frm); $frm.submit(); }); }); </script> </head> <body> <table width="770" border="0" align="center" cellpadding="0" cellspacing="0" style="margin: 90px;"> <tr> <td height="150" align="center"><img src="${pageContext.request.contextPath }/image/p_login.gif" /></td> </tr> <tr> <td height="174" style="background: url(${pageContext.request.contextPath }/image/login_bg.jpg); border: 1px solid #e3e3e3;"> <table width="100%" border="0" cellpadding="0" cellspacing="0"> <tr> <td width="260" height="110" align="center" style="border-right: 1px dotted #736357;"> <img src="${pageContext.request.contextPath }/image/logo.jpg" /> </td> <td> <table border="0" align="center" cellpadding="5" cellspacing="0"> <tr> <td><b>아이디</b></td> <td><input type="text" name="mem_id" class="box" tabindex="3" height="18" /></td> <td rowspan="2"> <img src="${pageContext.request.contextPath }/image/login.gif" class="loginBtn"/> </td> </tr> <tr> <td><b>패스워드</b></td> <td><input type="password" name="mem_pass" class="box" tabindex="3" height="18" /></td> </tr> </table> </td> </tr> </table> </td> </tr> </table> </body> </html>
memberList.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> <!DOCTYPE html 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> <table> <thead> <tr> <th>아이디</th> <th>성명</th> <th>주민번호1</th> <th>직업</th> <th>취미</th> </tr> </thead> <tbody> <c:forEach var="memberInfo" items="${memberList }"> <tr> <td>${memberInfo.mem_id }</td> <td>${memberInfo.mem_name }</td> <td>${memberInfo.mem_regno1 }</td> <td>${memberInfo.mem_job }</td> <td>${memberInfo.mem_like }</td> </tr> </c:forEach> </tbody> </table> </body> </html>
추가
SqlMapConfig.xml 에서 JNDI 를 사용 하기 위해서는 context.xml 이 필요하다.
SqlMapConfig.xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE sqlMapConfig PUBLIC "-//ibatis.apache.org//DTD SQL Map Config 2.0//EN" "http://ibatis.apache.org/dtd/sql-map-config-2.dtd"> <sqlMapConfig> <properties resource="kr/or/ddit/ibatis/config/SqlMapConfig.properties" /> <settings cacheModelsEnabled="true" enhancementEnabled="true" lazyLoadingEnabled="true" maxRequests="32" maxSessions="10" maxTransactions="5" useStatementNamespaces="true" /> <!-- java JDBC : autoCommit(false)으로 트랜잭션 처리 autoCommit(false)-commit() -rollback() iBatis JDBC : auto transaction으로 트랜잭션 처리. iBatis는 모든 쿼리를 트랜잭션 단위로 처리. 로컬 트랜잭션 처리 startTransaction(); commitTransaction(); endTransaction(); DBCP(DataBase Connection Pooling) 1. http://commons.apache.org 2. --> <transactionManager type="JDBC"> <!-- DB Connection Pool Leaks 응용프로그램의 로직 실패시 컨넥션의 회수가 불분명해질때 사용중인 컨넥션의 추적 및 회수 옵션 --> <!-- <dataSource type="SIMPLE"> <property name="JDBC.Driver" value="${driver}" /> <property name="JDBC.ConnectionURL" value="${url}" /> <property name="JDBC.Username" value="${username}" /> <property name="JDBC.Password" value="${password}" /> </dataSource> --> <!-- <dataSource type="DBCP"> --> <!-- <property name="driverClassName" value="${driver}" /> --> <!-- <property name="url" value="${url}" /> --> <!-- <property name="username" value="${username}" /> --> <!-- <property name="password" value="${password}" /> --> <!-- <property name="maxActive" value="10" /> --> <!-- <property name="initialSize" value="1" /> --> <!-- <property name="removeAbandoned" value="true" /> 강제 회수 하겠다. --> <!-- <property name="removeAnandonedTimeout" value="60" /> 얼마나 있다가 강제 회수? --> <!-- <property name="testOnBorrow" value="true"/> --> <!-- <property name="validationQuery" value="SELECT 1 FROM DUAL"/> --> <!-- <property name="maxIdle" value="6"/> 몇개 만들건지 --> <!-- <property name="minIdle" value="3"/> 좀더 빨리 빌려주겠다? --> <!-- <property name="logAnandoned" value="true" /> 반납받는상태 pooling 상태 등등 을 보여줌 --> <!-- <property name="maxWait" value="-1" /> 다 빌려줬는데 또 빌려달라고 하는 녀석을 얼마나 대기 시킬건지 -1은 무한대 --> <!-- </dataSource> --> <dataSource type="JNDI"> <!-- java naming directory interface --> <property name="DBJndiContext" value="java:comp/env/jdbc/ddit"/> <!-- 자바 환경변수 밑에 이러한 이름jdbc/ddit으로 선언되어져 있는 자원 --> </dataSource> </transactionManager> <sqlMap resource="kr/or/ddit/ibatis/mapper/member.xml"/> <sqlMap resource="kr/or/ddit/ibatis/mapper/prod.xml"/> <sqlMap resource="kr/or/ddit/ibatis/mapper/zipcode.xml"/> <sqlMap resource="kr/or/ddit/ibatis/mapper/lprod.xml"/> <sqlMap resource="kr/or/ddit/ibatis/mapper/buyer.xml"/> <sqlMap resource="kr/or/ddit/ibatis/mapper/freeboard.xml"/> <sqlMap resource="kr/or/ddit/ibatis/mapper/fileitem.xml"/> </sqlMapConfig>
context.xml
<?xml version="1.0" encoding="UTF-8"?> <Context> <watchededResource>WEB-INF/web.xml</watchededResource> <Resource name = "jdbc/ddit" auth = "jyh6842" type = "javax.sql.DataSource" driverClassName="oracle.jdbc.driver.OracleDriver" url="jdbc:oracle:thin:@localhost:1521:XE" username="jyh6842" password="java" initialSize="10" maxActive="10" maxIdle = "6" minIdle = "3" removeAbandoned = "true" removeAbandonedTimeout = "60" maxWait="-1" factory = "org.apache.tomcat.dbcp.dbcp.BasicDataSourceFactory"> </Resource> </Context>추가
'WEB' 카테고리의 다른 글
Struts2 예제 (3) 2020.07.09 Maven 설정시 볼 것 (0) 2020.07.07 Forward, Redirect 사용처 (0) 2020.07.06 file Upload (0) 2020.07.03 type CLOB => type String 전환 (0) 2020.07.01