728x90
300x250

[Spring-Framework] 11. Spring MVC - HikariCP 3.4.2, Oracle 19g 연동하기(Properties, Java) - (2)


1부에서는 환경설정하는 방법에 대해서 소개하였다.

2부에서는 코드로 구현하는 방법을 위주로 소개하겠다.


[1부] [Spring-Framework] 10. Spring MVC - HikariCP 3.4.2, Oracle 19g 연동하기(Properties, Java) - (1), 2020-09-23 14:20

https://yyman.tistory.com/1410



10. Properties 방식 - DataSource.java


코드를 하나 만들어보았다.


패키지: com.springMVC.web.persistance


package com.springMVC.web.persistance;


import java.io.IOException;

import java.io.InputStream;

import java.io.Reader;

import java.util.Properties;


import java.sql.Connection;

import java.sql.SQLException;


import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.springframework.beans.factory.annotation.Value;


import com.zaxxer.hikari.HikariConfig;

import com.zaxxer.hikari.HikariDataSource;


public class DataSource {


private static final Logger logger = LoggerFactory.getLogger(DataSource.class);


    private static String CLASSNAME;

    private static String JDBC_URL;

    private static String USERNAME;

    private static String PASSWORD;

    private static String CACHE_PREP_STMTS;

    private static HikariDataSource ds;

    

/*

(자바 방식)

    private static HikariConfig config = new HikariConfig();

    

    static {

    config.setDriverClassName("oracle.jdbc.OracleDriver");

        config.setJdbcUrl( "jdbc:oracle:thin:@localhost:1521:orcl" );

        config.setUsername( "사용자계정명" );

        config.setPassword( "비밀번호" );

        

        config.addDataSourceProperty( "cachePrepStmts" , "true" );

        config.addDataSourceProperty( "prepStmtCacheSize" , "250" );

        config.addDataSourceProperty( "prepStmtCacheSqlLimit" , "2048" );

        ds = new HikariDataSource( config );

    }

    */

    

    private HikariConfig config;

    

    public DataSource() {

   

    InputStream inputStream;

    config = new HikariConfig();

   

    String resource = "db.properties";

        Properties properties = new Properties();

        

        try {

        inputStream = getClass().getClassLoader().getResourceAsStream(resource);

            properties.load(inputStream);

            System.out.println(properties.getProperty("jdbcUrl"));

            System.out.println(properties.getProperty("dataSourceClassName"));

            

            

            CLASSNAME = properties.getProperty("dataSourceClassName");

            JDBC_URL = properties.getProperty("jdbcUrl");

            USERNAME = properties.getProperty("dataSource.user");

            PASSWORD = properties.getProperty("dataSource.password");

            

            CACHE_PREP_STMTS = properties.getProperty("cachePrepStmts");


            config.setDriverClassName(CLASSNAME);

            config.setJdbcUrl( JDBC_URL );

            config.setUsername( USERNAME );

            config.setPassword( PASSWORD );

            

            config.addDataSourceProperty( "cachePrepStmts" , CACHE_PREP_STMTS );

            config.addDataSourceProperty( "prepStmtCacheSize" , "250" );

            config.addDataSourceProperty( "prepStmtCacheSqlLimit" , "2048" );

            

            ds = new HikariDataSource( config );

            

        } catch (IOException e) {

            e.printStackTrace();

        }


    }


    public Connection getConnection() throws SQLException {


        return ds.getConnection();

    }


}


파일명: DataSource.java


[첨부(Attachments)]

DataSource-java-type-properties.zip


위의 소스를 static 방식으로 간결하게 코드를 변경할 수 없는 이유는 "getClass().getClassLoader().getResourceAsStream(resource);" 이 부분이 static 변수에서는 처리가 되지 않는다.


비고: 클래스명에 대해서 "DataSource"로 해도 되나요?

       javax.sql.DataSource가 존재한다. 예제의 DataSource 클래스명은 좋은 명칭은 아니다. 

       (동작은 될 수 있겠으나 javax.sql.DataSource를 사용할 때는 명칭에 대해서 다시 생각을 해봐야 할 것이다.)



10-1. Controller - HomeController.java 수정하기(Properties 방식)


HomeController.java 파일로 작업하는 방법이다.


package com.springMVC.web.controller;


import java.text.DateFormat;

import java.util.Date;

import java.util.Locale;


import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.springframework.stereotype.Controller;

import org.springframework.ui.Model;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RequestMethod;


import com.springMVC.web.dao.AddressBookDao;

import com.springMVC.web.persistance.DataSource;


/**

 * Handles requests for the application home page.

 */

@Controller

public class HomeController {

/*

// Controller 안에서만 사용가능.

@Value("#{props['dataSourceClassName']}")

private String CLASSNAME;

@Value("#{props['jdbcUrl']}")

private String JDBC_URL;

@Value("#{props['dataSource.user']}")

private String USERNAME;

@Value("#{props['dataSource.password']}")

private String PASSWORD;

*/

private static final Logger logger = LoggerFactory.getLogger(HomeController.class);

// @Value("#{props['jdbcUrl']}")

// private String url;

/**

* Simply selects the home view to render by returning its name.

*/

@RequestMapping(value = "/", method = RequestMethod.GET)

public String home(Locale locale, Model model) {

logger.info("Welcome home! The client locale is {}.", locale);

Date date = new Date();

DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, locale);

String formattedDate = dateFormat.format(date);

try {

DataSource ds = new DataSource();

//ds.getConnection();

AddressBookDao dao = new AddressBookDao();

dao.allSelect();

//logger.info("URL:{}", JDBC_URL);

//dao.allSelect();

}

catch(Exception e) {

logger.info("msg: {}", e.getMessage());

}

model.addAttribute("serverTime", formattedDate );

return "home";

}

}


파일명: HomeController.java


[첨부(Attachments)]

HomeController-java-type-properties.zip




10-2. DAO - AddressBookDao.java (Properties 방식)


package com.springMVC.web.dao;


import java.sql.Connection;

import java.sql.PreparedStatement;

import java.sql.ResultSet;

import java.sql.SQLException;


import org.slf4j.Logger;

import org.slf4j.LoggerFactory;


import com.springMVC.web.persistance.DataSource;


public class AddressBookDao {


private static final Logger logger = LoggerFactory.getLogger(AddressBookDao.class);


public void allSelect() {

try {

DataSource ds = new DataSource();

Connection conn = ds.getConnection();

String query = "select * from addressbook";

PreparedStatement pstmt = conn.prepareStatement(query);

ResultSet rs = pstmt.executeQuery();

while(rs.next()) {


String msg = "번호:" + rs.getString("num") + "/이름:" + rs.getString("name") + "/주소:" + rs.getString("address");

logger.info("Msg: {}.", msg);

}

rs.close();

conn.close();

} catch (SQLException e) {

logger.info("msg:{}",  e.getMessage());

}

}

}



파일명: AddressBookDao.java


[첨부(Attachments)]

AddressBookDao-type-properties.zip




11. Java 방식 - DataSource.java


앞에 Properties 방식으로 구성해봐도 되고, 자바 코드 방식으로 해도 무방하다.


package com.springMVC.web.persistance;


import java.io.IOException;

import java.io.InputStream;

import java.io.Reader;

import java.util.Properties;


import java.sql.Connection;

import java.sql.SQLException;


import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.springframework.beans.factory.annotation.Value;


import com.zaxxer.hikari.HikariConfig;

import com.zaxxer.hikari.HikariDataSource;


public class DataSource {


private static final Logger logger = LoggerFactory.getLogger(DataSource.class);


    private static String CLASSNAME;

    private static String JDBC_URL;

    private static String USERNAME;

    private static String PASSWORD;

    private static String CACHE_PREP_STMTS;

    private static HikariDataSource ds;

    

    private static HikariConfig config = new HikariConfig();

    

    static {

    config.setDriverClassName("oracle.jdbc.OracleDriver");

        config.setJdbcUrl( "jdbc:oracle:thin:@localhost:1521:orcl" );

        config.setUsername( "사용자계정명" );

        config.setPassword( "비밀번호" );

        

        config.addDataSourceProperty( "cachePrepStmts" , "true" );

        config.addDataSourceProperty( "prepStmtCacheSize" , "250" );

        config.addDataSourceProperty( "prepStmtCacheSqlLimit" , "2048" );

        ds = new HikariDataSource( config );

    }

    

    /*

    private HikariConfig config;

    

    public DataSource() {

   

    InputStream inputStream;

    config = new HikariConfig();

   

    String resource = "db.properties";

        Properties properties = new Properties();

        

        try {

        inputStream = getClass().getClassLoader().getResourceAsStream(resource);

            properties.load(inputStream);

            System.out.println(properties.getProperty("jdbcUrl"));

            System.out.println(properties.getProperty("dataSourceClassName"));

            

            

            CLASSNAME = properties.getProperty("dataSourceClassName");

            JDBC_URL = properties.getProperty("jdbcUrl");

            USERNAME = properties.getProperty("dataSource.user");

            PASSWORD = properties.getProperty("dataSource.password");

            

            CACHE_PREP_STMTS = properties.getProperty("cachePrepStmts");


            config.setDriverClassName(CLASSNAME);

            config.setJdbcUrl( JDBC_URL );

            config.setUsername( USERNAME );

            config.setPassword( PASSWORD );

            

            config.addDataSourceProperty( "cachePrepStmts" , CACHE_PREP_STMTS );

            config.addDataSourceProperty( "prepStmtCacheSize" , "250" );

            config.addDataSourceProperty( "prepStmtCacheSqlLimit" , "2048" );

            

            ds = new HikariDataSource( config );

            

        } catch (IOException e) {

            e.printStackTrace();

        }


    }

    

    

    */


    public static Connection getConnection() throws SQLException {


        return ds.getConnection();

    }

}


파일명: DataSource.java


[첨부(Attachments)]

DataSource-java-type-java.zip




11-1. Controller - HomeController.java 수정하기(Java 방식)


HomeController.java 파일로 작업하는 방법이다.


package com.springMVC.web.controller;


import java.text.DateFormat;

import java.util.Date;

import java.util.Locale;


import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.springframework.stereotype.Controller;

import org.springframework.ui.Model;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RequestMethod;


import com.springMVC.web.dao.AddressBookDao;

import com.springMVC.web.persistance.DataSource;


/**

 * Handles requests for the application home page.

 */

@Controller

public class HomeController {

/*

// Controller 안에서만 사용가능.

@Value("#{props['dataSourceClassName']}")

private String CLASSNAME;

@Value("#{props['jdbcUrl']}")

private String JDBC_URL;

@Value("#{props['dataSource.user']}")

private String USERNAME;

@Value("#{props['dataSource.password']}")

private String PASSWORD;

*/

private static final Logger logger = LoggerFactory.getLogger(HomeController.class);

// @Value("#{props['jdbcUrl']}")

// private String url;

/**

* Simply selects the home view to render by returning its name.

*/

@RequestMapping(value = "/", method = RequestMethod.GET)

public String home(Locale locale, Model model) {

logger.info("Welcome home! The client locale is {}.", locale);

Date date = new Date();

DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, locale);

String formattedDate = dateFormat.format(date);

try {

//ds.getConnection();

AddressBookDao dao = new AddressBookDao();

dao.allSelect();

//logger.info("URL:{}", JDBC_URL);

//dao.allSelect();

}

catch(Exception e) {

logger.info("msg: {}", e.getMessage());

}

model.addAttribute("serverTime", formattedDate );

return "home";

}

}


파일명: HomeController.java


[첨부(Attachments)]

HomeController-java-type-java.zip





11-2. DAO - AddressBookDao.java (JAVA 방식)


자바 방식으로 dao를 구성하는 방법이다.


package com.springMVC.web.dao;


import java.sql.Connection;

import java.sql.PreparedStatement;

import java.sql.ResultSet;

import java.sql.SQLException;


import org.slf4j.Logger;

import org.slf4j.LoggerFactory;


import com.springMVC.web.persistance.DataSource;


public class AddressBookDao {


private static final Logger logger = LoggerFactory.getLogger(AddressBookDao.class);


public void allSelect() {

try {

Connection conn = DataSource.getConnection();

String query = "select * from addressbook";

PreparedStatement pstmt = conn.prepareStatement(query);

ResultSet rs = pstmt.executeQuery();

while(rs.next()) {


String msg = "번호:" + rs.getString("num") + "/이름:" + rs.getString("name") + "/주소:" + rs.getString("address");

logger.info("Msg: {}.", msg);

}

rs.close();

conn.close();

} catch (SQLException e) {

logger.info("msg:{}",  e.getMessage());

}

}

}



파일명: AddressBookDao.java


[첨부(Attachments)]

AddressBookDao.java-Type-java.zip



12. 출력 결과


작업한 데이터베이스의 모습이다.

작업한 결과를 보면, 무슨 작업을 하려고 했는지 직관적으로 이해될 것으로 보인다.

DB를 처리하거나 호출하는 건 똑같은데, 호출할 때 미리 저장된 풀을 활용하여 부담을 줄여주는 효과가 있다.



그림 11. Oracle DB - SQL Developer 모습(Addressbook)



그림 12. Oracle DB - SQL Developer 모습(Addressbook)



그림 13. 화면 출력 결과 - STS4(Eclipse)



* 맺음글(Conclusion)


시중의 HikariCP에 대한 글이 오류가 많아서 한번 정확하게 최신 버전으로 작성해보고 싶었다.

수차례 태스트 작업을 완료하였으니 사용하는 데 지장없을 것으로 보인다.


공식 사이트: https://github.com/brettwooldridge/HikariCP

-> 공식 사이트의 메뉴얼이 다소 부족한 면이 있다.



* 참고자료(Reference)


1. [Spring] 커넥션 풀(Connection pool)이란?, https://linked2ev.github.io/spring/2019/08/14/Spring-3-%EC%BB%A4%EB%84%A5%EC%85%98-%ED%92%80%EC%9D%B4%EB%9E%80/ , Accessed by 2020-09-23, Last Modified 2019-08-14.

2. Spring-Hikari-Oracle연동 시 나는 oracle.jdbc.driver.OracleDriver not found 에러, https://apiclass.tistory.com/entry/Spring-Hikari-Oracle%EC%97%B0%EB%8F%99-%EC%8B%9C-%EB%82%98%EB%8A%94-oraclejdbcdriverOracleDriver-not-found-%EC%97%90%EB%9F%AC, Accessed by 2020-09-23, Last Modified 2019-10-16.

3. Introduction to HikariCP, https://www.baeldung.com/hikaricp, Accessed by 2020-09-23, Last Modified 2020-06-02.

4. Maven Repository: mysql » mysql-connector-java » 8.0.21, https://mvnrepository.com/artifact/mysql/mysql-connector-java/8.0.21, Accessed by 2020-09-23, Last Modified .

5. GitHub - brettwooldridge/HikariCP: 光 HikariCP・A solid, high-performance, JDBC connection pool at last., https://github.com/brettwooldridge/HikariCP, Accessed by 2020-09-23, Last Modified .

6. [Spring][04]커넥션 풀 설정(HikariCP), https://kimvampa.tistory.com/57, Accessed by 2020-09-23, Last Modified 2020-04-10.

7. [Spring] Spring Test 오류 해결 모음(SpringJUnit4ClassRunner , Resource specification), https://life-with-coding.tistory.com/373, Accessed by 2020-09-23, Last Modified 2020-07-08.

8. [오류, 에러] Spring Junit Test 환경설정 / Class<SpringJUnit4ClassRunner> cannot be resolved to a type, https://developerntraveler.tistory.com/1, Accessed by 2020-09-23, Last Modified 2020-05-14.

9. 오라클 드라이버 에러 - Registered driver with driverClassName=oracle.jdbc.driver.OracleDriver was not found, trying direct instantiation, https://wrkbr.tistory.com/410, Accessed by 2020-09-23, Last Modified 2018.

10. SpringBoot error: Registered driver with driverClassName=oracle.jdbc.driver.OracleDriver was not found, trying direct instantiation, https://stackoverflow.com/questions/52014595/springboot-error-registered-driver-with-driverclassname-oracle-jdbc-driver-orac, Accessed by 2020-09-23, Last Modified 2018.

11. Spring에서 Properties 사용, https://yookeun.github.io/java/2015/12/22/spring-properties/, Accessed by 2020-09-23, Last Modified 2015-12-22.

12. Java에서 Properties 파일 읽기, https://prettymucho.tistory.com/7, Accessed by 2020-09-23, Last Modified 2017-06-12.

반응형
728x90
300x250

[Spring-Framework] 10. Spring MVC - HikariCP 3.4.2, Oracle 19g 연동하기(Properties, Java) - (1)


Spring MVC 프로젝트로 HikariCP 3.4.2를 연동하는 방법에 대해서 소개하겠다.

Apache DBCP(커넥션 풀) 프로젝트도 있으나 최근에는 HikariCP가 성능이 더 우수하다고 한다.


양이 많은 주제이므로 2부로 나눠서 작성하였다.



1. Introduce(소개) - 커넥션 풀


1. 커넥션 풀(DBCP)이란?

웹 컨테이너(WAS)가 실행되면서 DB와 미리 connection(연결)을 해놓은 객체들을 pool에 저장해두었다가, 클라이언트 요청이 오면 connection을 빌려주고, 처리가 끝나면 다시 connection을 반납받아 pool에 저장하는 방식을 말한다.



2. 작업환경


이 글에서 사용한 작업 환경이다.


* IDE: Spring Tool-Suite 4-4.7.2 Releases(Eclipse)


* Web Server(웹서버):

Apache Tomcat 9


* 데이터베이스(Databases)

Oracle Databases 19

MySQL 8.0.21


* 프레임워크

Spring Framework 3.1.1 Releases


* 라이브러리

POM - Oracle JDBC 19

POM - MySQL 8.0.21

Maven Project - 3.6.3/1.16.0.20200610-1735


특징: MyBatis 제거 등 영속 프레임워크 미적용




3. 프로젝트 구성


작업할 프로젝트의 구성이다.



그림 1. 프로젝트 구성




4. 새 프로젝트 생성


File -> New -> Others...

                 Spring 폴더-> Spring Legacy Projects



5. pom.xml 설정





그림 2. POM.xml 수정 - 자바 버전 수정하기


[JAVA JDK 버전 오류]

오류 : Resource specification not allowed here for source level below 1.7


자바 버전을 변경하는 이유는 1.6으로는 버전이 낮아서 미지원한다고 오류가 발생하기 때문이다.

pom.xml 셋팅 후 project에서 변경을 해줘야 한다.


그림 3. POM.xml 수정 - Spring Test 영역 수정하기



그림 4. POM.xml 수정 - HikariCP, Oracle JDBC


      <properties>

<java-version>14</java-version>

<org.springframework-version>3.1.1.RELEASE</org.springframework-version>

<org.aspectj-version>1.6.10</org.aspectj-version>

<org.slf4j-version>1.6.6</org.slf4j-version>

</properties>


(중략)


<!-- spring-test -->

<dependency>

<groupId>org.springframework</groupId>

<artifactId>spring-test</artifactId>

<version>${org.springframework-version}</version>

</dependency>


(중략)


<!-- https://mvnrepository.com/artifact/com.zaxxer/HikariCP -->

<dependency>

    <groupId>com.zaxxer</groupId>

    <artifactId>HikariCP</artifactId>

    <version>3.4.2</version>

</dependency>


<dependency>

<groupId>com.oracle.database.jdbc</groupId>

<artifactId>ojdbc8</artifactId>

<version>19.3.0.0</version>

</dependency>    


* 파일명: pom.xml


* 참고 - MySQL 연동할 때


아래의 코드는 pom.xml에 넣어준다.


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

<dependency>

    <groupId>mysql</groupId>

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

    <version>8.0.21</version>

</dependency>




6. Project의 Properties의 Java Build Path 내 Libraries의 JRE 버전 바꾸기


pom.xml은 maven 환경에 대한 자바 버전 설정이었는데, 근본적인 Build Path에 관한 속성을 변경하는 작업이다.


[JAVA JDK 버전 오류]

오류 : Resource specification not allowed here for source level below 1.7



그림 5. Properties 클릭하기


프로젝트를 클릭한다.

오른쪽 버튼을 누른 후, Properties를 클릭한다.




그림 6. Java Build Path 설정하기 - Libraries


JRE System Library 1.6 버전을 Remove한다.

Add Library를 클릭하여 버전을 1.7 버전 이상으로 올려준다.



7. root-context.xml 수정하기


-> src/main/webapp/spring/root-context.xml에 있음.



그림 7. root-context.xml 파일 작업내용


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

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

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

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

<!-- Root Context: defines shared resources visible to all other web components -->

<bean id="hikariConfig" class="com.zaxxer.hikari.HikariConfig">

<!-- Oracle 9 이상으로 작성. -->

<!-- 오라클 9 이후에 oracle.jdbc.driver.OracleDriver는 중단되었음.  -->

<!-- oracle.jdbc.pool.OracleDataSource -->

<!-- jdbc:oracle:thin:@localhost:1521:orcl -->


  <property name="driverClassName" value="oracle.jdbc.OracleDriver"></property>

<property name="jdbcUrl" value="jdbc:oracle:thin:@localhost:1521:orcl"></property> 

<property name="username" value="사용자계정명"></property>

<property name="password" value="비밀번호"></property>

</bean>

<bean id="datasource" class="com.zaxxer.hikari.HikariDataSource" destroy-method="close">

<constructor-arg ref="hikariConfig"></constructor-arg>

</bean>

</beans>



파일명: root-context.xml (Oracle 11 이상) - 태스트 확인: Oracle 18g


* [첨부(Attachments)]

root-context-oracle.zip



* 참고 - MySQL 연동(root-context.xml)


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

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

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

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

<!-- Root Context: defines shared resources visible to all other web components -->

<bean id="hikariConfig" class="com.zaxxer.hikari.HikariConfig">

  <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"></property>

<property name="jdbcUrl" value="jdbc:mysql://localhost:{포트번호}/{DB명}?serverTimezone=UTC"></property> 

<property name="username" value="사용자 계정명"></property>

<property name="password" value="비밀번호"></property>

</bean>

<bean id="datasource" class="com.zaxxer.hikari.HikariDataSource" destroy-method="close">

<constructor-arg ref="hikariConfig"></constructor-arg>

</bean>

</beans>


파일명: root-context.xml(mysql 버전)


* [첨부(Attachments)]

root-context-mysql.zip



* 정정: jdbc:mysql://localhost:3306/web?serverTimezone=UTC&characterEncoding=utf8



8. servlet-context.xml 파일 수정하기


servlet-context.xml 파일을 수정해준다.


파일 경로: /src/main/webapp/WEB-INF/spring/appServlet



그림 8. servlet-context.xml - 수정된 모습


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

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

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

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

http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.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>

<!-- 추가(Hikara4 -->

<!-- <context:property-placeholder location="classpath:/db.properties" />  -->

<util:properties id="props" location="classpath:/db.properties" />     

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

</beans:beans>


파일명: servlet-context.xml


* [첨부(Attachments)]

servlet-context.zip




9. /src/main/resources/db.properties 만들기


Spring MVC 프로젝트로 작성하였으면, Resources 폴더는 생성되어 있을 것이다.

없다면, 별도로 만들어야 한다.


db.properties 파일은 존재하지 않기 때문에 따로 만들어줘야 한다.



그림 9. 파일 만들기


resources 폴더를 클릭한 후 오른쪽 버튼을 클릭한다.

New->File을 클릭한다.



그림 10. 프로젝트 구성 - dbProperties


jdbcUrl=jdbc:oracle:thin:@localhost:1521:orcl

dataSourceClassName=oracle.jdbc.OracleDriver

dataSource.user={username}

dataSource.password={password}

cachePrepStmts=true

prepStmtCacheSize=250

prepStmtCacheSqlLimit=2048


파일명: db.properties (oracle 버전)


[첨부(Attachments)]

db-properties-oracle.zip


jdbcUrl=jdbc:mysql://localhost:3306/web?serverTimezone=UTC

dataSourceClassName=com.mysql.cj.jdbc.Driver

dataSource.user={UserName}

dataSource.password={Password}

cachePrepStmts=true

prepStmtCacheSize=250

prepStmtCacheSqlLimit=2048


파일명: db.properties (mysql버전)


[첨부(Attachments)]

db-properties-mysql.zip



* 2부에서 만나요.


초기 셋팅은 이 정도면 끝났으니, 2부에서 연재하도록 하겠다.


[Spring-Framework] 11. Spring MVC - HikariCP 3.4.2, Oracle 19g 연동하기(Properties, Java) - (2), 2020-09-23 14:28

https://yyman.tistory.com/1411


반응형
728x90
300x250

[Spring-Framework] 9. MVC웹 - POST, GET 방식, c태그 목록 출력


웹 게시판 작성에서 필요한 POST, GET 방식 처리에 대해서 Spring-Framework를 통해서 소개하려고 한다.

자료구조(Data Structure)인 List, Hash-Map에 대한 내용은 생략하겠다.


일반 범용 "게시판"에서 사용될 수 있는 것 위주로 작성하였다.


* IDE: Spring Tool-Suite 4(Eclipse)

-> Spring Legacy Project의 Spring MVC Project를 기반으로 작성함.





1. 결과부터 살펴보는 POST, GET 방식 처리


크게 데이터를 전송하는 방식에는 POST, GET 방식이 있다.

기능으로 요약하면, 외부에 노출되서 전송되는 방식은 GET이고, 숨겨서 전송하는 방식은 POST방식이다.


이 프로젝트의 특징은 추후에 MyBatis 등의 라이브러리까지 고민하여 작성하였다.




그림 1. 글쓰기 양식



그림 2. POST 방식 처리 - Map 목록 출력




그림 3. GET 방식 처리 - List 목록 출력





2. 프로젝트


Controller, VO(Value Object)는 다음처럼 해준다.



그림 4. 프로젝트 구성(Controller와 VO)



View 영역은 아래처럼 구성해준다.



그림 5. 프로젝트 구성(view영역의 jsp 파일)





3. 코드(MemberVO)


MemberVO는 매우 간단하게 작성하였다.


package com.springMVC1.web.vo;


public class MemberVO {


private String id;

private String passwd;

public String getId() {

return id;

}

public void setId(String id) {

this.id = id;

}

public String getPasswd() {

return passwd;

}

public void setPasswd(String passwd) {

this.passwd = passwd;

}

}



파일명: MemberVO.java




4. 코드(Controller - BoardController)


BoardController를 구성해보았다.


package com.springMVC1.web.controller;


import java.text.DateFormat;

import java.util.ArrayList;

import java.util.Date;

import java.util.HashMap;

import java.util.List;

import java.util.Locale;

import java.util.Map;


import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.springframework.stereotype.Controller;

import org.springframework.ui.Model;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RequestMethod;


import com.springMVC1.web.vo.MemberVO;



@Controller

@RequestMapping(value="/board")

public class BoardController {

private static final Logger logger = LoggerFactory.getLogger(BoardController.class);

@RequestMapping(value = "/list", method = RequestMethod.GET)

public String list(Locale locale, Model model) {

logger.info("Welcome board - list! The client locale is {}.", locale);

Date date = new Date();

DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, locale);

String formattedDate = dateFormat.format(date);

model.addAttribute("serverTime", formattedDate );

return "/board/list";

}

// GET, POST 방식 모두 가능

@RequestMapping(value = "insert")

public String insert(Locale locale, Model model) {

return "/board/insert";

}

// POST방식만 사용

@RequestMapping(value = "insertResult", method=RequestMethod.POST)

public String insertResult(Model model, MemberVO memberVO) {

model.addAttribute("serverTime", "1군");


logger.info("로거 사용"); // 로거

HashMap<String, Object> map = new HashMap<String, Object>();

MemberVO node1 = new MemberVO();

// 1번 회원

node1.setId("user1");

node1.setPasswd("1234");

map.put("1", node1);

// 2번 회원

node1 = new MemberVO();

node1.setId("user2");

node1.setPasswd("9876");

map.put("2", node1);

// model 속성으로 등록

model.addAttribute("map", map);

return "/board/insert_result_post";

}

// GET방식만 사용 - 편법(매개변수 하나 더 추가) 

@RequestMapping(value = "insertResult", method=RequestMethod.GET)

public String insertResult(Model model, MemberVO memberVO, String s) {

model.addAttribute("serverTime", "2군");


logger.info("로거 사용"); // 로거

// 다중 회원 목록 출력 실험

List<MemberVO> member = new ArrayList<MemberVO>();

MemberVO node1 = new MemberVO();

// 1번 회원

node1.setId("user1");

node1.setPasswd("1234");

member.add(node1);

// 2번 회원

node1 = new MemberVO();

node1.setId("user2");

node1.setPasswd("9876");

member.add(node1);

model.addAttribute("list", member);

return "/board/insert_result_get";

}

}


파일명: BoardController.java


이 프로젝트에서 POST, GET을 하나의 RequestMapping Value값 "insertResult"로 처리하는 방법에 대해서 소개하고 있다.




5. 코드(View - JSP 파일)


insert.jsp 파일을 기반으로 POST, GET 방식 실험을 동시에 할 수 있도록 설계하였다.


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

    pageEncoding="UTF-8"%>

<!DOCTYPE html>

<html>

<head>

<meta charset="UTF-8">

<title>글쓰기 - 양식</title>

</head>

<body>


<%

String context = request.getContextPath();

%>

<h3>POST 방식</h3>

<form action="<%=context%>/board/insertResult" method="POST">

ID: <input type="text" name="id"><br/>

비밀번호: <input type="password" name="passwd"><br/>

<input type="submit" value="전송">

</form>

<br />

<h3>GET 방식</h3>

<form action="<%=context%>/board/insertResult" method="GET">

ID: <input type="text" name="id"><br/>

비밀번호: <input type="password" name="passwd"><br/>

<input type="submit" value="전송">

</form>


</body>

</html>


파일: /board/insert.jsp


<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>

<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>


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

    pageEncoding="UTF-8"%>

<!DOCTYPE html>

<html>

<head>

<meta charset="UTF-8">

<title>등록 결과 - GET방식(실험)</title>

</head>

<body>


<!-- 결과 -->

<h3>GET 방식 - 실험</h3>

<h5>GET으로 전송받은 데이터</h5>

<table border="1" style="width:500px">

<tr>

<td>서버시간</td>

<td>${serverTime }</td>

</tr>

<tr>

<td>ID</td>

<td>${memberVO.id}</td>

</tr>

<tr>

<td>비밀번호</td>

<td>${memberVO.passwd }</td>

</tr>

</table>

<br />

<h5>ArrayList 결과 출력하기</h5>

<!-- 다중 회원 출력 -->

<table border="1" style="width:500px">


<c:forEach items="${list}" var="list">

<tr>

<td>ID</td>

<td>${list.id}</td>

<td>비밀번호</td>

<td>${list.passwd }</td>

</tr>

</c:forEach>

</table>


</body>

</html>


파일: /board/insert_result_get.jsp


<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>

<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>


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

    pageEncoding="UTF-8"%>

<!DOCTYPE html>

<html>

<head>

<meta charset="UTF-8">

<title>등록 결과 - Post방식(실험)</title>

</head>

<body>


<!-- 결과 -->

<h3>POST 방식 - 실험</h3>

<br/>

<table border="1" style="width:500px">

<tr>

<td>서버시간</td>

<td>${serverTime }</td>

</tr>

<tr>

<td>ID</td>

<td>${memberVO.id}</td>

</tr>

<tr>

<td>비밀번호</td>

<td>${memberVO.passwd }</td>

</tr>

</table>


<h5>Map 결과 출력하기</h5>

<!-- 다중 회원 출력 -->

<table border="1" style="width:700px">


<c:forEach items="${map}" var="i">

<tr>

<td style="width:50px">1. Key값</td>

<td style="width:150px">${i.key}</td>

<td style="width:50px">2. 객체주소</td>

<td style="width:200px">${i.value}</td>

<%

%>

<td style="width:50px">3. 객체값(ID)</td>

<td style="width:100px">${i.value.id}</td>

<td style="width:50px">3. 객체값(Passwd)</td>

<td style="width:100px">${i.value.passwd}</td>

</tr>

</c:forEach>

</table>


</body>

</html>


파일: /board/insert_result_post.jsp


* 형식문자

-> 년도 출력

<fmt:formatNumber value="${변수명}" pattern="yyyy-mm-dd" />

<fmt:formatNumber value="${객체명.멤버변수명}" pattern="yyyy-mm-dd" />



* 맺음글(Conclusion)


게시판 구현에 대해서 조금 더 쉽게 접근할 수 있는 방법에 대해서 소개하였다.

복잡한 기능들 다 제거해보았더니, 나름대로 Spring-Framework도 쉽고 빠르게 접근할 수 있다고 본다.

반응형
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.

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

반응형

+ Recent posts