728x90
300x250

[Spring-Framework] 8. Spring MVC 웹 프로젝트 생성하기, UTF-8 문제(1)


Spring MVC 프로젝트를 이해하기 위해서는 몇 가지 가벼운 지식이 요구된다.


* 웹 서버: Apache Tomcat 9

  - JSP/Servlet 기초 이해력

* 라이브러리: Maven(메이븐)

* Spring 프레임워크없이, JSP/Servlet 기반으로 MVC2를 직접 구현할 수 있는 수준


jQuery, Ajax 등 기반으로 만들어진 시중 책들이 굉장히 많은데 이건 별도의 영역이다.

같이 취급해서는 안 된다고 본다.


엄밀히 보면, jQuery나 Ajax는 javascript 영역이다.


시중 책들이 워낙 어렵게 소개되고 있어서 간단하고 알기 쉽게 소개하려고 한다.


운영체제: Microsoft Windows 10

개발환경: Spring Tool-Suite 4-4.7.2. Release (Eclipse 기반 개발)

웹 서버: apache-tomcat-9.0.37-windows-x64




1. Eclipse Marketplace에서 "Spring Tools 3 Add-On for Spring Tools 4 3.9.14. RELEASE" 설치하기

(부재: Spring Legacy Project 기능 추가하기)


Spring MVC Project를 쉽고 빠르게 사용하려면, Spring Legacy Project 기능을 설치해야 한다.

현재 최신 STS 4-4.7.2를 보면, Spring Boot나 Spring Starter 등 최신 기능을 주력으로 하는 것 같다.



그림 1. Eclipse의 Help 메뉴


"Help->Eclipse Marketplace"를 들어간다.



그림 2. STS 검색하기


sts를 검색한다.

"Spring Tools 3 Add-On for Spring Tools 4 3.9.14. RELEASE"를 Install한다.


(중략함. 설치 과정 자체가 쉬움.)



2. 새 프로젝트 만들기


File-> New-> Others를 누른다.



그림 3. Project 생성하기


Spring 폴더의 Spring Legacy Project를 선택한다.

Next를 누른다.



그림 4. Project 생성하기


Spring MVC Project를 선택한 후 Next를 누른다.




그림 5. Project 생성하기


프로젝트 상위 패키지명을 입력한 후 Finish를 누른다.


의외로 쉽게 MVC 프로젝트가 생성되는 것을 확인할 수 있다.

참고로 com.springMVC1.web으로 작성하면, 태스트 배포 주소는 "홈페이지주소:8080/web"이 된다.



3. 신규 프로젝트 구경하기


시작이 반이다.

Spring MVC에 겁먹지 말고, 프로젝트를 구경해보기 바란다.



그림 6. Controller 모습



그림 7. View 영역의 WEB-INF/views/home.jsp 모습





그림 8. servlet-context.xml


과거에는 힘들게 servlet-context.xml을 작성하였지만, 지금은 힘들게 작성할 필요는 없다.


<?xml version="1.0" encoding="UTF-8"?>

<beans:beans xmlns="http://www.springframework.org/schema/mvc"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:beans="http://www.springframework.org/schema/beans"

xmlns:context="http://www.springframework.org/schema/context"

xsi:schemaLocation="http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd

http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd

http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">


<!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->

<!-- Enables the Spring MVC @Controller programming model -->

<annotation-driven />


<!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->

<resources mapping="/resources/**" location="/resources/" />


<!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory -->

<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">

<beans:property name="prefix" value="/WEB-INF/views/" />

<beans:property name="suffix" value=".jsp" />

</beans:bean>

<context:component-scan base-package="com.springMVC1.web" />

</beans:beans>


* 소스코드 원문: servlet-context.xml





그림 9. root-context.xml





그림 10. servlet-context.xml


web.xml 파일이다. 

servlet 작성하면서, 작업해본 경험이 있을 수 있다. 동일하게 사용할 수 있다.

참고로 maven으로 웹 프로젝트를 개설하면, 자동으로 생성된다.



그림 11. pom.xml


Spring Framework는 maven 프로젝트의 핵심인 pom.xml 기능을 그대로 사용할 수 있다.




그림 12. Hello World - 초기 접속


Spring MVC를 처음으로 구성하고 접속해보면, 그림 12의 화면을 볼 수 있다.



4. 한글 문제 해결하기(UTF-8 문제)


한글 문제 해결에 관한 이슈이다.

web.xml 파일을 수정하여 해결할 수 있다.



그림 13. web.xml에서 한글 문제 해결하기


<?xml version="1.0" encoding="UTF-8"?>

<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://java.sun.com/xml/ns/javaee https://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">


<!-- The definition of the Root Spring Container shared by all Servlets and Filters -->

<context-param>

<param-name>contextConfigLocation</param-name>

<param-value>/WEB-INF/spring/root-context.xml</param-value>

</context-param>

<!-- Creates the Spring Container shared by all Servlets and Filters -->

<listener>

<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>

</listener>


<!-- Processes application requests -->

<servlet>

<servlet-name>appServlet</servlet-name>

<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

<init-param>

<param-name>contextConfigLocation</param-name>

<param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>

</init-param>

<load-on-startup>1</load-on-startup>

</servlet>

<servlet-mapping>

<servlet-name>appServlet</servlet-name>

<url-pattern>/</url-pattern>

</servlet-mapping>


<!-- UTF-8 -->

<filter>

<filter-name>encodingFilter</filter-name>

<filter-class>

org.springframework.web.filter.CharacterEncodingFilter</filter-class>

<init-param>

<param-name>encoding</param-name>

<param-value>UTF-8</param-value>

</init-param> <init-param>

<param-name>forceEncoding</param-name>

<param-value>true</param-value>

</init-param>

</filter>

<filter-mapping>

<filter-name>encodingFilter</filter-name>

<url-pattern>/*</url-pattern>

</filter-mapping>​



</web-app>



* 파일명: web.xml


[첨부(Attachments)]

web.zip



그림 14. 한글 문제가 해결된 모습




5. Controller - 입문하기


Spring MVC Controller를 활용하여 쉽고 간단하게 작성하는 방법을 소개하겠다.



그림 15. 클래스 만들기(Controller로 개조 예정)


패키지에서 오른쪽 버튼을 클릭한다.

New->Class를 클릭한다.

"BoardController"를 하나 만들어준다.



그림 16. 클래스 만들기(Controller) - HomeController.java


HomeController의 내용을 신규 생성한 "BoardController.java" 파일을 열어서 복사, 붙여넣기를 해준다.




그림 17. 클래스 만들기(Controller) - BoardController.java


편집을 완료한 BoardController의 모습이다.


정정: 

(1) HomeController.class -> BoardController.class로 변경 (탈자)
(2) Welcome home: The ..... -> Welcome board: The...로 변경





그림 18. lisp.jsp 생성하기 -> src/main/webapp/WEB-INF/views/board/list.jsp


views내에 board폴더를 만든다.

board폴더 내에 list.jsp 파일을 만든다.



그림 19. 서버를 로드했을 때 모습 - STS 4


Spring-Framework MVC를 웹서버에서 실행시켜보면, 매우 간단한 구조로 동작하는 모습을 살펴볼 수 있다.

web.xml 파일 수정도 안 했으며, Controller하고 list.jsp 파일만 만들었는데 작동하는 모습을 보면, 프레임워크가 좋긴 좋다는 것을 느낄 수 있다.



그림 20. board/list 호출한 결과



* 맺음글(Conclusion)


매우 간단한 형태로 Spring MVC Project를 구성하는 방법에 대해서 소개하였다.


반응형
728x90
300x250

[JSP] 11. WAR 배포하기 - 웹 사이트 올리기


개발을 하였으면, 사용자가 접속할 수 있도록 배포를 해주어야 한다.

기존의 Apache Web Server나 Microsoft IIS 서버의 경우에는 프로젝트 그대로 올려주면 되는데, JSP는 두 가지 방법을 지원하고 있다.


WAR 형태 파일로 압축하여 서버에 올리는 방법이 있다.




1. 리눅스, 윈도우 환경에서 "Eclipse IDE(Spring Tool-Suite 4)"로 개발했을 때


1. 배포할 spring 프로젝트를 우클릭하여 export를 선택한다.

2. export 메뉴가 나오면 Web 카테고리 안의 WAR file을 선택하고 Next를 누른다.

3. Destination에 war파일을 저장할 위치를 지정해준다. (tomcat이 설치된 폴더의 webapps 폴더로 지정해주면 편리하다)


4. Export source files와 Overwrite existing file 항목을 체크해준다.

5. 마지막으로 finish를 누르면 war파일이 생성된다.



그림 1. File 메뉴 모습


File -> Export를 클릭한다.



그림 2. Eclipse의 Export 작업


"Web 폴더"의 "War file"을 선택한 후, "Next"를 누른다.



그림 3. Eclipse의 Export 작업


작업한 웹 프로젝트를 선택하고 "Browse"를 누른다.



그림 4. Eclipse의 Export 작업


배포할 파일의 내보낼 위치를 선택한다.

저장(S)를 누른다.



그림 5. Eclipse의 Export 작업


"Finish"를 누른다.




2. Windows(윈도우) 환경에서의 아파치 서버에 배포하기


{tomcat 설치 경로}\webapps 폴더에 생성한 war 파일을 복사한다.

{tomcat 설치 경로}/bin 으로 들어가서 startup.bat을 실행하면 tomcat이 시작된다.


tomcat을 시작하면, 자동으로 프로젝트 이름과 동일한 폴더가 생성되면서 war 파일로 묶여있던 패키지가 풀린다.


웹브라우저에서 localhost:8080이나 아이피주소:8080로 해당 프로젝트에 접속하면 된다. 

프로젝트명이 test인 경우 http://localhost:8080/test 로 접속하면 spring 프로젝트에 접속된다.




그림 6. 배포 폴더에 war 파일 모습


webapps폴더에 war 파일을 붙여넣는다.



그림 7. bin의 startup.bat(Apache Tomcat 9)


bin폴더에 있는 startup.bat을 실행하여 웹 서버를 실행해준다.



그림 8. Apache Tomcat 9 - 서버 가동중




그림 9. 웹 브라우저에서 확인하기


웹 브라우저에서 접속하여 확인하면, 동작하는 것을 알 수 있다.



3. Linux(Ubuntu) 환경에서 배포


마찬가지로 tomcat이 설치된 디렉토리의 webapps 디렉토리에 war 파일을 복사하고 tomcat을 재시작 해주면 된다.

(/var/lib/tomcat{버전}/webapps/ 디렉토리에 복사한다.)


tomcat을 재실행한다.

Windows와 동일하게 tomcat을 시작하면 자동으로 프로젝트 이름과 동일한 폴더가 생성되면서 war 파일로 묶여있던 패키지가 풀린다.


$ sudo service tomcat{버전} restart


웹브라우저에서 해당 서버의 아이피주소:8080로 접속할 수 있다.


운영체제: 리눅스 우분투(Ubuntu-20 Desktop 64bit)


[명령어 요약]

user@localhost :sudo -i

root#apt update

(처음 우분투 설치하면, 업데이트 하라고 GUI화면에 올라옴. 재부팅을 몇 번 해보고 나서 작업하는 것을 권장함.)

root#apt install tomcat9

root#service tomcat9 start


(war 파일 경로 찾기)

#mv {파일명}.war /var/lib/tomcat9/webapps

(수동 컴파일 버전은 수동 설치 경로로 할 것)


(잠시 기다리고 나서 1분 이내)

* 파이어폭스 열어서 접속할 것




그림 10. 우분투(리눅스)에서 톰캣9 - 설치하기




그림 11. 우분투(리눅스)에서 ifconfig 명령어 집합(net-tools) 설치 및 톰캣 실행하기 - 리눅스




그림 12. 파이어폭스에서 localhost 구경하기 - 리눅스





그림 13. 톰캣 설치 경로 찾기 - 리눅스






그림 14. war 파일 복사 및 경로 이동하기 - 리눅스





그림 15. 루트에 배포된 war 파일 모습 - 리눅스






4. 루트 경로에 배포하기


* ROOT에 war파일 배포할 경우


1. 프로젝트 war파일 생성


- Eclipse에서 프로젝트 우클릭 -> Export - Web - WAR file 선택 -> Next버튼 클릭


- Destination에 war파일 생성될 위치 지정하고, 파일명은 반드시 'ROOT.war'로 입력한 후 Finish버튼 클릭


* 파일명을 꼭 ROOT로 해야하는 것은 아니지만 ROOT가 아닌 다른 걸로 하려면 별도의 설정이 필요함


2. Tomcat 폴더/webapps/ROOT 폴더의 이름을 변경


* Tomcat을 설치하면 위 경로에 ROOT폴더가 있는데 이 폴더가 존재하면 ROOT.war가 압축해제되지 않음


3. Tomcat 폴더/webapps 폴더에 생성된 ROOT.war파일 이동



그림 16. root.war 파일 설치하기


초기에 ROOT폴더는 이름을 변경해서 둔다.



그림 17. 서버 실행하기


bin폴더에 들어가서 startup.bat을 실행한다.


그림 18. 루트 홈페이지 모습


"서버주소:포트"로 홈페이지에 접속하면, 루트 홈페이지로 풀린 프로젝트를 살펴볼 수 있다.



그림 19. 서버 동작 후, 프로젝트 컴파일된 모습


서버 동작 시키고 나서 webapps 폴더를 관찰해보면, ROOT 폴더가 새로 생겨있는 것을 살펴 볼 수 있다.



* 참고자료(References)


1. Spring 프로젝트 배포하기(tomcat 이용), https://attackyourheart.tistory.com/50, Accessed by 2020-09-22, Last Modified 2015-01-20.

2. Tomcat에 war파일 배포하는 방법, https://its-easy.tistory.com/4, Accessed by 2020-09-22, Last Modified 2018-02-13.

반응형
728x90
300x250

[Spring-Framework] 7. Maven, Hibernate 5.4, Servlet, MySQL 8 연동(CRUD) - (2)


2부 글을 이어서 작성하고자 한다.


[1부] [Spring-Framework] 6. Maven, Hibernate 5.4, Servlet, MySQL 8 연동(CRUD) - (1) , 2020-09-21 14:36
https://yyman.tistory.com/1404



7. 서블렛 만들기


패키지: com.hibernateMaven.web.controller

서블릿명(클래스명):

1. SampleServlet

2. StudentServlet


두 개를 만들어준다.


세부적인 내용은 지금하진 않는다.



8. Model 정의(Entity)


OR-M(Object Relational-Mapping)의 특징을 가지는 Hibernate에서 사용할 수 있도록 DTO 또는 VO(Value Object)를 정의해줘야 한다.


패키지: com.hibernateMaven.web.model

클래스명: 

1. Emptable

2. Student


클래스에 Persistence를 잘 정의해줘야 한다.

@Entity, @Table 등에 대한 Mapping을 클래스에서도 할 수 있다.


package com.hibernateMaven.web.model;


import java.sql.Date;


import javax.persistence.*;


@Entity

@Table(name = "emptable")

public class Emptable

{


@Id

@GeneratedValue(strategy = GenerationType.AUTO)

private int empno;


@Column(name="name")

private String name;


@Column(name="address")

private String address;


@Column(name="createdate")

private Date createdate;

public int getEmpno() {

return empno;

}

public void setEmpno(int empno) {

this.empno = empno;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public String getAddress() {

return address;

}

public void setAddress(String address) {

this.address = address;

}

public Date getCreatedate() {

return createdate;

}

public void setCreatedate(Date createdate) {

this.createdate = createdate;

}

}


코드 1. Emptable.java


package com.hibernateMaven.web.model;


import java.sql.Date;


import javax.persistence.Column;

import javax.persistence.Entity;

import javax.persistence.GeneratedValue;

import javax.persistence.GenerationType;

import javax.persistence.Id;

import javax.persistence.Table;


@Entity

@Table(name = "student")

public class Student {


@Id

@GeneratedValue(strategy = GenerationType.AUTO)

private int studentno;


@Column(name="name")

private String name;


@Column(name="address")

private String address;


@Column(name="createdate")

private Date createdate;

public int getStudentno() {

return studentno;

}

public void setStudentno(int studentno) {

this.studentno = studentno;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public String getAddress() {

return address;

}

public void setAddress(String address) {

this.address = address;

}

public Date getCreatedate() {

return createdate;

}

public void setCreatedate(Date createdate) {

this.createdate = createdate;

}

}


코드 2. Student.java


이전의 Hibernate 개발을 보면, xml으로 hibernate.cfg.xml에 resource-mapping을 시켜주었다.

물론 현재 XML-Mapping 방법을 사용해도 무방하나, 굳이 번거롭게 2개 이상 수정 작업을 만들어서 일을 크게 만들 필요는 없다고 본다.


<?xml version = "1.0" encoding = "utf-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <class name = "com.hibernateMaven2.web.model.Emptable" table = "emptable"> <meta attribute = "class-description"> This class contains the employee detail. </meta> <id name = "empno" type = "int" column = "empno"> <generator class="native"/> </id> <property name = "name" column = "name" type = "string"/> <property name = "address" column = "address" type = "string"/> <property name = "createdate" column = "createdate" type = "date"/> </class>  </hibernate-mapping>

예1) Emptable.hbm.xml


[첨부(Attachments)]

Emptable.hbm-xml.zip


Xml-Mapping 관련 파일이 필요한 이유는 JBoss-Hibernate에서 현재 생성이 되지 않고 있다.
(JBoss의 업데이트 등의 문제) - [2020-09-21 기준]


충분히 태스트를 해보았다. JBoss 기능에도 클래스로 맵핑하는 기능이 있다.



그림 14. Mapping 추가 기능 - STS 4의 JBoss(Hibernate 기능)





9. Hibernate.cfg.xml 파일 수정하기


그림 14의 Add-Mapping 작업을 해줘야 한다.

1부의 그림 9에 있는 첨부 파일의 내용이다.


<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN"

                                         "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">

<hibernate-configuration>

 <session-factory name="">

  <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>

  <property name="hibernate.connection.username">사용자계정</property>

  <property name="hibernate.connection.password">비밀번호</property>

  <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/web?serverTimezone=UTC&amp;characterEncoding=utf8</property>

  <property name="hibernate.dialect">org.hibernate.dialect.MySQL8Dialect</property>

  <property name="hibernate.show_sql">true</property>

  <property name="hibernate.hbm2ddl.auto">update</property>

  <property name="hibernate.default_entity_mode">pojo</property>

  <property name="hibernate.current_session_context_class">thread</property>

  

  <mapping class="com.hibernateMaven.web.model.Emptable"/>    <!-- empTable 클래스 맵핑-->

  <mapping class="com.hibernateMaven.web.model.Student"/>

 </session-factory>

</hibernate-configuration>


코드 3) 클래스 맵핑 방법


[첨부(Attachments)]

hibernate.cfg-class-mapping.zip



예1의 형태로도 맵핑을 시도해볼 수 있다.


<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN"

                                         "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">

<hibernate-configuration>

 <session-factory name="">

  <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>

  <property name="hibernate.connection.username">사용자명</property>

  <property name="hibernate.connection.password">비밀번호</property>

  <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/web?serverTimezone=UTC&amp;characterEncoding=utf8</property>

  <property name="hibernate.dialect">org.hibernate.dialect.MySQL8Dialect</property>

  <property name="hibernate.show_sql">true</property>

  <property name="hibernate.hbm2ddl.auto">update</property>

  <property name="hibernate.default_entity_mode">pojo</property>

  <property name="hibernate.current_session_context_class">thread</property>

  <mapping class="com.hibernateMaven.web.model.Student"/>


  <!-- XML Resource 자원으로 맵핑 -->

  <mapping resource="com/hibernateMaven/web/model/Emptable.hbm.xml"/>

 </session-factory>

</hibernate-configuration>


코드 4) 클래스, XML 맵핑 방법


[첨부(Attachments)]

hibernate.cfg-xml-mapping.zip



코드 3과 코드 4를 언급한 것은 시중 시판되는 책이나 검색 자료 등에서 언급되고 있는 소스코드의 고정관념을 깨라는 이야기이다.

자유롭게 해도 된다.


 

 

그림 15) 코드 3방식의 클래스 맵핑으로만 구성

그림 16. 코드 4방식을 채택하였을 때의 구조
         (XML-Mapping이라고 흔히 정의함)



10. HibernateUtil.java (이해보다는 복사, 붙여넣기할 것)


HibernateUtil이라는 클래스에 정의된 원형들은 DB의 연결과 종료에 해당되는 부분들이다.

연결 한번 하려고 이걸 다 외우고 작성할 수 없으니 Copy해서 사용하는 걸 추천한다.


package com.hibernateMaven.web.factory;


import org.hibernate.SessionFactory;

import org.hibernate.boot.Metadata;

import org.hibernate.boot.MetadataSources;

import org.hibernate.boot.registry.StandardServiceRegistry;

import org.hibernate.boot.registry.StandardServiceRegistryBuilder;



public class HibernateUtil

{


    private static StandardServiceRegistry registry;

    private static SessionFactory sessionFactory;


    public static SessionFactory getSessionFactory() {

        if (sessionFactory == null) {

            try {

                // Create registry

                registry = new StandardServiceRegistryBuilder().configure().build();


                // Create MetadataSources

                MetadataSources sources = new MetadataSources(registry);


                // Create Metadata

                Metadata metadata = sources.getMetadataBuilder().build();


                // Create SessionFactory

                sessionFactory = metadata.getSessionFactoryBuilder().build();

                

            } catch (Exception e) {

                e.printStackTrace();

                if (registry != null) {

                    StandardServiceRegistryBuilder.destroy(registry);

                }

            }

        }

        return sessionFactory;

    }


    public static void shutdown() {

        if (registry != null) {

            StandardServiceRegistryBuilder.destroy(registry);

        }

    }


}


코드 5) HibernateUtil.java 코드


[첨부(Attachments)]

HibernateUtil.zip



11. Interface 설계


이 글에서는 select, select where cause, insert, update, delete를 위주의 기능을 확인할 수 있도록 작성되었다.


package com.hibernateMaven.web.service;


import java.util.List;


import com.hibernateMaven.web.model.Emptable;


public interface IEmpTable {


public List<Emptable> allList(); // Select * FROM empTable

public Emptable getList(Integer num); // Select * from emptable where empno = ?

public void save(Emptable emptable); // insert into emptable

public int update(Emptable emptable); // update emptable set cause where emp = ? 

public int delete(Integer num); // delete from emptable where empno = ?

public Emptable searchName(Integer num, String name); // 두 가지 조건 동시 만족 조회

}



코드 6) IEmpTable.java (인터페이스 파일)


[첨부(Attachments)]

IEmpTable.zip



package com.hibernateMaven.web.service;


import java.util.List;


import com.hibernateMaven.web.model.Student;


public interface IStudent {


public List<Student> allList(); // Select * FROM student

public Student getList(Integer num); // Select * from student where studentno = ?

}



코드 7) IStudent.java (인터페이스 파일)


[첨부(Attachments)]

IStudent.zip




12. Class 구현


IEmpTable을 바탕으로 EmpTableService.java, StudentService.java 파일을 작성해보았다.


package com.hibernateMaven.web.service;


import java.util.List;


import org.hibernate.query.*;

import org.hibernate.Session;

import org.hibernate.Transaction;


import com.hibernateMaven.web.factory.HibernateUtil;

import com.hibernateMaven.web.model.Emptable;


public class EmpTableService implements IEmpTable {


@Override

public List<Emptable> allList() {


Transaction transaction = null;

List<Emptable> list = null;

try (Session session = HibernateUtil.getSessionFactory().openSession()) {

// start a transaction

transaction = session.beginTransaction();

// get an user object

list = session.createQuery("from Emptable").getResultList();

System.out.println("연습:" + list.get(0).getName());

// commit transaction

transaction.commit();

} catch (Exception e) {

if (transaction != null) {

transaction.rollback();

}

e.printStackTrace();

}

        return list;

}


@Override

public Emptable getList(Integer num) {

Transaction transaction = null;

Emptable emptable = null;

try (Session session = HibernateUtil.getSessionFactory().openSession()) {

transaction = session.beginTransaction();

emptable = session.get(Emptable.class, num);

            

System.out.println("특정 조회:" + emptable.getName());

transaction.commit();


return emptable;

        } catch (Exception e) {

            if (transaction != null) {

                transaction.rollback();

            }

            e.printStackTrace();

            

            return null;

        }

}



@Override

public void save(Emptable emptable) {

Transaction transaction = null;

try (Session session = HibernateUtil.getSessionFactory().openSession()) {

// start a transaction

transaction = session.beginTransaction();

// save the student object

session.save(emptable);

// commit transaction

transaction.commit();

} catch (Exception e) {

if (transaction != null) {

transaction.rollback();

}

e.printStackTrace();

}

}


@Override

public int update(Emptable emptable) {


Transaction transaction = null;

String hql = null;

int result = -1;

try (Session session = HibernateUtil.getSessionFactory().openSession()) {

// start a transaction

transaction = session.beginTransaction();

// save the student object

hql = "UPDATE Emptable set name = :name, "  +

"address = :address, createdate = :createdate " +

             "WHERE empno = :empno";

Query query = session.createQuery(hql);

query.setParameter("name", emptable.getName());

query.setParameter("address", emptable.getAddress());

query.setParameter("createdate", emptable.getCreatedate());

query.setParameter("empno", emptable.getEmpno());

result = query.executeUpdate();


System.out.println("수정결과:" + result);

// commit transaction

transaction.commit();

} catch (Exception e) {

if (transaction != null) {

transaction.rollback();

}

e.printStackTrace();

}

return result;

}


@Override

public int delete(Integer num) {

Transaction transaction = null;

String hql = null;

int result = -1;

try (Session session = HibernateUtil.getSessionFactory().openSession()) {

// start a transaction

transaction = session.beginTransaction();

// save the student object

hql = "Delete from Emptable " +

             "WHERE empno = :empno";

Query query = session.createQuery(hql);

query.setParameter("empno",  num);

result = query.executeUpdate();


System.out.println("삭제결과:" + result);

// commit transaction

transaction.commit();

} catch (Exception e) {

if (transaction != null) {

transaction.rollback();

}

e.printStackTrace();

}

return result;

}


@Override

public Emptable searchName(Integer num, String name) {


Transaction transaction = null;

String hql = null;

Emptable emp = null;

try (Session session = HibernateUtil.getSessionFactory().openSession()) {

// start a transaction

transaction = session.beginTransaction();

// save the student object

hql = "from Emptable " +

             "WHERE empno = :empno and name = :name";

Query query = session.createQuery(hql);

query.setParameter("empno", num);

query.setParameter("name",  name);

emp = (Emptable) query.list().get(0);


System.out.println("번호, 이름 검색");

// commit transaction

transaction.commit();

return emp;

} catch (Exception e) {

if (transaction != null) {

transaction.rollback();

}

e.printStackTrace();

return null;

}

}


}



코드 8) EmpTableService.java


[첨부(Attachments)]

EmpTableService.zip


package com.hibernateMaven.web.service;


import java.util.List;


import org.hibernate.query.*;

import org.hibernate.Session;

import org.hibernate.Transaction;


import com.hibernateMaven.web.factory.HibernateUtil;

import com.hibernateMaven.web.model.Student;


public class StudentService implements IStudent {


@Override

public List<Student> allList() {

return null;

}


@Override

public Student getList(Integer num) {

Student student;

Transaction transaction = null;

        Session session= HibernateUtil.getSessionFactory().openSession();

         try

         {

  transaction = session.beginTransaction();

             student=(Student)session.get(Student.class,num); 

 

             System.out.println("특정 조회:" + student.getName());

             transaction.commit();

             return student;

         }

         catch (Exception e) 

         {

        e.printStackTrace();

            return null;

         }

         finally 

         {

             session.close(); 

         }

         

         /*

Student student = null;

try (Session session = HibernateUtil.getSessionFactory().openSession()) {

transaction = session.beginTransaction();

student = session.get(Student.class, num);

            

System.out.println("특정 조회:" + student.getName());

        } catch (Exception e) {

            if (transaction != null) {

                transaction.rollback();

            }

            e.printStackTrace();

        }

*/

}


}



코드 9) StudentService.java


[첨부(Attachments)]

StudentService.zip




13. Servlet - 완성하기


1부에서 생성한 서블렛의 내용을 구현하였다.


package com.hibernateMaven.web.controller;


import java.io.IOException;

import java.io.PrintWriter;

import java.sql.Date;

import java.util.List;


import javax.servlet.ServletException;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;


import com.hibernateMaven.web.model.Emptable;

import com.hibernateMaven.web.service.EmpTableService;

import com.hibernateMaven.web.service.StudentService;


public class SampleServlet extends HttpServlet {

private static final long serialVersionUID = 1L;

       

    public SampleServlet() {

        super();

    }


/**

* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)

*/

protected void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {


res.setContentType("text/html;charset=UTF-8");

PrintWriter out = res.getWriter();

// HTML 스타일 정의

out.println("<html><head><title>Hibernate Maven - MySQL 8 실험</title></head><body>");

EmpTableService service = new EmpTableService();


// 1. 전체 조회

List<Emptable> emp1 = service.allList();


// 2. 특정 ID 조회

Emptable emp2 = service.getList(1);

// 3. 삽입 구현

Emptable createEmp = new Emptable();

createEmp.setName("홍길동");

createEmp.setAddress("행복구 행복시");

java.sql.Date sqlDate = java.sql.Date.valueOf("2020-05-20");

createEmp.setCreatedate(sqlDate);

service.save(createEmp);

// 4. 수정

Emptable updateEmp = new Emptable();

updateEmp.setName("동길홍");

updateEmp.setAddress("시복행 구복행");

sqlDate = java.sql.Date.valueOf("1990-09-01");

updateEmp.setCreatedate(sqlDate);

updateEmp.setEmpno(3);

service.update(updateEmp);

// 5. 삭제

service.delete(4);

// 6. 특정 이름, 번호 조회

Emptable query1 = service.searchName(18, "홍길동");

out.println("주소:" + query1.getAddress() + "<br/>" );

out.println("</body></html>");

out.close();

}


/**

* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)

*/

protected void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {

}


}



코드 10) SampleServlet.java


[첨부(Attachments)]

SampleServlet.zip



package com.hibernateMaven.web.controller;


import java.io.IOException;

import java.io.PrintWriter;

import java.util.List;


import javax.servlet.ServletException;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;


import com.hibernateMaven.web.model.Student;

import com.hibernateMaven.web.service.StudentService;



public class StudentServlet extends HttpServlet {

private static final long serialVersionUID = 1L;

       

    public StudentServlet() {

        super();

    }


/**

* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)

*/

protected void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {


res.setContentType("text/html;charset=UTF-8");

PrintWriter out = res.getWriter();

// HTML 스타일 정의

out.println("<html><head><title>Hibernate Maven - MySQL 8 실험(Table:Student)</title></head><body>");

StudentService service2 = new StudentService();


// 1. 전체 조회

//List<Student> student1 = service.allList();

service2.getList(1);

out.println("</body></html>");

out.close();

}


/**

* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)

*/

protected void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {

doGet(req, res);

}


}



코드 11) StudentServlet.java


[첨부(Attachments)]

StudentServlet.zip



15. 맺음글(Conclusion)


OR-M 프레임워크 중 하나인 Hibernate 5.4 Final 버전을 사용하는 방법에 대해서 소개하였다.


추가적으로 알아보면 도움되는 것: Hibernate HQL
-> SQL언어가 사라진 것이 아니라, 또 Hibernate가 제공하는 HQL이 탄생하게 되었다.
ORM을 맹신하면 안 되는 이유가 있는 것이다.

* Link1: https://howtodoinjava.com/hibernate/complete-hibernate-query-language-hql-tutorial/ (영어), 2014-10-30

  Link2: https://www.tutorialspoint.com/hibernate/hibernate_query_language.htm, (영어)


* 공식 사이트: https://docs.jboss.org/hibernate/orm/5.4/userguide/html_single/Hibernate_User_Guide.html#hql, Hibernate 5.4 Final 메뉴얼

  (조금 공부할 양이 많다.) - 2020-08-27 10:35:21


제대로 사용하기 위해서는 이 밖에도 Hibernate 프레임워크 하나에만 많은 공부가 필요한 것 같다.

물론 전부 학습 할 수는 없다.



* 참고자료(References)


[Hibernate - Example Project]


5. GitHub - RameshMF/Hibernate-ORM-Tutorials: 40+ source code Examples/Tutorials/Guides of Hibernate ORM Framework, https://github.com/RameshMF/Hibernate-ORM-Tutorials, Accessed by 2020-09-21, Last Modified .


-> 추천(43점): 구현하는 예제가 다양하게 이클립스 버전으로 작성되어 있다. 물론 100% 돌아가는 건 아니다. 구현할 때 많은 참고가 된다.


6. Hibernate 5 XML Configuration Example - DZone Java, https://dzone.com/articles/hibernate-5-xml-configuration-example, Accessed by 2020-09-21, Last Modified 2018-11-29.


-> 추천(55점): Web 프로젝트는 아니었지만, 구현에 있어서 큰 도움을 주었다.


[Hibernate HQL]


7. Hibernate HQL - Hibernate Query Language Examples - - HowToDoInJava, https://howtodoinjava.com/hibernate/complete-hibernate-query-language-hql-tutorial/, Accessed by 2020-09-21, Last Modified 2014-10-30.


-> 추천(40점): 기본적인 부분에 대해서 잘 작성되었다.


8. Hibernate ORM 5.4.21.Final User Guide, https://docs.jboss.org/hibernate/orm/5.4/userguide/html_single/Hibernate_User_Guide.html, Accessed by 2020-09-21, Last Modified 2020-08-27.


-> 추천(40점): 조금 어렵긴 해도 알면 도움이 될 거 같다. 다 활용하진 못할 거 같다는 생각도 든다.


9. Hibernate - Query Language - Tutorialspoint, https://www.tutorialspoint.com/hibernate/hibernate_query_language.htm, Accessed by 2020-09-21, Last Modified .


-> 추천(40점): 기본적인 부분에 대해서 잘 작성되었다.


[Hibernate - XML]


10. java - [Hibernate]Error: entity class not found: - Stack Overflow, https://stackoverflow.com/questions/6692882/hibernateerror-entity-class-not-found/38801518, Accessed by 2020-09-21, Last Modified 2016.


-> XML-Mapping 시연할 때, "[Hibernate]Error: entity class not found:"를 해결하기 위해서 찾아본 것이다.


11. Brain to Blog :: 하이버네이트(Hibernate) 사용하기, https://antop.tistory.com/entry/%ED%95%98%EC%9D%B4%EB%B2%84%EB%84%A4%EC%9D%B4%ED%8A%B8Hibernate-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0, Accessed by 2020-09-21, Last Modified 2009-08-24.

반응형
728x90
300x250

[JSP] 10. JSP 폴더 구성에 대한 것


이전 게시글을 따라 수행하면, 허점이 하나 있다는 것을 알 수 있다.

뷰 파일로 만든 .jsp파일을 직접 주소만 알게 되면, 접근할 수도 있다는 취약점이 있다.


1. [JSP] 9. MVC 디자인 패턴 - 초간단 이해, FrontController 패턴(1), 2020. 9. 20. 17:24

   https://yyman.tistory.com/1401


이러한 점을 설명하면서 알아두면 좋은 폴더의 구성에 대해서 소개하려고 한다.



[JSP 폴더에 대한 설명]


1) 프로젝트명/java resources/src/

   servlet, Class, Interface 등 예를 들면 java파일을 담는 곳

    - src 밑에 폴더 만들어서 작성  

      예) someFolder, SomeClass.java 식으로 사용


프로젝트를 개설해보면, 일부 살짝 차이가 있을 수 있겠으나 통상적으로 비슷하다.


2) 프로젝트명 "webContent"  

   - jsp 문서를 작성하면 된다.


3) 프로젝트명/webContent/WEB-INF/ 

   - 아래는 접근이 안됨, 보안 영역임.

    - 프로젝트명/webContent/WEB-INF/lib/  폴더에 각종

      jar 파일, ojdbc6 등을 붙여 넣어야 실행이 가능함.


※ jsp는 주소가 노출되어 있어서 공격을 받을 수 있다

    그래서, 

    @webServlet("*.do")와  같은 URL Mapping 어노테이션을 사용하여 URL 숨김 효과를 본다.

    또는 web.xml 에 정의하여 사용.





2. 9번 글 - 프로젝트에 적용해보기


WebContest에 있는 addressInsert.jsp와 addressList.jsp를 WEB-INF안에 view 폴더를 만들어서 이동시킨다.



그림 1) WEB-INF\view 폴더에 있는 jsp파일 실행시키기


jsp파일 경로를 입력하였으나 동작되지 않는 것을 확인할 수 있다.



2-1. 소스코드 변경하기


서블릿으로 WEB-INF\View에 있는 jsp파일을 사용하려면, 

AddressInsertController.java와 AddressListController.java의 파일 내용을 수정한다.



그림 2) 수정된 AddressInsert.java 파일



그림 3) 수정된 AddressList.java 파일


package com.eduJsp.controller;


import java.io.IOException;


import javax.servlet.ServletException;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;


public class AddressInsertController implements Controller {


@Override

public void execute(HttpServletRequest req, HttpServletResponse res) throws

ServletException, IOException{


HttpUtil.forward(req, res, "/WEB-INF/view/addressInsert.jsp");

}


}




package com.eduJsp.controller;


import java.io.IOException;


import javax.servlet.ServletException;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;


public class AddressListController implements Controller {


@Override

public void execute(HttpServletRequest req, HttpServletResponse res) throws

ServletException, IOException {

HttpUtil.forward(req, res, "/WEB-INF/view/addressList.jsp");

}


}




3. 결과


서블릿을 통해서 결과를 확인해보면, 이해할 수 있을 것으로 보인다.



그림 4) Servlet 파일(*.do) - 호출하기



4. 작업내용 정리해보기


변경작업을 수행한 이력을 체크해본 것이다. 조금 알기 쉽게 표기해보았으니 참고하여 정리해보면 좋을 듯 하다.



그림 5) 프로젝트 구조 - 변경 사항


반응형
728x90
300x250

[Spring-Framework] 6. Maven, Hibernate 5.4, Servlet, MySQL 8 연동(CRUD) - (1)


Hibernate 5.4 이상에서 ORM기반의 데이터베이스를 사용하는 방법에 대해서 소개하겠다.

글을 작성하게 된 계기는 인터넷을 검색해보니깐, 워낙 오래된 Hibernate 버전을 기준으로 현실성이 없는 복잡한 구현의 글이 많아서 쉽고 간단하게 작성할 수 없겠느냐는 생각을 갖고 좀 더 쉽고 적응하기 쉽도록 만들어보고자 작성하게 되었다.


글을 2부로 구성하였다.


조금 태스트를 하면서 느낀 소감은 iBatis나 SQL이 훨씬 사용하기에는 편리하다.

절차지향적인 언어인 SQL 사용하는 게 나쁜 건만 아니라고 본다.


조금 양이 많을 수 밖에 없어서 불가피하게 두 개의 글로 나누었으니 참고하길 바란다.


Hibernate(하이버네이트)란?

하이버네이트 ORM은 자바 언어를 위한 객체 관계 매핑 프레임워크이다.
객체 지향 도메인 모델을 관계형 데이터베이스로 매핑하기 위한 프레임워크를 제공한다.
하이버네이트는 GNU LGPL 2.1로 배포되는 자유 소프트웨어이다.

https://hibernate.org/



ORM(Object-relational mapping)이란?

ORM(Object-relational mapping)을 단순하게 표현하면 객체와 관계와의 설정이라 할 수 있다.
ORM에서 말하는 객체(Object)의 의미는 우리가 흔히 알고 있는 OOP(Object_Oriented Programming)의 그 객체를 의미한다는 것을 쉽게 유추할 수 있을 것이다. 그렇다면 과연 관계라는 것이 의미하는 것은 무엇일까?
지극히 기초적인 이야기지만 개발자가 흔히 사용하고 있는 관계형 데이터베이스를 의미한다.



[환경]

- 운영체제: Microsoft Windows 10


- 웹서버: Apache-tomcat-9.0.37                (http://tomcat.apache.org/)


- IDE: Spring Tool-Suite 4-4.7.2 Releases      (https://spring.io/tools)

  * JBoss -> Hibernate만 설치할 것(필수) - Help->Eclipse Marketplace


- 데이터베이스: MySQL 8.0.21 Windows 64bit  (https://dev.mysql.com/downloads/mysql/)

  * Library: Connector/J 8.0.21


- 개발 라이브러리:

  * Maven

    - https://maven.apache.org/

  * hibernate-entitymanager (5.4.21 Final)

    - https://mvnrepository.com/artifact/org.hibernate/hibernate-entitymanager

    - https://hibernate.org/

  * javax.inject (1)
  * javax.servlet-api (4.0.1)

    - https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api

  * mysql-connector-java (8.0.21)

    - https://mvnrepository.com/artifact/mysql/mysql-connector-java




1. MySQL Server - 설치하기


아래의 사이트에 접속한다.

https://dev.mysql.com/downloads/mysql/


설치 방법은 워낙 간단하고, 잡음이 적은 프로그램이므로 짧게 정리하였다.




그림 1) MySQL Server 8.0.21 - 설치하기





그림 2) MySQL Server 8.0.21 - 설치하기



2. 테이블 설계 (emptable, student)


dto 또는 model 영역 중 하나의 작업으로 두 개의 테이블을 설계하였다.


"emptable", "student"




그림 3) 데이터베이스 테이블 생성 - emptable






그림 4) 데이터베이스 테이블 생성 - student



CREATE TABLE `emptable` (

  `empno` INT NOT NULL AUTO_INCREMENT,

  `name` VARCHAR(20) NULL,

  `address` VARCHAR(100) NULL,

  `createdate` DATE NULL,

  PRIMARY KEY (`empno`));


INSERT INTO `emptable` (`name`, `address`, `createdate`) VALUES ('하하', '안녕', '20-09-1');



CREATE TABLE `student` (

  `studentno` INT NOT NULL AUTO_INCREMENT,

  `name` VARCHAR(45) NULL,

  `address` VARCHAR(100) NULL,

  `createdate` DATE NULL,

  PRIMARY KEY (`studentno`))

ENGINE = InnoDB

DEFAULT CHARACTER SET = utf8

COLLATE = utf8_unicode_ci;


INSERT INTO `student` (`name`, `address`, `createdate`) VALUES ('홍길동', '연습', '21-3-4');


[첨부(Attachments)]

emptable.zip

student.zip




3. 프로젝트 구성


미리 살펴보는 hibernateMaven2 프로젝트의 구성이다.



그림 5) 프로젝트 구성도 - hibernateMaven2


* Servlet 구성

- /SampleServlet

- /StudentServlet



4. POM.xml 수정하기(Maven 적용된 프로젝트)


pom.xml이 왜 없냐고 생각하는 경우가 있을 수 있다.

알기 쉽게 소개하면, maven이 적용되어있는 프로젝트에서 존재하는 기능이라고 보면 된다.


http://mvnrepository.com에 접속해서 몇 가지 구성을 찾아서 입력해줘야 한다.


(중략)

      <!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-entitymanager -->

<dependency>

    <groupId>org.hibernate</groupId>

    <artifactId>hibernate-entitymanager</artifactId>

    <version>5.4.21.Final</version>

</dependency>

    <!-- @Inject -->

    <dependency>

        <groupId>javax.inject</groupId>

        <artifactId>javax.inject</artifactId>

        <version>1</version>

    </dependency>

    <!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->

<dependency>

    <groupId>javax.servlet</groupId>

    <artifactId>javax.servlet-api</artifactId>

    <version>4.0.1</version>

    <scope>provided</scope>

</dependency>

    <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->

<dependency>

    <groupId>mysql</groupId>

    <artifactId>mysql-connector-java</artifactId>

    <version>8.0.21</version>

</dependency>


(중략)




그림 6) pom.xml 수정하기







5. hibernate 환경설정 - 생성과 수정


이 작업은 "JBoss -> hibernate" 라이브러리를 설치하지 않으면, 의미가 없다고 보면 된다.

수동으로 물론 셋팅할 수는 있으나 권장하진 않는다. (시도해봐도 무방, 처음에 찾는데 시간이 오래 걸린다. 이런 문제)




그림 7) 프로젝트 항목 -> 오른쪽 버튼 메뉴 모습





그림 8) Hibernate Configuration File 선택하기


- Hibernate XML Mapping file 기능은 생성이 되지 않는다.

  (꼭 반드시 XML Mapping으로 hibernate resources를 잡을 필요는 없으며, Class Mapping도 사용된다.)


셋팅에서 필요한 부분들을 정리해보았다.


* hibernate.connection.driver_class = com.mysql.jdbc.Driver

* hibernate.connection.url = jdbc:mysql://localhost:3306/web?serverTimezone=UTC&characterEncoding=utf8

* hibernate.dialect = org.hibernate.dialect.MySQL8Dialect

* hibernate.show_sql = true

* hibernate.hbm2ddl.auto = update

* hibernate.default_entity_mode = pojo

* hibernate.current_session_context_class = thread



문제1. [MySQL 초기 설치 후 작업했을 때, 타임존 문제]


타임존 미설정시

* ERROR: The server time zone value


해결 방법1: serverTime=UTC를 입력해준다.

해결 방법2: 서버 my.cnf 파일에서 timezone을 지정해준다.


* my.cnf 파일 내에 환경 설정을 변경해주는 방법이 있다.
[mysqld]

default-time-zone='+9:00'



문제2. [UTF-8 환경설정 문제]


해결 방법1: characterEncoding=utf8을 입력해준다.

해결 방법2: 서버 my.cnf 파일에서 timezone을 지정해준다.


* my.cnf 파일 내에 환경 설정을 변경해주는 방법이 있다.

[mysqld]

init_connect = SET collation_connection = utf8_general_ci

init_connect = SET NAMES utf8

character-set-server = utf8

collation-server = utf8_general_ci




그림 9) hibernate.cfg.xml


[첨부(Attachments)]

hibernate.cfg.zip


* 경로는 다음과 같다. 참고로 초기에 폴더가 생성되어 있는 것이 아니라서, 수동으로 폴더를 만들어줘야 한다.


폴더: src/main/resources




그림 10) hibernate 모습



물론 공식 메뉴얼만 가지고 이해가 되지 않으면 추가적인 검색을 시도해봐도 된다.





5. 결과 - 미리 살펴보는 결과


완성된 작품은 이러한 모습을 가지고 있다.

무슨 작품을 만들지 생각해보기 위함이다.


그림 11) 출력 결과 - 웹 브라우저




그림 12) 출력 결과 - 웹 브라우저(2)




그림 13) 출력 결과 - 웹 브라우저(3)




6. 2부에서 만나요 


게시글 2부에서 연속 글이 연재된다.


[Spring-Framework] 7. Maven, Hibernate 5.4, Servlet, MySQL 8 연동(CRUD) - (2)

https://yyman.tistory.com/1405




* 참고 자료(References)


1. Hibernate Getting Started Guide, https://docs.jboss.org/hibernate/orm/5.4/quickstart/html_single/, Accessed by 2020-09-21, Last Modified 2020-08-27 10:35.

- 공식적인 Hibernate 메뉴얼이니 이해가 안 되면 읽어보길 바란다.


2. Hibernate 5 Java Configuration Example - DZone Java, https://dzone.com/articles/hibernate-5-java-configuration-example, Accessed by 2020-09-21, Last Modified 2018-12-03

- 추천(70점): 가장 실질적으로 많은 도움을 받았던 글이다. (영어 글)


3. MySQL(MariaDB) 서버 타임존 설정하기, https://offbyone.tistory.com/318, Accessed by 2020-09-21, Last Modified 2018-07-17 23:38.

4. java.sql.SQLException: The server time zone value ‘xx time’ is unrecognized, https://mkyong.com/jdbc/java-sql-sqlexception-the-server-time-zone-value-xx-time-is-unrecognized/, Accessed by 2020-09-21, Last Modified 2019-07-05.

- 비고: (영어 글)이다.

반응형
728x90
300x250

[JSP] 9. MVC 디자인 패턴 - 초간단 이해, FrontController 패턴(1)


이전의 글을 보면, 순수하게 "JSP/서블릿"으로 처리하는 방법에 대해서 소개하고 있는데, 실질적으로 개발에서 자주 사용할 수 있는 패턴에 대해서 소개해보려고 한다.


기존 개발에 대해서 다시 한번 생각해보도록 하자.



그림 1. 기존 개발방법론의 문제점 - 요약


기존 개발방법론을 살펴보면, 크게 JSP, Servlet 처리에 대해서 하나의 코드 안에 "개발 코드(액션 코드 또는 동적 코드)", "사용자 인터페이스(UI)" 등이 혼잡되어 구현되는 문제가 있을 수 있다.


Servlet을 사용해보면 알겠지만, 자바 코드 내에서 홈페이지 코드라고 불리는 html, css 등을 넣어준다는 게 보통 쉬운 일이 아니다.

물론 저레벨의 C언어 등으로 개발해보면, 언어 특성 때문에 어쩔 수 없이 MVC 개발이 어려운 경우가 있을 수도 있다.


이야기하고자 하는 것은 MVC패턴으로 개발을 하게 되는 배경은 "소프트웨어공학"에서 유지보수 차원의 문제부터 역할 전문화 등의 각종 공학적인 문제 때문에 패턴이라는 게 생겼을 것으로 보인다.


[첨부(Attachments)]

200920_Diagram1.pptx




1. 디자인 패턴이란?


디자인 패턴은 프로그램을 개발할 때 사용하는 일정한 뼈대(프레임) 또는 틀이라고 생각하면 된다.


디자인 패턴만 전문적으로 다루고 있는 참고서적이나 참고 사이트가 있는데 찾아보면 도움이 될 것이라고 본다.

(다소 처음에는 이해가 안 될 수도 있음. 개발을 조금 해봐야 필요성을 인지하게 된다.)





2. Model View Controller (MVC) 디자인 패턴


php나 asp 개발을 해보면, 디자인패턴이 초기에 바로 적용되진 않는다. 

물론 최근에는 aspx(asp.net)의 경우에는 model 1, model 2 느낌의 개발이 적용되어 있다고 본다.

이유는 간단한게 C#의 직접적인 경쟁자는 Java 프로그래밍 언어라는 점이다.


Java 진영의 JSP 개발을 하게 되면, MVC 패턴의 적용을 먼저 시작하고 들어가게 된다.


그림 2. MVC Model 1, MVC Model 2 구조


도식화된 그림으로 이해하고 있어도 무방하다. 그림 1에서 언급했던 이야기는 그림 2로서 정리해볼 수가 있다.


[첨부(Attachments)]

200920_Diagram2.pptx


현재에도 Model 1이 사용되는 이유로는 장점이 있다.

초기 개발 속도에 있어서는 빠를 수가 있다.

무슨 이야기냐면, 컨트롤러와 뷰 영역을 신경쓰지 않고 개발하기 때문에 어렵게 공부하고 개발할 필요가 없는 것이다.

JSP 코드나 Servlet 코드 내에 통합적으로 코드를 집어넣으면 되는데, 굳이 컨트롤러를 복잡하게 매번 신경쓰고 개발하지 않아도 되는
프로젝트가 있을 수 있다.

Model2는 설계가 어려운 반면, 유지보수로 갔을 때는 역할 구분이 쉽다는 장점을 가지고 있다.


이전의 방법과 현재의 방법에서 적절한 방법을 찾아서 적용하는 것도 중요하다고 본다.


* 모델은 서비스와 데이터베이스 처리를 담당하는 역할을 하며, 각 로직처리, DB 질의 처리 기능을 수행한다.

* 는 JSP, CSS, HTML를 사용하여 구현함. 

* 컨트롤러는 뷰와 모델을 중개하는 역할을 수행하며, 클라이언트가 전달한 파라마터를 추출하여 모델로 전달하고, 처리결과를 보여주는 기능을 한다.



3. Eclipse의 Dynamic Web Project로 구현해보기


Apache Maven을 활용하면, 속도감이 있게 구현할 수 있겠으나 원초적인 방법으로 구현해보려고 한다.



그림 3. Dynamic Web Project - 생생하기


New 메뉴에서 Project -> Others를 누르면 위의 화면이 뜬다.

Web 폴더에서 Dynamic Web Project를 선택한 후 Next를 누른다.




그림 4. Dynamic Web Project - 생생하기


프로젝트 명을 입력하고 Next를 누른다.

Finish를 눌러도 무방하나 web.xml 파일을 자동으로 생성하려고 한다.



그림 5. Dynamic Web Project - 생생하기


Next를 누른다.



그림 6. Dynamic Web Project - 생생하기


Generate web.xml deployment descriptor에 체크를 한 후 Finish를 누르면 web.xml이 포함된 신규 프로젝트가 생성되는 것을 확인할 수 있다.



그림 7. Dynamic Web Project - 생생하기


성공적으로 신규 프로젝트가 생성되었다.



4. web.xml 설정하기


Front Controller 패턴을 적용하기 위해서 Web.xml 파일을 살짝 수정해주어야 한다.



그림 8. 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>edu-jsp-MVC</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>

  

<!-- Front Controller 패턴 -->

<servlet>

<servlet-name>front</servlet-name>

<servlet-class>com.eduJsp.controller.FrontController</servlet-class>

<init-param>

<param-name>charset</param-name>

<param-value>UTF-8</param-value>

</init-param>

</servlet>

<servlet-mapping>

<servlet-name>front</servlet-name>

<url-pattern>*.do</url-pattern>

</servlet-mapping>

  

</web-app>


[소스 코드]


[첨부(Attachments)]

web.zip




5. FrontController 생성하기(서블릿) - Controller


FrontController 패턴의 초기 컨트롤러를 생성하겠다.


그림 9. Servlet 만들기 - FrontController 생성


Java Resources를 오른쪽 버튼으로 클릭한다.

New-> Servlet을 클릭한다.



그림 10. Servlet 만들기 - FrontController 생성


Java Package 명은 com.eduJsp.controller로 입력한다.

Class Name 명은 FrontController로 입력한다.

Next를 누른다.



그림 11. Servlet 만들기 - FrontController 생성


Next를 누른다.



그림 12. Servlet 만들기 - FrontController 생성


init, service만 체크해준다.

Finish를 누른다.




그림 13. Servlet-API 복사, 붙여넣기 하기


servlet-api 파일을 apahce-tomcat 설치 경로에서 lib 폴더에서 찾아보면 파일이 있다.

프로젝트의 WEB-INF/lib 폴더에 "복사, 붙여넣기"를 해준다.





6. Controller 인터페이스 생성하기 - Controller


Controller에 대한 인터페이스에 관한 것이다.

공통적으로 사용할 인터페이스이니 지정을 한번 해주면 된다.



그림 14. Interface 만들기


"com.eduJsp...." 폴더에서 오른쪽 버튼을 클릭한다.

New->Interface를 클릭한다.



그림 15. Interface 만들기


"Name(파일명)"을 Controller로 입력한다.

Finish를 누른다.



그림 16. Interface 만들기


package com.eduJsp.controller;


import java.io.IOException;


import javax.servlet.ServletException;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;


public interface Controller {


public void execute(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException;

}


* 파일명: Controller.java


[첨부(Attachments)]

Controller.zip




7. AddressInsertController와 AddressListController - Controller


이번에 수행할 작업은 앞서 6에서 생성한 Controller 인터페이스를 바탕으로 List, Insert 컨트롤러를 만들어보도록 하겠다.



그림 17. Controller 구현부 - 만들기


com.eduJsp 오른쪽 버튼 -> New -> Class를 누른다.




그림 18. Controller 구현부 - 만들기


두 개를 만들어야 함. (그림 17, 그림 18과정 - 반복)
- ClassName(클래스명): AddressInsertController

- ClassName(클래스명): AddressListController


클래스를 두개 만들어준다.

참고로 클래스를 생성할 때 Interfaces를 Add하여 Finish를 누르면 메서드(Method)가 자동으로 생성된다.



8. FrontController.java 코드 작성하기(서블릿) - Controller


앞서 작성한 컨트롤러(인터페이스)를 바탕으로 FrontController를 작성해보겠다.



그림 19. FrontController.java 코드 작성


package com.eduJsp.controller;


import java.io.IOException;

import java.util.HashMap;


import javax.servlet.ServletConfig;

import javax.servlet.ServletException;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;


public class FrontController extends HttpServlet {

private static final long serialVersionUID = 1L;

    

private String charset = null;

private HashMap<String, Controller> list = null;

    public FrontController() {

        super();

    }


    @Override

public void init(ServletConfig sc) throws ServletException {

    charset = sc.getInitParameter("charset");

    list = new HashMap<String, Controller>();

   

    list.put("/board/insert.do", new AddressInsertController());

    list.put("/board/list.do", new AddressListController());

   

}


    @Override

protected void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {


    req.setCharacterEncoding(charset);

    String url = req.getRequestURI();

    String contextPath = req.getContextPath();

    String path = url.substring(contextPath.length());

   

    Controller subController = list.get(path);

    subController.execute(req, res);

   

}


}



* 파일명: FrontController.java


[첨부(Attachments)]

FrontController.zip




9. HttpUtil 코드 작성하기(서블릿) - Controller


RequestDispatcher가 해당 주제에서는 핵심이라고 보면 되겠다.

앞서 작성한 AddressListController나 AddressInsertController 등에서 jsp파일 경로 등을 요청했을 때, 작업을 처리해주는 역할을 수행한다.



그림 20. HttpUtil 코드 작성


com.eduJsp 폴더를 오른쪽 버튼한다.

New->Servlet을 클릭한다.




그림 21. HttpUtil 코드 작성


Class Name은 HttpUtil로 지정한다.

Next를 누른다.



그림 22. HttpUtil 코드 작성


Next를 누른다.




그림 23. HttpUtil 코드 작성


service만 체크하고 Finish를 누른다.

함수 원형을 생성하기 귀찮아서 하나만 선택하였다.

참고로 다음 작업에서는 함수 원형을 살짝 수정할 것이다.




그림 24. HttpUtil 코드 작성



package com.eduJsp.controller;


import java.io.IOException;


import javax.servlet.RequestDispatcher;

import javax.servlet.ServletException;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;


public class HttpUtil extends HttpServlet {

private static final long serialVersionUID = 1L;

       

public static void forward(HttpServletRequest req, HttpServletResponse res, 

String path) throws ServletException, IOException {

try {

RequestDispatcher dispatcher = req.getRequestDispatcher(path);

dispatcher.forward(req, res);

}catch(Exception ex) {

System.out.println("forward 오류:" + ex);

}


}


}



* 파일명: HttpUtil.java


[첨부(Attachments)]

HttpUtil.zip




10. addressList.jsp, addressInsert.jsp 파일 생성하기 - View (뷰 영역 만들기)


이번 작업에서는 뷰 영역을 만들어주겠다.



그림 25. 뷰 생성하기


WebContent 폴더에서 오른쪽 버튼을 클릭한다.

New->JSP File을 클릭한다.




그림 26. 뷰 생성하기


File name은 addressList로 입력한 후 Finish를 누른다.



그림 27. 뷰 생성하기


File name은 addressInsert로 입력한 후 Finish를 누른다.


<%@ page language="java" contentType="text/html; charset=UTF-8"

    pageEncoding="UTF-8"%>

<!DOCTYPE html>

<html>

<head>

<meta charset="UTF-8">

<title>목록 - MVC 페이지</title>

</head>

<body>

<h3>목록 - MVC 페이지</h3>

</body>

</html>


* 파일명: addressList.jsp


[첨부(Attachments)]

addressList.zip


<%@ page language="java" contentType="text/html; charset=UTF-8"

    pageEncoding="UTF-8"%>

<!DOCTYPE html>

<html>

<head>

<meta charset="UTF-8">

<title>삽입 - MVC 페이지</title>

</head>

<body>

<h3>삽입 - MVC 페이지</h3>

</body>

</html>


* 파일명: addressInsert.jsp


[첨부(Attachments)]

addressInsert.zip



11. AddressInsertController.java, AddressListController.java


AddressInsertController.java, AddressListController.java 파일에 관한 것이다.


package com.eduJsp.controller;


import java.io.IOException;


import javax.servlet.ServletException;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;


public class AddressInsertController implements Controller {


@Override

public void execute(HttpServletRequest req, HttpServletResponse res) throws

ServletException, IOException{


HttpUtil.forward(req, res, "/WEB-INF/view/addressInsert.jsp");

}


}


* 파일명: AddressInsertController.java


package com.eduJsp.controller;


import java.io.IOException;


import javax.servlet.ServletException;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;


public class AddressListController implements Controller {


@Override

public void execute(HttpServletRequest req, HttpServletResponse res) throws

ServletException, IOException {

HttpUtil.forward(req, res, "/WEB-INF/view/addressList.jsp");

}


}


* 파일명: AddressListController.java



12. 결과


서버에 올려서 확인해보면, 아래와 같은 결과를 출력해볼 수 있다.



그림 28. 출력하기 - 결과(1)



그림 29. 출력하기 - 결과(2)



13. UML 설계(Controller 설계)


"bottom->top" 방식으로 UML 결과를 보여주도록 하겠다.



그림 30. UML 설계도 - edu-jspMVC 프로젝트


예를 들면, 이러한 설계도를 바탕으로 코드를 작성하기에 앞서 한번 더 생각해볼 수 있다.

물론 코드 학습에 있어서는 직접 짜봐야 감이 오는 건 분명하다.


* UML 작성 프로그램: Modelio Open Source 4.0



14. 질의처리 및 로직에 관한 영역 - Model 영역(선택)


모델은 서비스와 데이터베이스 처리를 담당하는 역할을 하며, 각 로직처리, DB 질의 처리 기능을 수행한다.

패키지를 기준으로 보면, com.edu-jspMVC.service에 해당된다고 보면 된다.


모델 영역은 데이터베이스를 사용하지 않거나 복잡한 로직을 구현할 일이 없다면, 선택으로 둬도 무방할 것 같다.


14-1. VO(Value Object) - Model 영역(선택)


정보를 저장할 목적으로 만든 VO(Value Object) 객체라고 정의할 수 있다.


* tableName(테이블명): addressbook


 키

 항목명

 속성 

 PK(기본키)

num

인덱스(ID)

 

name

nvarchar2(20)

 

address

nvarchar2(100)

 

birthdate

date


표 1. addressbook 테이블


package com.eduJsp.vo;


import java.sql.Date;


public class AddressVO {

private int num;

private String name;

private String address;

private Date birthdate;

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 getAddress() {

return address;

}

public void setAddress(String address) {

this.address = address;

}

public Date getBirthdate() {

return birthdate;

}

public void setBirthdate(Date birthdate) {

this.birthdate = birthdate;

}

}


* 파일명: AddressVO.java


[첨부(Attachments)]

AddressVO.zip




14-2. Service 설계 - Model 영역(선택)


클래스명은 "AddressService" 이런 형태로 파일을 구성하여 사용하면 된다.

인터페이스를 설계해도 무방하다.


package com.eduJsp.service;


import java.util.List;


import com.eduJsp.vo.AddressVO;


public interface IAddress {


public AddressVO getAddress(Integer num) ;

public List<AddressVO> allData();

public int insertAddress(AddressVO addressVO);

public int updateAddress(AddressVO addressVO);

public int deleteAddress(AddressVO addressVO);

}


* 파일명: IAddress.java


[첨부(Attachments)]

IAddress.zip


package com.eduJsp.service;


import java.util.List;

import com.eduJsp.vo.AddressVO;


public class AddressService implements IAddress{


@Override

public AddressVO getAddress(Integer num) {

return null;

}


@Override

public List<AddressVO> allData() {

// TODO Auto-generated method stub

return null;

}


@Override

public int insertAddress(AddressVO addressVO) {

// TODO Auto-generated method stub

return 0;

}


@Override

public int updateAddress(AddressVO addressVO) {

// TODO Auto-generated method stub

return 0;

}


@Override

public int deleteAddress(AddressVO addressVO) {

// TODO Auto-generated method stub

return 0;

}

}



* 파일명: AddressService.java


[첨부(Attachments)]

AddressService.zip




14-3. DAO(Data Access Object) - Model 영역(선택)


데이터베이스 처리에 관한 실질적인 코드를 구현하는 곳이다.

현재 프로그램들의 대부분은 DB를 사용하지만, 꼭 사용해야 하는 것은 아니다.


패키지를 기준으로 보면, "com.edu-jspMVC.dao"에 해당된다고 보면 된다.

예를 들면, 클래스명 "AddressDAO" 이런 형태로 파일을 구성하여 사용하면 된다.


여기 부분에 예를 들면, Resultset, Preparedstatement, Connection 등의 기능을 활용하여 SQL문장 등을 정의하는 것이다.


package com.eduJsp.dao;


import java.sql.Connection;

import java.sql.PreparedStatement;

import java.sql.ResultSet;


import com.eduJsp.vo.AddressVO;


public class AddressDAO {


    public AddressVO selectAddress(Integer num) {


    Connection conn = null;

    PreparedStatement pstmt = null;

    ResultSet rs = null;

   

    AddressVO node = new AddressVO();

   

    String sql = "select NUM, NAME, ADDRESS, BIRTHDATE " +

      " from addressbook" + 

      " where num=?";

    System.out.println(sql);

   

    // 달력 날짜 출력 버그 개선

   

    try {

    //conn = session.connect();

   

    pstmt = conn.prepareStatement(sql);

    pstmt.setInt(1, num);

   

    rs = pstmt.executeQuery();

   

    if ( rs.next() ) {

    node.setNum(rs.getInt(1));

    node.setName(rs.getNString(2));

    node.setAddress(rs.getNString(3));

    node.setBirthdate(rs.getDate(4));

    }

   

   

    }catch(Exception ex) {

    System.out.println("오류 발생: " + ex);

    }

    finally {

    // session.close(conn, pstmt, rs);

    }

   

        return node;


    }

}


* 파일명: AddressDAO.java


[첨부(Attachments)]

AddressDAO.zip




15. MVC 프로젝트 구성도


MVC 프로젝트를 구성한 모습이다.



그림 31. MVC Project 구성


그림 31처럼 이런 형태로 구성된다고 보면 되겠다.



16. 맺음글(Conclusion)


글을 다소 길게 쭉 작성했는데, MVC를 좀 더 정확하게 소개하고 싶어서 그런 점 이해하길 바란다.


MVC 패턴의 원리에 대해서 JSP/Servlet을 기반으로 소개하였다.

예를 들면, Spring Frameworks를 먼저 접하기보다는 순수한 부분에 대해서도 생각해봐야 한다고 본다.



* 참고자료(References)


반응형
728x90
300x250

[Spring-Framework] 5. 순정 Maven MVC 웹 프로젝트 - 서블릿, Oracle DB


이번에 소개할 프로젝트는 Maven을 활용하여 Oracle 연동에 대해서 소개하려고 한다.


* 미리 준비해야 할 것: Oracle Database 설치되어 있어야 함.

-> 오라클의 경우에는 오라클 데이터베이스가 설치되어야만, pom.xml에서 <dependency>로 불러올 수가 있음.



[글의 주제]

1. 흥미로운 실험 - Spring Framework가 없는 Maven MVC 웹 프로젝트로 Servlet(서블릿) 구성해보기

2. Oracle Database 연결해보기


글의 주제를 2가지로 설정한 이유는 Spring Framework와 Maven을 동일시하는 경우가 있어서 차이를 알아보기 위해서 작성하게 되었다.


[사용 환경]

1. Oracle Databases 19g (2020-09월 기준: 최신버전)

2. OpenJDK (2020-09월 기준: 최신버전)

3. Apache Tomcat 9

4. SpringToolSuite4 (2020-09월 기준: 최신버전)

5. MS Windows 10



1. MVNRepository가 만능인가?


몇 가지 미지원하는 제품도 존재할 수 있다. 참고하면 도움이 될 것이다.



그림 1) MVNRepository 검색하기


https://mvnrepository.com/


접속하여 "Oracle"이라고 검색한다.

Oracle JDBC 를 클릭한다.

최신버전을 선택해본다.



그림 2) MVNRepository - Oracle JDBC 12.1.0.2


Maven 생성 코드가 나왔다.

해당 코드를 복사, 붙여넣기를 pom.xml에 시도 해본다.



그림 3) pom.xml에 적용했을 때 오류


Multiple problems have occur......

Error reading file - oracle-jdbc-12.1.0.2.jar 파일을 읽어올 수 없다고 에러가 발생한다.


이렇게 에러가 출력되었다면, 정상적으로 코드를 입력한 것이다.

오류가 발생하는 원인으로는 오라클 데이터베이스는 상용 소프트웨어이기 때문이다.



2. 프로젝트에서 Maven -> Add Dependency 기능 활용하기


Maven 플러그인의 Add Dependency 기능으로 적용해보려고 한다.



그림 4) Maven의 프로젝트


작업중인 프로젝트를 클릭한다.

오른쪽 버튼을 누른다.

"Maven"-> "Add Dependency"를 클릭한다.



그림 5) Maven의 프로젝트


oracle을 검색한다.

com.oracle.database.jdbc | ojdbc8을 선택한 후 OK를 누른다.



그림 6) Maven의 프로젝트


자동으로 oracle jar파일이 생성되는 것을 확인할 수 있다.

버전을 자세히 보면, 19.3.0.0이라고 적혀져 있다.

오라클 최신 버전이 컴퓨터 내에 설치되어 있어서, 해당 버전을 인식하여 가져온 것으로 보인다.




3. Maven에서의 Java 코드 생성하기


이전의 프로젝트에 비해서 복잡하게 느껴질 수도 있지만, 큰 차이점은 없다고 보면 되겠다.

먼저 AddressDto라는 클래스를 생성해보려고 한다.



그림 7) Class 생성하기


Java Resources에서 오른쪽 버튼을 누른다.

New 항목에서 Class를 클릭한다.



그림 8) AddressDto.java 파일 만들기


Package명을 간단하게 "mavenWeb.db"로 입력하였다.

Name명은 "AddressDto"라고 입력하였다.

다 입력하였으면, "Finish"를 누른다.



그림 9) 코드를 입력한 모습 - AddressDto.java


크게 어렵지 않게 Jsp 프로그래밍에서의 Java 파일 생성한 방법처럼, 동일한 형태로 사용할 수 있다는 것을 알 수 있다.





4. Maven에서의 Servlet 코드 생성하기


이전의 서블릿 작업은 web.xml에서 수정작업을 추가적으로 해줘야만 했었다.

Maven에서 서블릿(Servlet)을 생성하면, 자동으로 web.xml에 입력된다.



그림 10) Java Resources의 오른쪽 버튼 메뉴 모습


Java Resources를 선택한 후 오른쪽 버튼 클릭하여 New->Servlet을 클릭한다.



그림 11) Create Servlet


Java Package명은 "mavenWeb.view"으로 지정하였다.

Class name명은 "BoardListServlet"으로 지정하였다.

완료되었다면, Finish를 누른다.



그림 12) web.xml 파일


파일경로: src/main/webapp/WEB-INF/web.xml


자동으로 <Servlet>과 <Servlet-Mapping>이 등록된 것을 볼 수 있다.



그림 13) BoardListServlet.java 파일


doGet함수와 doPost 등이 자동 생성된 프로그램을 볼 수 있다.

Run을 하여 "아파치 톰캣 서버"를 동작시킨 후 아래처럼 태스트를 해볼 수 있다.



그림 14) Open Browser에서의 서블릿 동작 확인하기


매우 친숙한 화면에서 동작되는 모습을 확인할 수 있다.




5. Oracle DB - 간단하게 연동시키기(프레임워크 X - 순정 JDBC) [소스코드]


JDBC 기반으로 Maven Servlet 프로젝트 작업을 구현하겠다.



그림 15) 프로젝트 구성하기의 예


작업해줄 영역은 크게 mavenWeb.db, mavenWeb.view, WEB-INF내의 web.xml 파일이 되겠다.


* 이전 게시글(동일하거나 참고하면 되는 게시글):

1. [JSP] 영속프레임워크 MyBatis를 활용한 CRUD 구현 - JSP와 Oracle, https://yyman.tistory.com/1390?category=810693, 2020-09-19 01:31

-> 비교해서 읽어 보기: 현재 게시글에서는 프레임워크 없이 JDBC 처리에 대해서 소개하고 있음.




package mavenWeb.db;


import java.sql.Connection;

import java.sql.DriverManager;

import java.sql.PreparedStatement;

import java.sql.ResultSet;


public class SqlMapSessionFactory {


private static SqlMapSessionFactory factory = new SqlMapSessionFactory();

private SqlMapSessionFactory() {}

public static SqlMapSessionFactory getInstance() {

return factory;

}

public Connection connect() {

Connection conn = null;

try {

Class.forName("oracle.jdbc.driver.OracleDriver");

conn = DriverManager.getConnection("jdbc:oracle:thin:@127.0.0.1:1521:orcl", "사용자명", "비밀번호");

}

catch(Exception ex) {

System.out.println("오류 발생: " + ex);

}

return conn;

}

public void close(Connection conn, PreparedStatement ps, ResultSet rs) {

if ( rs != null ) {

try {

rs.close();

}

catch(Exception ex) {

System.out.println("오류 발생: " + ex);

}

close(conn, ps); // Recursive 구조 응용(재귀 함수)

}

}

public void close(Connection conn, PreparedStatement ps) {

if (ps != null ) {

try {

ps.close();

}

catch(Exception ex) {

System.out.println("오류 발생: " + ex);

}

}

if (conn != null ) {

try {

conn.close();

}

catch(Exception ex) {

System.out.println("오류 발생: " + ex);

}

}

}

}



* 파일명: SqlMapSessionFactory.java


[첨부(Attachments)]

SqlMapSessionFactory.zip


package mavenWeb.db;


import java.sql.Date;


public class AddressDto {


private int num;

private String name;

private String address;

private Date birthdate;

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 getAddress() {

return address;

}

public void setAddress(String address) {

this.address = address;

}

public Date getBirthdate() {

return birthdate;

}

public void setBirthdate(Date birthdate) {

this.birthdate = birthdate;

}


}



* 파일명: AddressDto.java


비고: 이전 프로젝트와 동일함. (MyBatis 게시글과 흡사함)

java.sql.Timestamp에서 java.sql.Date로 변경함.


[첨부(Attachments)]

AddressDto.zip


package mavenWeb.db;


public interface Address {


public AddressDto getAddress(Integer num);

public int updateAddress(AddressDto addressDTO);

public int insertAddress(AddressDto addressDTO); 

public int deleteAddress(Integer num);

}


* 파일명: Address.java (인터페이스)


비고: 이전 프로젝트와 동일함. (MyBatis 게시글과 동일함)


[첨부(Attachments)]

Address.zip


package mavenWeb.db;


public class AddressImpl implements Address {


@Override

public AddressDto getAddress(Integer num) {

AddressDao dao = AddressDao.getInstance();

return dao.selectAddress(num);

}


@Override

public int updateAddress(AddressDto addressDTO) {

AddressDao dao = AddressDao.getInstance();

return dao.updateAddress(addressDTO);

}


@Override

public int insertAddress(AddressDto addressDTO) {

AddressDao dao = AddressDao.getInstance();

return dao.insertAddress(addressDTO);

}


@Override

public int deleteAddress(Integer num) {

AddressDao dao = AddressDao.getInstance();

return dao.deleteAddress(num);

}


}



* 파일명: AddressImpl.java


비고: 이전 프로젝트와 동일함. (MyBatis 게시글과 동일함)


[첨부(Attachments)]

AddressImpl.zip


package mavenWeb.db;


import java.sql.Connection;

import java.sql.PreparedStatement;

import java.sql.ResultSet;

import java.text.SimpleDateFormat;

import java.util.Calendar;


public class AddressDao {

private AddressDao() {}

    private static AddressDao dao;

    private static SqlMapSessionFactory session; 


    public static AddressDao getInstance(){


        if(dao == null){

            dao = new AddressDao();

            session = SqlMapSessionFactory.getInstance();

        }


        return dao;

    }

    


    public AddressDto selectAddress(Integer num) {


    Connection conn = null;

    PreparedStatement pstmt = null;

    ResultSet rs = null;

   

    AddressDto node = new AddressDto();

   

    String sql = "select NUM, NAME, ADDRESS, BIRTHDATE " +

      " from addressbook" + 

      " where num=?";

    System.out.println(sql);

   

    // 달력 날짜 출력 버그 개선

   

    try {

    conn = session.connect();

    pstmt = conn.prepareStatement(sql);

    pstmt.setInt(1, num);

   

    rs = pstmt.executeQuery();

   

    if ( rs.next() ) {

    node.setNum(rs.getInt(1));

    node.setName(rs.getNString(2));

    node.setAddress(rs.getNString(3));

    node.setBirthdate(rs.getDate(4));

    }

   

   

    }catch(Exception ex) {

    System.out.println("오류 발생: " + ex);

    }

    finally {

    session.close(conn, pstmt, rs);

    }

   

        return node;


    }

    

    public int updateAddress(AddressDto addressDTO) {


    Connection conn = null;

    PreparedStatement pstmt = null;

    int result = -1;

   

    String sql = "update addressbook set NAME = ?, ADDRESS = ?, BIRTHDATE = ? " + 

      " where num = ?";

    try {

   

    System.out.println(addressDTO.getBirthdate());

   

    conn = session.connect();

    pstmt = conn.prepareStatement(sql);

    pstmt.setString(1, addressDTO.getName());

    pstmt.setString(2, addressDTO.getAddress());

    pstmt.setDate(3, addressDTO.getBirthdate());

    pstmt.setInt(4,  addressDTO.getNum());

   

    result = pstmt.executeUpdate();

   

   

    }catch(Exception ex) {

    System.out.println("오류 발생: " + ex);

    }

    finally {

    session.close(conn, pstmt);

    }

   

    return result;

   

    }


    public int insertAddress(AddressDto addressDTO) {

   

    Connection conn = null;

    PreparedStatement pstmt = null;

    int result = -1;

   

    String sql = "insert into addressbook (NAME, ADDRESS, BIRTHDATE) " + 

      " values(?,?,?)";

    try {

   

    System.out.println(addressDTO.getBirthdate());

   

    conn = session.connect();

    pstmt = conn.prepareStatement(sql);

    pstmt.setString(1, addressDTO.getName());

    pstmt.setString(2, addressDTO.getAddress());

    pstmt.setDate(3, addressDTO.getBirthdate());

   

    result = pstmt.executeUpdate();

   

   

    }catch(Exception ex) {

    System.out.println("오류 발생: " + ex);

    }

    finally {

    session.close(conn, pstmt);

    }

   

    return result;

    }

    

    public int deleteAddress(Integer num) {

   

    Connection conn = null;

    PreparedStatement pstmt = null;

    int result = -1;

   

    String sql = "delete from addressbook " + 

      " where num = ?";

    try {

   

    conn = session.connect();

    pstmt = conn.prepareStatement(sql);

    pstmt.setInt(1, num);

   

    result = pstmt.executeUpdate();

   

   

    }catch(Exception ex) {

    System.out.println("오류 발생: " + ex);

    }

    finally {

    session.close(conn, pstmt);

    }

   

    return result;

    }


    

}



* 파일명: AddressDao.java


비고: 


[첨부(Attachments)]

AddressDao.zip





6. 서블릿 뷰 - [소스코드]


web.xml을 살짝만 수정해주면 된다. 크게 많이 수정할 필요가 없다.

이유는 자동생성되기 때문이다.


<?xml version="1.0" encoding="UTF-8"?>


<web-app 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"

version="3.1">

  <display-name>Archetype Created Web Application</display-name>

  

  

<!-- Subject: web.xml     -->

<!-- Filename: web.xml     -->

<!-- Created Date: 2020-09-19     -->

<!-- * Description:     --> 

<!-- 1. Maven 기반의 Servlet 실험(2020-09-20) --> 

  

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

  <!-- Board Servlet 자동생성됨 -->

  <servlet>

  <servlet-name>BoardListServlet</servlet-name>

  <servlet-class>mavenWeb.view.BoardListServlet</servlet-class>

  </servlet>

  <servlet>

  <servlet-name>BoardInsertServlet</servlet-name>

  <servlet-class>mavenWeb.view.BoardInsertServlet</servlet-class>

  </servlet>

  <servlet>

  <servlet-name>BoardDeleteServlet</servlet-name>

  <servlet-class>mavenWeb.view.BoardDeleteServlet</servlet-class>

  </servlet>

  <servlet>

  <servlet-name>BoardUpdateServlet</servlet-name>

  <servlet-class>mavenWeb.view.BoardUpdateServlet</servlet-class>

  </servlet>

  <servlet-mapping>

  <servlet-name>BoardListServlet</servlet-name>

  <url-pattern>/board/list.do</url-pattern>

  </servlet-mapping>

  <servlet-mapping>

  <servlet-name>BoardInsertServlet</servlet-name>

  <url-pattern>/board/insert.do</url-pattern>

  </servlet-mapping>

  <servlet-mapping>

  <servlet-name>BoardDeleteServlet</servlet-name>

  <url-pattern>/board/delete.do</url-pattern>

  </servlet-mapping>

  <servlet-mapping>

  <servlet-name>BoardUpdateServlet</servlet-name>

  <url-pattern>/board/update.do</url-pattern>

  </servlet-mapping>


</web-app>


* 파일명: web.xml


[첨부(Attachments)]

web.zip


package mavenWeb.view;


import java.io.IOException;

import java.io.PrintWriter;


import javax.servlet.ServletException;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;


import mavenWeb.db.AddressDto;

import mavenWeb.db.AddressImpl;


/**

 * Servlet implementation class BoardDeleteServlet

 */

public class BoardDeleteServlet extends HttpServlet {

private static final long serialVersionUID = 1L;

       

    /**

     * @see HttpServlet#HttpServlet()

     */

    public BoardDeleteServlet() {

        super();

    }


/**

* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)

*/

protected void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {


res.setContentType("text/html;charset=UTF-8");

PrintWriter out = res.getWriter();

out.print("<br/>");

AddressImpl address = new AddressImpl();

int result = address.deleteAddress(5);

AddressDto addressDto = address.getAddress(3);

out.println("<html><head><title>CRUD - Delete(Maven)</title></head>");

out.println("<body><h2>MyBatis - Delete(Maven)</h2>");

out.print("<br/>");

out.print("삭제여부:" + result + "</br>");

out.print("<br/>");

if ( addressDto != null ) {

out.print(addressDto.getNum() + "/" + addressDto.getName() + "/");

out.print(addressDto.getAddress() + "/" + addressDto.getBirthdate());

}

out.println("</body></html>");

out.close();

}


/**

* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)

*/

protected void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {

doGet(req, res);

}


}



* 파일명: BoardDeleteServlet.java


[첨부(Attachments)]

BoardDeleteServlet.zip


package mavenWeb.view;


import java.io.IOException;

import java.io.PrintWriter;

import java.sql.Date;

import java.text.SimpleDateFormat;


import javax.servlet.ServletException;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;


import mavenWeb.db.AddressDto;

import mavenWeb.db.AddressImpl;


/**

 * Servlet implementation class BoardInsertServlet

 */

public class BoardInsertServlet extends HttpServlet {

private static final long serialVersionUID = 1L;

       

    /**

     * @see HttpServlet#HttpServlet()

     */

    public BoardInsertServlet() {

        super();

    }


/**

* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)

*/

protected void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {

res.setContentType("text/html;charset=UTF-8");

PrintWriter out = res.getWriter();

out.print("<br/>");

AddressImpl address = new AddressImpl();

AddressDto dbNode = new AddressDto(); 

dbNode.setName("도도" + serialVersionUID);

dbNode.setAddress("행복시 행복동");

// 버그1: new Date() 사용안됨. (2020을 3920으로 인식함.) 

// 버그2: new Timestamp() 사용안됨. (2020을 3920으로 인식함.) 

String userDate = "2020-02-01";

java.sql.Date sqlDate = java.sql.Date.valueOf(userDate);

dbNode.setBirthdate(sqlDate);

int result = address.insertAddress(dbNode);

AddressDto addressDto = address.getAddress(1);

out.println("<html><head><title>CRUD - Insert(Maven)</title></head>");

out.println("<body><h2>MyBatis - Insert</h2>");


SimpleDateFormat format1 = new SimpleDateFormat ( "yyyy-MM-dd" );

String birthdate = format1.format(addressDto.getBirthdate());

out.print("<br/>");

out.print("등록여부:" + result + "</br>");

out.print("<br/>");

out.print(addressDto.getNum() + "/" + addressDto.getName() + "/");

out.print(addressDto.getAddress() + "/" + birthdate);

out.println("</body></html>");

out.close();

}


/**

* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)

*/

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

// TODO Auto-generated method stub

doGet(request, response);

}


}



* 파일명: BoardInsertServlet.java


[첨부(Attachments)]

BoardInsertServlet.zip


package mavenWeb.view;


import java.io.IOException;

import java.io.PrintWriter;

import java.text.SimpleDateFormat;


import javax.servlet.ServletException;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;


import mavenWeb.db.AddressDto;

import mavenWeb.db.AddressImpl;


/**

 * Servlet implementation class BoardListServlet

 */

public class BoardListServlet extends HttpServlet {

private static final long serialVersionUID = 1L;

       

    /**

     * @see HttpServlet#HttpServlet()

     */

    public BoardListServlet() {

        super();

    }


/**

* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)

*/

protected void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {

res.setContentType("text/html;charset=UTF-8");

PrintWriter out = res.getWriter();

out.print("<br/>");

AddressImpl address = new AddressImpl();

AddressDto addressDto = address.getAddress(16);

out.println("<html><head><title>CRUD - List(Maven)</title></head>");

out.println("<body><h2>MyBatis - List</h2>");

SimpleDateFormat format1 = new SimpleDateFormat ( "yyyy-MM-dd" );

String birthdate = format1.format(addressDto.getBirthdate());

out.print(addressDto.getNum() + "/" + addressDto.getName() + "/");

out.print(addressDto.getAddress() + "/" + birthdate);

out.print("<br/>");

out.println("</body></html>");

out.close();

}


/**

* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)

*/

protected void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {

doGet(req, res);

}


}



* 파일명: BoardListServlet.java


[첨부(Attachments)]

BoardListServlet.zip


package mavenWeb.view;


import java.io.IOException;

import java.io.PrintWriter;


import javax.servlet.ServletException;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;


import mavenWeb.db.AddressDto;

import mavenWeb.db.AddressImpl;


/**

 * Servlet implementation class BoardUpdateServlet

 */

public class BoardUpdateServlet extends HttpServlet {

private static final long serialVersionUID = 1L;

       

    /**

     * @see HttpServlet#HttpServlet()

     */

    public BoardUpdateServlet() {

        super();

    }


/**

* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)

*/

protected void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {


res.setContentType("text/html;charset=UTF-8");

PrintWriter out = res.getWriter();

out.print("<br/>");

AddressImpl address = new AddressImpl();

AddressDto dbNode = new AddressDto();

dbNode.setNum(3);

dbNode.setName("도도수정" + serialVersionUID);

dbNode.setAddress("행복시 행복동");


// 버그1: new Date() 사용안됨. (2020을 3920으로 인식함.) 

// 버그2: new Timestamp() 사용안됨. (2020을 3920으로 인식함.)

String userDate = "2020-07-01";

java.sql.Date sqlDate = java.sql.Date.valueOf(userDate);

dbNode.setBirthdate(sqlDate);

int result = address.updateAddress(dbNode);

AddressDto addressDto = address.getAddress(3);

out.println("<html><head><title>CRUD - Update(Maven)</title></head>");

out.println("<body><h2>MyBatis - Update(Maven)</h2>");

out.print("<br/>");

out.print("수정여부:" + result + "</br>");

out.print("<br/>");

out.print(addressDto.getNum() + "/" + addressDto.getName() + "/");

out.print(addressDto.getAddress() + "/" + addressDto.getBirthdate());

out.println("</body></html>");

out.close();

}


/**

* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)

*/

protected void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {

doGet(req, res);

}


}



* 파일명: BoardUpdateServlet.java


[첨부(Attachments)]

BoardUpdateServlet.zip




7. 데이터베이스 설계


예제 데이터베이스를 설계하도록 하겠다. 역설계에 대해서도 생각해보면, 흥미로운 주제가 될 것으로 보인다.


tableName(테이블명): addressbook


 키

 항목명

 속성 

 PK(기본키)

num

인덱스(ID)

 

name

nvarchar

 

address

nvarchar

 

birthdate

date




그림 16) 데이터베이스 테이블 - 설계



8. 결론(Conclusion)


순정 Maven MVC의 사용방법은 JSP/Servlet하고 동일하거나 큰 차이가 없다는 점을 알 수 있었다.

Spring-Framework의 Maven을 사용할 때 기본 원리를 이해하는 데 도움될 수 있을 거 같다.


* 소스코드: 동작 태스트 완료하였음.


Maven을 사용하면, 편해지는 부분이 정말 많아진다.



* 참고자료(Reference)


1. 자바 오라클 연동 데이터 삽입,수정,조회,삭제-1, https://ngg3319.tistory.com/76, Accessed by 2020-09-20, Last Modified 2018-03-12 16:17

2. 자바 오라클 연동 데이터 삽입,수정,조회,삭제-2, https://ngg3319.tistory.com/79, Accessed by 2020-09-20, Last Modified 2018-03-13 22:02

-> 추천(40점): 의외로 쉽게 잘 작성되어 있음.

-> 참고 부분: sqlDate 에 대해서 처리하는 방법 참고함. (String 문자로 java.sql.Date.valueOf()의 아이디어를 얻었음.)


3. maven 이용 spring MVC project 생성 :: Copy Coding, https://copycoding.tistory.com/178, Accessed by 2020-09-20, Last Modified 2019-05-03 12:27

-> 추천(70점): 순수한 Maven 프로젝트에 대해서 잘 설명되어 있음.


반응형
728x90
300x250

[Spring-Framework] 4. Eclipse와 Maven MVC 웹 프로젝트 - 생성하기


이번에 소개할 글은 Apache Maven 프로젝트(이하 "메이븐" 또는 "Maven")을 활용하여 Maven 기반의 MVC 프로젝트를 생성하도록 하겠다.

Spring-Framework를 이해하기 전에 경험해보면 도움이 될 것이라고 생각한다.


적용 대상: Eclipse 최신 버전(또는 Spring Tool Suite-4 이상)




1. 프로젝트 생성하기


프로젝트 생성부터 간단하면서도 알기 쉽게 작성하였다.



그림 1. Project 생성하기


File에서 New->Project...을 클릭한다.




그림 2. Project 생성하기


Use Default Workspace location을 체크한 후 Next를 누른다.



그림 3. Project 생성하기


org.apache.maven.archietypes    |   maven-archietype-webapp   |   1.4


해당 카탈로그를 선택한 후 Next를 누른다.



그림 4. Project 생성하기


아래 그림 3처럼 여러가지 값을 적는 창이 나타난다.

Group Id는 프로젝트를 진행하는 회사나 팀의 도메인 이름을 거꾸로 적는다.

Artifact Id는 해당 프로젝트의 이름을 적는다.

package는 위 두가지가 조합된 이름으로 나온다.


작성을 완료하였으면, Finish를 누른다.



그림 5. Project 생성하기


프로젝트 생성이 된 것을 확인할 수 있다.

Problems 창에 보면, Servlet 오류가 있는 것을 확인할 수 있다.

정상적으로 프로젝트가 생성된 것이다.



2. Maven 프로젝트에서의 Servlet-api.jar 파일에 대한 것(pom.xml 이해)


maven을 사용하면, 귀찮게 servlet-api.jar 파일을 따로 복사, 붙여넣기를 할 필요가 없다.



그림 6. 이전 스타일 - Maven 프로젝트를 사용하지 않은 경우


Apache Maven 프로젝트는 POM.xml 기반으로 동작한다.

따로 servlet-api.jar를 이전의 "WebContents\Web-inf\lib에 복사, 붙여넣기"를 안 해도 된다.




3. Maven 프로젝트에서의 Servlet-api.jar 파일에 대한 것(pom.xml 구현)


pom.xml 파일을 편집하여 servlet-api.jar를 자동으로 생성하는 방법에 대해서 소개하겠다.



그림 7. pom.xml - eclipse


pom.xml을 더블클릭한다.


<dependencies>~</dependencies> 내에는 <dependency>가 정의되어 있는 것을 살펴볼 수 있다.
(글로만 보면, 조금 어려우니 그림을 가지고 소개함.)


    <dependency>

<groupId>javax.servlet</groupId>

<artifactId>javax.servlet-api</artifactId>

<version>3.1.0</version>

<scope>provided</scope>

</dependency>


</dependency> 뒤에 위의 내용을 입력해준다.



그림 8. pom.xml - eclipse


pom.xml에 명령어를 입력함으로서 잠시 기다리면, javax-servlet-api-3.1.0.jar 파일이 자동으로 생성되는 것을 확인할 수 있다.

그리고 Problems 내에 발생했던 javax.servlet Error도 함께 사라지는 것을 확인할 수 있다.


참고: SSD 이상의 빠른 저장매체로 작업한다면, 빠르게 변화하는 모습을 확인할 수 있음.





4. Maven 프로젝트 - Hello World 실행하기


Maven 프로젝트를 Apache Tomcat 9으로 실행하도록 하겠다.



그림 9. Apache Tomcat 9으로 개발환경에서 모의 태스트 하기


"Run As..."를 누른다.




그림 10. Apache Tomcat 9으로 개발환경에서 모의 태스트 하기


Run on Server를 선택한 후 OK를 누른다.



그림 11. Apache Tomcat 9으로 개발환경에서 모의 태스트 하기


Tomcat 서버 셋팅을 한 후 Finish를 누른다.


비고: 이미 환경 셋팅이 된 모습이다. Tomcat v9.0 Server at localhost가 안 보인다면 환경설정을 따로 해야 한다.




그림 12. Apache Tomcat 9으로 개발환경에서 모의 태스트 하기


Finish를 누른다.



그림 13. Apache Tomcat 9으로 개발환경에서 모의 태스트 하기


Maven 기반으로 완성된 홈페이지를 살펴볼 수 있다.




5. Maven Project의 pom.xml 설정이 만능인가?


앞서 servlet-api.jar에 대해서 간단한 설정으로 자동생성이 된다고 소개하였다.

pom.xml 설정으로 모든 것을 다 처리할 수 있을 정도인지 언급해보려고 한다.


결론은 아니다.



그림 14. pom.xml 설정에서의 오류


pom.xml 설정을 하였는데, 운이 안 좋으면 jar파일을 못 찾을 수도 있다.

물론 36줄~40줄의 내용이 완벽한 것은 절대 아니다.


이 부분에 대해서는 추가적으로 소개하겠다.




6. Maven Project의 pom.xml 설정에 대한 정보찾기 


그림 14에서의 잘못된 pom.xml 설정의 문제에 대해서 잠깐 소개하였다.

구체적으로 Maven Project에서 지원하는 Repository가 무엇인지, 버전은 어떻게 되는지 각종 정보에 대해서 알 수 있는 사이트를 소개하겠다.


https://mvnrepository.com/


이 사이트를 모르면, 초기에 환경설정 작업을 하는 데 많이 힘들 것으로 보인다.



그림 15. mvnpepository.com (2020-09-19)


그림 15 사이트에 접속해서 검색해서 사용하고자 하는 버전, pom에서 지원하는지 등을 쉽게 살펴볼 수 있다.



그림 16. mvnrepository.com의 mysql 검색 결과 (2020-09-19)


MySQL Connector/J를 클릭한다.



그림 17. mvnrepository.com의 mysql 세부 결과 (2020-09-19)


세부적으로 지원하는 버전에 대해서 소개하고 있다.



그림 18. 버전을 클릭하여 pom에서 사용하는 코드 생성


Maven에 적용할 수 있는 코드가 출력되는 것을 확인할 수 있다.

그림 14의 오류 문제가 해결되는지 한번 적용해보겠다.



그림 19. 이상없이 적용된 mysql-connecotr-java-8.xx버전 - Maven MVC


<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->

<dependency>

    <groupId>mysql</groupId>

    <artifactId>mysql-connector-java</artifactId>

    <version>8.0.21</version>

</dependency>


정상적으로 동작하는 모습을 살펴볼 수 있다.



비고: MyBatis부터 다양한 Library를 예를 들면, 간단한 명령어로 연결시킬 수가 있음.




7. 결론(Conclusion)


pom.xml을 제대로 적용해주면, 많은 문제를 쉽고 간단하게 해결할 수 있다고 본다.

Maven MVC 웹 프로젝트 입문에 대해서 소개하였다.


JSP/Servlet을 경험한 사용자들을 위한 글을 한번 추가로 연재해보겠다.



* 참고 자료(References)


1. Maven Repository: mysql » mysql-connector-java » 8.0.21, https://mvnrepository.com/artifact/mysql/mysql-connector-java/8.0.21, Accessed by 2020-09-20, Last Modified 2020-07-12.

2. Spring MVC Example for User Registration and Login - DZone Web Dev, https://dzone.com/articles/spring-mvc-example-for-user-registration-and-login-1, Accessed by 2020-09-20, Last Modified 2017-03-05.

3. Maven Repository: Search/Browse/Explore, https://mvnrepository.com/ , Accessed by 2020-09-20, Last Modified 2020-09-20.

반응형

+ Recent posts