100일 챌린지/빅데이터기반 인공지능 융합 서비스 개발자

Day38 - Maven으로 웹사이트 만들고 배포하기

ksyke 2024. 9. 13. 17:24

목차

    프로젝트 준비

    1) Maven 프로젝트 생성하기

    Eclipse의 Project Explorer 윈도우에서 마우스 우클릭 후 새로운 프로젝트 생성하기를 누른다.

     

    Maven Project의 Artifect Id maven-archetype-webapp을 선택하고 프로젝트와 패키지 이름을 설정한 뒤 finish를 누른다.

    2) 프로젝트 버전 올리기

    처음 생성했을시 버전이 맞지 않아 에러가 나는걸 볼 수 있다. 

    이를 해결하기 위해 프로젝트의 버전을 올리고 서버를 연결해준다.

    2-1) .setting의 xml 버전 올리기

    파일 탐색기에서 Maven 프로젝트를 열면 다음과 같이 폴더들이 생성된것을 확인할 수 있다. 

    .settings 폴더로 가 안의 .xml 파일의 코드를 아래와 같이 수정한다. 

    <?xml version="1.0" encoding="UTF-8"?>
    <faceted-project>
      <fixed facet="wst.jsdt.web"/>
      <installed facet="java" version="1.8"/>
      <installed facet="jst.web" version="3.1"/>
      <installed facet="wst.jsdt.web" version="1.0"/>
    </faceted-project>

    2-2) web.xml에서 web-app의 버전 맞추기

    프로젝트를 서버와 연결해주기 위해선 이클립스의 서버 폴더에 들어가 사용중인 서버의 web.xml 파일을 연다.

    여기서 1번과 17번 라인의 코드를 maven 프로젝트의 src>main>webapp>WEB-INF 안의 web.xml 파일에 붙여넣어 주면 된다. 

    <?xml version="1.0" encoding="UTF-8"?>
    
    <web-app version="3.1" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee                       http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd">

    2-3) pom.xml에 maven plugin 버전 맞추기

    Maven 프로젝트폴더 안에 위치한 pom.xml에 plugin 정보를 오버라이드한다.

        <plugins>
        	<plugin>
    	    	<groupId>org.apache.maven.plugins</groupId>
    	    	<artifactId>maven-compiler-plugin</artifactId>
    	    	<version>3.1</version>
    	    	<configuration>
    	    		<source>1.8</source>
    	    		<target>1.8</target>
    	    	</configuration>
        	</plugin>
        </plugins>

    3) 기본 라이브러리 추가하기

    java로 웹사이트를 만들기 위해 아래의 라이브러리를 추가/수정한다.

        <dependency>
          <groupId>junit</groupId>
          <artifactId>junit</artifactId>
          <version>4.13</version>
          <scope>test</scope>
        </dependency>
        <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
    	<dependency>
    	    <groupId>mysql</groupId>
    	    <artifactId>mysql-connector-java</artifactId>
    	    <version>8.0.33</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/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/log4j/log4j -->
    	<dependency>
    	    <groupId>log4j</groupId>
    	    <artifactId>log4j</artifactId>
    	    <version>1.2.17</version>
    	</dependency>
    	<!-- https://mvnrepository.com/artifact/javax.servlet/jstl -->
    	<dependency>
    	    <groupId>javax.servlet</groupId>
    	    <artifactId>jstl</artifactId>
    	    <version>1.2</version>
    	</dependency>

    4) Log4j 세팅하기

    Log4j를 사용하기 위해선 Maven 프로젝트의 src>main>resources 폴더에 log4j.properties 파일을 만든다.

    내용으로는 홈페이지에 나온 방법을 참고해 아래와 같이 작성한다.

    https://logging.apache.org/log4j/1.x/

    # log4j.properties
    log4j.rootLogger=WARN, A1
    log4j.appender.A1=org.apache.log4j.ConsoleAppender
    log4j.appender.A1.layout=org.apache.log4j.PatternLayout
    
    # Print the date in ISO 8601 format
    log4j.appender.A1.layout.ConversionPattern=%C %M [%p] - %m%n
    
    # Print only messages of level WARN or above in the package com.foo.
    log4j.logger.com.home.controller=WARN
    log4j.logger.com.emp=DEBUG

    백엔드

    5) Dto/Dao 만들기

    프로젝트의 src>main 폴더에 java 폴더를 만들어 그 안에 패키지를 생성하고 Dto/Dao 클래스를 만든다.

    아래는 Dto와 Dao의 샘플 코드이다:

    // Dto
    package com.my.model;
    
    import java.util.Date;
    
    import com.my.model.MyDto;
    
    public class MyDto {
    	private int empno,pay;
    	private String ename;
    	private Date hiredate;
    	public MyDto() {
    	}
    	public MyDto(int empno, int pay, String ename, Date hiredate) {
    		super();
    		this.empno = empno;
    		this.pay = pay;
    		this.ename = ename;
    		this.hiredate = hiredate;
    	}
    	public int getEmpno() {
    		return empno;
    	}
    	public void setEmpno(int empno) {
    		this.empno = empno;
    	}
    	public int getPay() {
    		return pay;
    	}
    	public void setPay(int pay) {
    		this.pay = pay;
    	}
    	public String getEname() {
    		return ename;
    	}
    	public void setEname(String ename) {
    		this.ename = ename;
    	}
    	public Date getHiredate() {
    		return hiredate;
    	}
    	public void setHiredate(Date hiredate) {
    		this.hiredate = hiredate;
    	}
    	@Override
    	public String toString() {
    		return "EmpDto [empno=" + empno + ", pay=" + pay + ", ename=" + ename + "]";
    	}
    	@Override
    	public int hashCode() {
    		final int prime = 31;
    		int result = 1;
    		result = prime * result + empno;
    		result = prime * result + ((ename == null) ? 0 : ename.hashCode());
    		result = prime * result + pay;
    		return result;
    	}
    	@Override
    	public boolean equals(Object obj) {
    		if (this == obj)
    			return true;
    		if (obj == null)
    			return false;
    		if (getClass() != obj.getClass())
    			return false;
    		EmpDto other = (EmpDto) obj;
    		if (empno != other.empno)
    			return false;
    		if (ename == null) {
    			if (other.ename != null)
    				return false;
    		} else if (!ename.equals(other.ename))
    			return false;
    		if (pay != other.pay)
    			return false;
    		return true;
    	}
    }

     

    // Dao
    package com.my.model;
    
    import java.sql.Connection;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.util.ArrayList;
    import java.util.List;
    
    import javax.sql.DataSource;
    
    import org.apache.log4j.Logger;
    
    import com.my.model.MyDto;
    import com.mysql.cj.jdbc.MysqlDataSource;
    
    public class MyDao {
    	Logger log=Logger.getLogger(getClass());
    	DataSource dataSource;
    	
    	public MyDao(){
    //		InitialContext ctxt=new InitialContext();
    //		dataSource=(DataSource) ctxt.lookup("java:/comp/env/jdbc/mysqlDB");
    		MysqlDataSource dataSource=new MysqlDataSource();
    		dataSource.setUrl("jdbc:mysql://localhost:3306/xe");
    		dataSource.setUser("scott");
    		dataSource.setPassword("tiger");
    		this.dataSource=dataSource;
    	}
    	
    	public List<MyDto> pullList() throws SQLException{
    		List<MyDto> list=new ArrayList<MyDto>();
    		String sql="select * from emp38 order by empno";
    		try(
    				Connection conn=dataSource.getConnection();
    				PreparedStatement pstmt=conn.prepareStatement(sql);
    				ResultSet rs=pstmt.executeQuery();
    				){
    			while(rs.next()) {
    				list.add(new EmpDto(
    						rs.getInt("empno"),rs.getInt("pay"),
    						rs.getString("ename"),rs.getDate("hiredate")
    						));
    			}
    			log.debug(list.toString());
    			return list;
    		}
    		
    	}
    	public MyDto getList(int pk) throws SQLException {
    		MyDto bean=new MyDto();
    		String sql="select * from emp38 where empno=?";
    		try(
    				Connection conn=dataSource.getConnection();
    				PreparedStatement pstmt=conn.prepareStatement(sql);
    				){
    			pstmt.setInt(1, pk);
    			ResultSet rs=pstmt.executeQuery();
    			if(rs.next())
    				bean=new EmpDto(
    						rs.getInt("empno"),rs.getInt("pay"),
    						rs.getString("ename"),rs.getDate("hiredate")
    						);
    			rs.close();
    		}
    		return bean;
    	}
    	public int pushList(MyDto bean) throws SQLException {
    		String sql="insert into emp38 (ename,pay,hiredate) values (?,?,now())";
    		try(
    				Connection conn=dataSource.getConnection();
    				PreparedStatement pstmt=conn.prepareStatement(sql);
    				){
    			pstmt.setString(1, bean.getEname());
    			pstmt.setInt(2, bean.getPay());
    			return pstmt.executeUpdate();
    		}
    	}
    	
    	public int editList(MyDto bean) throws SQLException {
    		String sql="Update emp38 set ename=?,pay=? where empno=?";
    		try(
    				Connection conn=dataSource.getConnection();
    				PreparedStatement pstmt=conn.prepareStatement(sql);
    				){
    			pstmt.setString(1, bean.getEname());
    			pstmt.setInt(2, bean.getPay());
    			pstmt.setInt(2, bean.getEmpno());
    			return pstmt.executeUpdate();
    		}
    	}
    	public int removeList(int pk) throws SQLException {
    		String sql="delete from emp38 where empno=?";
    		try(
    				Connection conn=dataSource.getConnection();
    				PreparedStatement pstmt=conn.prepareStatement(sql);
    				){
    			pstmt.setInt(1, pk);
    			return pstmt.executeUpdate();
    		}
    	}
    }

    => project compliance와 JRE를 바꾸라는 에러가 나올떄는 프로젝트 속성에 들어가 아래와 같이 바꾸면 된다.

    (1.7 버전 이상으로 바꾼다.)

    6) Dao 테스트하기

    Maven의 test를 수행하기 위해선 작성한 Dao 파일에서 우클릭후 새로운 파일 만들기에 들어간다.

    package com.emp.model;
    
    import static org.junit.Assert.*;
    
    import java.sql.SQLException;
    import java.util.List;
    
    import org.junit.Test;
    import org.junit.runner.OrderWith;
    import org.junit.runner.manipulation.Alphanumeric;
    
    import junit.framework.Assert;
    
    @OrderWith(Alphanumeric.class)
    public class EmpDaoTest {
    	EmpDto target=new EmpDto(1,1111,"tester1",null);
    
    	@Test
    	public void testPullList() throws SQLException {
    		EmpDao dao=new EmpDao();
    		List<EmpDto> list=dao.pullList();
    		Assert.assertNotNull(list);
    		Assert.assertNotSame(0,list.size());
    	}
    
    	@Test
    	public void testGetList() throws SQLException {
    //		EmpDto target=new EmpDto(1,1111,"tester1",null);
    		
    		EmpDao dao=new EmpDao();
    		EmpDto result=dao.getList(target.getEmpno());
    		Assert.assertNotNull(result);
    		Assert.assertEquals(target,result);
    	}
    	
    	@Test
    	public void testPushList() throws SQLException {
    //		EmpDto target=new EmpDto(6,6666,"test6",null);
    		
    		EmpDao dao=new EmpDao();
    		int result=dao.pushList(target);
    		Assert.assertSame(1, result);
    	}
    	
    	@Test
    	public void testEditList() throws SQLException {
    		
    		EmpDao dao=new EmpDao();
    		int result=dao.editList(target);
    		Assert.assertSame(1, result);
    	}
    	
    	@Test
    	public void testRemoveList() throws SQLException {
    		
    		EmpDao dao=new EmpDao();
    		int result=dao.removeList(target.getEmpno());
    		Assert.assertSame(1, result);
    	}
    }

     

    프론트엔드

    7) index,intro와 template 파일들 만들기

    // index.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>
    <%@include file="template/head.jspf" %>
    </head>
    <body>
    <%@include file="template/menu.jspf" %>
    
    <div id="carousel-example-generic" class="carousel slide" data-ride="carousel">
      <!-- Indicators -->
      <ol class="carousel-indicators">
        <li data-target="#carousel-example-generic" data-slide-to="0" class="active"></li>
        <li data-target="#carousel-example-generic" data-slide-to="1"></li>
        <li data-target="#carousel-example-generic" data-slide-to="2"></li>
      </ol>
    
      <!-- Wrapper for slides -->
      <div class="carousel-inner" role="listbox">
        <div class="item active">
          <img src="imgs/img1.jpg" alt="...">
          <div class="carousel-caption">
          </div>
        </div>
        <div class="item">
          <img src="imgs/img2.jpg" alt="...">
          <div class="carousel-caption">
          </div>
        </div>
        <div class="item">
          <img src="imgs/img3.jpg" alt="...">
          <div class="carousel-caption">
          </div>
        </div>
      </div>
    
      <!-- Controls -->
      <a class="left carousel-control" href="#carousel-example-generic" role="button" data-slide="prev">
        <span class="glyphicon glyphicon-chevron-left" aria-hidden="true"></span>
        <span class="sr-only">Previous</span>
      </a>
      <a class="right carousel-control" href="#carousel-example-generic" role="button" data-slide="next">
        <span class="glyphicon glyphicon-chevron-right" aria-hidden="true"></span>
        <span class="sr-only">Next</span>
      </a>
    </div>
    
    <%@include file="template/footer.jspf" %>
    </div>
    </body>
    </html>
    // intro.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>
    <%@include file="template/head.jspf" %>
    </head>
    <body>
    <%@include file="template/menu.jspf" %>
    
    <div class="text-center">
    	<img src="https://www.inje.ac.kr/kor/assets/images/sub/gimhae-campus-1.jpg" class="img-thumbnails"/>
    </div>
    
    <%@include file="template/footer.jspf" %>
    </div>
    </body>
    </html>
    // footer.jspf
    
    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    		<!-- content end -->
    		</div>
    	</div>
    	<div id="footer" class="row">
    		<div class="col-md-12 text-center">
    				<address>
    					<p>김해캠퍼스 (50834) 경남 김해시 인제로 197</p>
    					<p>Copyright &copy; INJE University. All rights reserved.</p>
    				</address>
    		</div>
    	</div>
    // head.jspf
    
    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <link rel="stylesheet" type="text/css" href="${pageContext.request.contextPath }/css/bootstrap.min.css">
    <script type="text/javascript" src="${pageContext.request.contextPath }/js/jquery-1.12.4.min.js"></script>
    <script type="text/javascript" src="${pageContext.request.contextPath }/js/bootstrap.min.js"></script>
    <style type="text/css">
    	body>nav img{height: 100%;}
    </style>
    // menu.jspf
    
    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <nav class="navbar navbar-default">
      <div class="container-fluid">
        <div class="navbar-header">
          <a class="navbar-brand" href="${pageContext.request.contextPath }/">
            <img alt="Brand" src="${pageContext.request.contextPath }/imgs/logo.png">
          </a>
        </div>
        <ul class="nav navbar-nav">
        	<li><a href="${pageContext.request.contextPath }/">home</a></li>
        	<li><a href="${pageContext.request.contextPath }/intro.do">intro</a></li>
        	<li><a href="${pageContext.request.contextPath }/emp/">emp</a></li>
        	<li><a href="${pageContext.request.contextPath }/login">login</a></li>
        </ul>
      </div>
    </nav>
    <div class="container">
    	<div id="content" class="row">
    		<div class="col-md-12">
    		<!-- content begin -->

    8) Controller로 index와 intro 연결하기 

    // IndexController.java
    
    @WebServlet("/index.do")
    public class indexController extends HttpServlet{
    	Logger log=Logger.getLogger(this.getClass());
    	
    	@Override
    	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    		log.debug("call index controller");
    		RequestDispatcher rd=req.getRequestDispatcher("/index.jsp");
    		System.out.println("index: "+req.hashCode());
    		rd.forward(req, resp);
    				
    	}
    }
    // IntroController.java
    
    @WebServlet("/intro.do")
    public class IntroController extends HttpServlet{
    	@Override
    	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    		RequestDispatcher rd=req.getRequestDispatcher("/intro.jsp");
    		rd.forward(req, resp);
    	}
    }

    9) 추가, 수정, 삭제 수행하기

    // AddController.java
    
    @WebServlet("/emp/add.do")
    public class AddController extends HttpServlet{
    	@Override
    	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    		req.setAttribute("ename", req.getParameter("ename"));
    		req.setAttribute("pay", req.getParameter("pay"));
    		
    		RequestDispatcher rd=req.getRequestDispatcher("/emp/add.jsp");
    		rd.forward(req, resp);
    	}
    	@Override
    	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    		String ename=req.getParameter("ename");
    		if(ename==null||ename.trim().isEmpty()) {
    			req.setAttribute("errEname", "이름을 입력하세요");
    			doGet(req, resp);
    			return;
    		}
    		int pay=-1;
    		String param=req.getParameter("pay");
    		if(param==null||param.trim().isEmpty()) {
    			req.setAttribute("errPay", "금액을 입력하세요");
    			doGet(req, resp);
    			return;
    		}
    		try{
    			pay=Integer.parseInt(param);			
    		}catch(Exception e){
    			if(ename==null||ename.trim().isEmpty()) {
    				req.setAttribute("errPay", "금액으로 숫자를 입력하세요");
    				doGet(req, resp);
    				return;
    			}
    			
    		}
    		
    		EmpDto bean=new EmpDto(0,pay,ename,null);
    		
    		EmpDao dao=new EmpDao();
    		try {
    			dao.pushList(bean);
    		} catch (SQLException e) {
    			e.printStackTrace();
    		}
    		resp.sendRedirect("./?success=true");
    	}
    }
    // DeleteController.java
    
    @WebServlet("/emp/delete.do")
    public class DeleteController extends HttpServlet{
    	@Override
    	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    		int empno=Integer.parseInt(req.getParameter("empno"));
    		EmpDao dao=new EmpDao();
    		try {
    			dao.removeList(empno);
    		} catch (SQLException e) {
    			e.printStackTrace();
    		}
    	}
    }
    // DetailController.java
    
    @WebServlet("/emp/detail.do")
    public class DetailController extends HttpServlet{
    	@Override
    	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    		int empno=Integer.parseInt(req.getParameter("empno"));
    		EmpDao dao=new EmpDao();
    		try {
    			req.setAttribute("bean", dao.getList(empno));
    		} catch (SQLException e) {
    			e.printStackTrace();
    		}
    		RequestDispatcher rd=req.getRequestDispatcher("detail.jsp");
    		rd.forward(req, resp);
    	}
    }
    // EditController.java
    
    @WebServlet("/emp/edit.do")
    public class EditController extends HttpServlet {
    
    	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    		int empno=Integer.parseInt(req.getParameter("empno"));
    		EmpDao dao=new EmpDao();
    		try {
    			req.setAttribute("bean", dao.getList(empno));
    		} catch (SQLException e) {
    			e.printStackTrace();
    		}
    		RequestDispatcher rd=req.getRequestDispatcher("edit.jsp");
    		rd.forward(req, resp);
    	}
    
    
    	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    		EmpDto bean=new EmpDto(
    				Integer.parseInt(req.getParameter("empno")),
    				Integer.parseInt(req.getParameter("pay")),req.getParameter("ename"),null
    				);
    		EmpDao dao=new EmpDao();
    		try {
    			dao.editList(bean);
    		} catch (SQLException e) {
    			e.printStackTrace();
    		}
    		resp.sendRedirect("./?success=true");
    	}
    }
    // ListController.java
    
    @WebServlet("/emp/")
    public class ListController extends HttpServlet{
    	@Override
    	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    		EmpDao dao=new EmpDao();
    		try {
    			req.setAttribute("alist", dao.pullList());
    		} catch (SQLException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    		
    		RequestDispatcher rd=req.getRequestDispatcher("/emp/list.jsp");
    		rd.forward(req, resp);
    	}
    }

     

    배포하기

    mysql 내보내기

    sql 파일 코드 정리하기 (replace all)

    vagrant 파일 만들기

     

    Vagrantfile을 다음과 같이 수정한다.

    Vagrant.configure("2") do |config|
    
    config.vm.box = "ubuntu/focal64"
    
    config.vm.network "forwarded_port", guest: 8080, host: 7070
    config.vm.network "forwarded_port", guest: 3306, host: 33306
    
    config.vm.provision "shell", inline: <<-SHELL
        	apt update -y
     	SHELL
    end

    Vagrant up을 통해 실행한다.

     

    Vagrant 접속하기

     

    JDK 받기

     

    tomcat 받기

     

    https://archive.apache.org/dist/tomcat/tomcat-8/v8.5.100/bin/

     

    tar.gz 파일을 받아서