본문 바로가기

회고록(TIL&WIL)

TIL 2023.02.23 Java Web 12 (Struts frame work example, (feat.MongoDB))

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;
		}
	}
}