apache Struts 프레임워크
예전에 쓰던 자동화를 아주 잘해둔 프레임워크 스프링을 해보기전 비교느낌으로 체험
자바 프로젝트로 만들기
다운로드
빌드 패스에 다운받은 라이브러리들 추가
라이브러리 등록
필터 방식으로 구현하고있음 web.xml에 필터 추가
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
src에 struts.xml 생성
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
<constant name="struts.devMode" value="true" />
<package name="basicstruts2" extends="struts-default">
<action name="index" class="com.bit.controller.IndexAction">
<result>/index.jsp</result>
</action>
</package>
</struts>
Action인터페이스를 상속받아 controller 생성, index.jsp 생성
package com.bit.controller;
import com.opensymphony.xwork2.Action;
public class IndexAction implements Action{
@Override
public String execute() throws Exception {
System.out.println("스트럿츠 액션");
return "success";
}
}
index.action으로 접속 시 index.jsp 화면 출력됨
maven 프로젝트로 만들기
만드는 순간 샘플로 코드들이 다 들어가 있어서 바로 실행 가능하다.
org.apache.maven -> webapp으로 프로젝트 만든 후 struts 라이브러리 추가하기
-------------------- pom.xml 의존성 추가
<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.struts/struts2-core -->
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-core</artifactId>
<version>2.5.22</version>
</dependency>
------------------- web.xml 필터 추가
<filter>
<filter-name>struts</filter-name>
<filter-class>org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>struts</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
struts, mongoDB - CRUD 예제
pom.xml - dependency 추가, jetty 플러그인 추가
<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/javax.servlet/jstl -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/log4j/log4j -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<!-- https://mvnrepository.com/artifact/javax.servlet.jsp/jsp-api -->
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.2</version>
<scope>provided</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.mongodb/mongo-java-driver -->
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongo-java-driver</artifactId>
<version>3.12.12</version>
</dependency>
...
<plugins>
<plugin>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>9.4.7.v20170914</version>
<configuration>
<webApp>
<contextPath>/${build.finalName}</contextPath>
</webApp>
<stopKey>CTRL+C</stopKey>
<stopPort>8999</stopPort>
<scanIntervalSeconds>10</scanIntervalSeconds>
<scanTargets>
<scanTarget>src/main/webapp/WEB-INF/web.xml</scanTarget>
</scanTargets>
</configuration>
</plugin>
</plugins>
src/main/resources 에 log4j.properties파일과 struts.xml 파일 추가
-------------- log4j.properties
# Set root logger level to DEBUG and its only appender to A1.
log4j.rootLogger=DEBUG, A1
# A1 is set to be a ConsoleAppender.
log4j.appender.A1=org.apache.log4j.ConsoleAppender
# A1 uses PatternLayout.
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n
-------------- struts.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
"http://struts.apache.org/dtds/struts-2.5.dtd">
<struts>
<package name="default" namespace="/" extends="struts-default">
<action name="index" class="com.bit.action.IndexAction">
<result name="success">/index.jsp</result>
</action>
<action name="intro" class="com.bit.action.IndexAction">
<result name="success">/intro.jsp</result>
</action>
</package>
<package name="dept" namespace="/dept" extends="struts-default">
<action name="list" class="com.bit.action.ListAction">
<interceptor-ref name="params"/>
<result name="success">/dept/list.jsp</result>
</action>
<action name="add" class="com.bit.action.IndexAction">
<result name="success">/dept/add.jsp</result>
</action>
<action name="insert" class="com.bit.action.AddAction">
<interceptor-ref name="params"/>
<result name="input">/dept/add.jsp</result>
<result name="success" type="redirectAction">list</result>
</action>
<action name="detail" class="com.bit.action.DeptAction">
<interceptor-ref name="params"/>
<result name="success">/dept/detail.jsp</result>
</action>
<action name="update" class="com.bit.action.UpdateAction">
<interceptor-ref name="params"/>
<result name="input" type="redirect">detail.action?id=${id}</result>
<result name="success" type="redirect">list.action</result>
</action>
</package>
</struts>
DeptVo 와 DeptDao 작성
------------------ DeptVo
package com.bit.model;
import org.bson.types.ObjectId;
public class DeptVo {
private ObjectId id;
private int deptno;
private String dname, loc;
public DeptVo() {
}
public DeptVo(int deptno, String dname, String loc) {
super();
this.deptno = deptno;
this.dname = dname;
this.loc = loc;
}
public DeptVo(ObjectId id, int deptno, String dname, String loc) {
super();
this.id = id;
this.deptno = deptno;
this.dname = dname;
this.loc = loc;
}
public ObjectId getId() {
return id;
}
public void setId(ObjectId id) {
this.id = id;
}
public int getDeptno() {
return deptno;
}
public void setDeptno(int deptno) {
this.deptno = deptno;
}
public String getDname() {
return dname;
}
public void setDname(String dname) {
this.dname = dname;
}
public String getLoc() {
return loc;
}
public void setLoc(String loc) {
this.loc = loc;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + deptno;
result = prime * result + ((dname == null) ? 0 : dname.hashCode());
result = prime * result + ((id == null) ? 0 : id.hashCode());
result = prime * result + ((loc == null) ? 0 : loc.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
DeptVo other = (DeptVo) obj;
if (deptno != other.deptno)
return false;
if (dname == null) {
if (other.dname != null)
return false;
} else if (!dname.equals(other.dname))
return false;
if (id == null) {
if (other.id != null)
return false;
} else if (!id.equals(other.id))
return false;
if (loc == null) {
if (other.loc != null)
return false;
} else if (!loc.equals(other.loc))
return false;
return true;
}
@Override
public String toString() {
return "DeptVo [id=" + id + ", deptno=" + deptno + ", dname=" + dname + ", loc=" + loc + "]";
}
}
------------------ DeptDao
package com.bit.model;
import ...
public class DeptDao {
Logger log = Logger.getLogger("DeptDao");
MongoClient client = new MongoClient(Arrays.asList(
new ServerAddress("localhost", 27117),
new ServerAddress("localhost", 27217),
new ServerAddress("localhost", 27317)));
final String DBNAME = "lecture";
final String COLLNAME = "dept";
public List<DeptVo> findAll(){
List<DeptVo> list = new ArrayList<DeptVo>();
try {
MongoCollection<Document> coll = client.getDatabase(DBNAME).getCollection(COLLNAME);
FindIterable<Document> ite = coll.find();
MongoCursor<Document> cur = ite.cursor();
while (cur.hasNext()) {
org.bson.Document doc = cur.next();
list.add(new DeptVo(doc.getObjectId("_id"), doc.getInteger("deptno"), doc.getString("dname"),
doc.getString("loc")));
}
} finally {
if(client!=null)client.close();
}
log.debug(list.toString());
return list;
}
public void addOne(int deptno, String dname, String loc) {
try {
MongoCollection<Document> coll = client.getDatabase(DBNAME).getCollection(COLLNAME);
Document doc = new Document();
doc.append("deptno", deptno);
doc.append("dname", dname);
doc.append("loc", loc);
coll.insertOne(doc);
} finally {
if(client!=null)client.close();
}
}
public DeptVo findOne(String id) {
DeptVo bean = null;
ObjectId _id = new ObjectId(id);
try {
MongoCollection<Document> coll = client.getDatabase(DBNAME).getCollection(COLLNAME);
Bson filter = Filters.eq("_id", _id);
FindIterable<Document> ite = coll.find(filter);
Document doc = ite.first();
bean = new DeptVo(
doc.getObjectId("_id"),
doc.getInteger("deptno"),
doc.getString("dname"),
doc.getString("loc"));
} finally {
if(client!=null)client.close();
}
return bean;
}
public Long updateOne(String id, int deptno, String dname, String loc) {
ObjectId _id = new ObjectId(id);
try {
MongoCollection<Document> coll = client.getDatabase(DBNAME).getCollection(COLLNAME);
Bson filter = Filters.eq("_id", _id);
Bson update = Updates.combine(
Updates.set("dname", dname),
Updates.set("loc", loc));
UpdateResult result = coll.updateOne(filter, update);
return result.getModifiedCount();
} finally {
if(client!=null)client.close();
}
}
}
controller와 view
------------ IndexAction -> 화면 띄워주기 액션으로 사용
package com.bit.action;
import com.opensymphony.xwork2.Action;
public class IndexAction implements Action {
@Override
public String execute() throws Exception {
return SUCCESS;
}
}
-------------- AddAction - 입력받은 값을 받으려면 setter를 정의해주면 받아온다.(단 view에서 지정한 name과 같아야함)
package com.bit.action;
import com.bit.model.DeptDao;
import com.opensymphony.xwork2.Action;
public class AddAction implements Action {
int deptno;
String dname, loc;
public void setDeptno(int deptno) {
this.deptno = deptno;
}
public void setDname(String dname) {
this.dname = dname;
}
public void setLoc(String loc) {
this.loc = loc;
}
@Override
public String execute() throws Exception {
if(deptno==0) return INPUT;
if(dname.isEmpty()) return INPUT;
if(loc.isEmpty()) return INPUT;
DeptDao dao = new DeptDao();
dao.addOne(deptno, dname, loc);
return SUCCESS;
}
}
-------------- dept/add.jsp
<body>
<form action="insert.action" method="post">
<div>
<label>deptno</label>
<input name="deptno"/>
</div>
<div>
<label>dname</label>
<input name="dname"/>
</div>
<div>
<label>loc</label>
<input name="loc"/>
</div>
<div>
<button>btn</button>
</div>
</form>
</body>
------------ ListAction -> 리스트를 뷰에 넘겨줘야하기 때문에 변수 선언 및 getter 정의
package com.bit.action;
import java.util.List;
import com.bit.model.DeptDao;
import com.bit.model.DeptVo;
import com.opensymphony.xwork2.Action;
public class ListAction implements Action {
List<DeptVo> list;
public List<DeptVo> getList() {
return list;
}
@Override
public String execute() throws Exception {
DeptDao dao = new DeptDao();
list = dao.findAll();
return SUCCESS;
}
}
------------ dept/list.jsp -> Action에서 정의한 변수들을 jstl을 이용해서 받을 수 있다. 반드시 이름이 같아야함
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
...
<body>
<table>
<thead>
<tr>
<th>deptno</th>
<th>dname</th>
<th>loc</th>
</tr>
</thead>
<tbody>
<c:forEach items="${list }" var="bean">
<tr>
<c:url value="detail.action" var="detail">
<c:param name="id" value="${bean.id }"></c:param>
</c:url>
<td><a href="${detail}">${bean.deptno }</a></td>
<td><a href="${detail}">${bean.dname }</a></td>
<td><a href="${detail}">${bean.loc }</a></td>
</tr>
</c:forEach>
</tbody>
</table>
</body>
...
-------------- DeptAction - id는 받으니 setter, bean은 돌려주니 getter
package com.bit.action;
import org.apache.log4j.Logger;
import com.bit.model.DeptDao;
import com.bit.model.DeptVo;
import com.opensymphony.xwork2.Action;
public class DeptAction implements Action {
Logger log = Logger.getLogger(getClass().getCanonicalName());
String id;
private DeptVo bean;
public DeptVo getBean() {
return bean;
}
public void setId(String id) {
this.id = id;
}
@Override
public String execute() throws Exception {
log.debug(id);
DeptDao dao = new DeptDao();
bean = dao.findOne(id);
return SUCCESS;
}
}
---------------- dept/detail.jsp
<body>
<form action="update.action" method="post">
<input type="hidden" name="id" value="${bean.id }"/>
<div>
<label>deptno</label>
<input name="deptno" value="${bean.deptno }"/>
</div>
<div>
<label>dname</label>
<input name="dname" value="${bean.dname }"/>
</div>
<div>
<label>loc</label>
<input name="loc" value="${bean.loc }"/>
</div>
<div>
<button>btn</button>
</div>
</form>
</body>
--------------- UpdateAction
package com.bit.action;
import com.bit.model.DeptDao;
import com.opensymphony.xwork2.Action;
public class UpdateAction implements Action {
String id;
int deptno;
String dname;
String loc;
public void setId(String id) {
this.id = id;
}
public void setDeptno(int deptno) {
this.deptno = deptno;
}
public void setDname(String dname) {
this.dname = dname;
}
public void setLoc(String loc) {
this.loc = loc;
}
public String getId() {
return id;
}
public int getDeptno() {
return deptno;
}
public String getDname() {
return dname;
}
public String getLoc() {
return loc;
}
@Override
public String execute() throws Exception {
DeptDao dao = new DeptDao();
if(dao.updateOne(id, deptno, dname , loc)>0) {
return SUCCESS;
} else {
return INPUT;
}
}
}