728x90
300x250

[Spring-Framework] 30. AOP(Aspect-Oriented-Programming) 관점지향 프로그래밍 (Java셋팅) (1)


참고로 AOP는 Spring-Framework에만 적용되는 방법론이다.

새로 만들어진 개념은 아니고, 자바의 Proxy(패턴 아님. 탈취기법이 있음.)에서 핵심 영역의 관점으로 진화한 개념이다.


교과서나 시중 책 등에서는 이런 표현은 안 쓰긴 하지만, "탈취 방법"이라고 하는 게 적절하다고 주장하다.


해당 작업은 Spring Framework에서만 가능한 작업이다.



IDE: Spring Tool-Suite 4-4.7.2 Release(2020-08월)
Library: 

- Spring Framework 5.2.9.RELEASE (2020-09-15)

- Java Version: 14

- AspectJ: 1.9.6 (2020-07-22)

- AspectJ Weaver: 1.9.6 (2020-07-22)

- javax.servlet-api 4.0.1 (2018-04-20)


(순정 상태로 셋팅하였음.)



Project: Spring Legacy Project로 생성할 것


-> 안 보이는 사람들은 Help->Eclipse Marketplace -> STS 검색 후 "Spring Tools 3 Add-On for Spring Tools 4 3.9.14.RELEASE" 설치할 것



그림 1. STS-Addon (Eclipse Marketplace)



1. 이전의 개발 방법론(Proxy)


지금도 물론 이런 방법은 안 쓰일 수는 없다.

AOP가 먼저 나온 것이 결코 아니다. 아마 c#에도 이런 게 있는 걸로 알고 있다. (오래되서)


프로그래밍 개발을 하다보면, 로직을 구현하는데 있어서 코어 코드를 수정해서 작업을 하는 일이 많이 있다.

핵심 규칙은 x, y, z만 더해서 결과만 출력하면 되는 요구사항을 가진 문제인데 구현을 하다보면, 현실적인 문제라는 게 발생하게 된다.


그림 2. 이전의 로직 구현 방법 - 개발


그림 1과 같은 문제는 자주 생기는 문제이기도 하다.

이런 방법으로 구현하는 것이 아예 사라졌다는 게 아니다.


그림 1에서 (1단계)의 핵심 규칙을 재사용할 기회를 상실해버리는 문제가 발생하게 된다.



그림 3. 문제 인식


그림 2처럼 문제가 생겼다고 하자.

물론 머리가 조금 좋은 분들은 객체의 상속 관계로 처리해도 해결할 수 있지 않겠냐고 할 수도 있다. 

(객체지향 프로그래밍에서도 설계를 다시 해서 이런 문제를 나눠볼 수도 있겠음.)


허나 쉬운 일이 결코 아니다. 코드라는 게 이쪽에서 사용되고 있는지, 저기에서 사용되고 있는지 작성을 하게 되면 수정이 정말 어렵다는 것이다.


물론 C#을 논하는 자리가 아니어서 자바를 예로 들면, Proxy 탈취 방법이 존재한다.




그림 4. Proxy 탈취 방법 - 자바


자바에서는 


Type of Classes username new Proxy.newProxyInstance(Classes.class.getClassLoader(), new Class[] { classes.class } , 

new InvocationHandler(){

          public Object invoke(Object proxy, Method method, Object args[] throws Throwable{

                     

                  // 전단계 호출

                  Object result = method.invoke(sum, args);

                  // 후단계 호출

         }


     }


};


슈도 코드(Pseudo Code) 1. 자바의 Proxy 호출 방법


이런 방법으로 핵심 로직을 탈취하는 방법이 있다.

기본적인 원리는 이런 원리에 입각해서 만들어졌다고 보면 된다.


AOP의 용어 설명은 나중에 할 것이다. 절대로 지금 바로 알면 안 된다고 생각한다.


3단계를 기본으로 한다. "전 단계, 핵심 로직, 후 단계"

이 단계의 확장적인 개념이다.


Spring AOP에서는 5단계로 확장되었다.


전단계:    {Around 단계, Before 단계}, 

핵심로직:         핵심 로직(중간)

후단계:    {after Method 호출, AfterThrowing(선택 - 예외 처리 발생 때만)}


조금 더 이해하기 쉬워졌을 것으로 보인다.


[첨부(Attachments)]

background-aop.zip





2. 코드로 살펴보는 AOP


AOP를 이론으로만 봐서는 이해가 무척 안 될 것이다. 구현을 통해서 단계적으로 살펴보도록 하겠다.

프로젝트 생성부터 단계적으로 소개하겠다.



그림 5. 프로젝트 생성하기


File을 클릭한다.

New -> Spring Legacy Project를 클릭한다.



그림 6. 프로젝트 생성하기


Spring MVC Project를 선택한다.

Project name을 입력한다.

Next를 누른다.




그림 7. 프로젝트 생성하기


Top-level-package를 입력한다. (예: com.local.example)

Finish를 누른다.



3. POM.xml 설정하기


http://mvnrepository.com 사이트에 접속한다.

검색 키워드에 "aspectj"라고 입력한다. (세 가지 검색을 해서 버전을 획득해야 함)

검색 키워드에 "spring"라고 입력한다.

검색 키워드에 "servlet"이라고 입력한다.


두 가지의 Maven 주소를 획득해야 한다.



그림 8. MVNRepository 검색 결과의 예 (1) - AspectJ



그림 9. MVNRepository 검색 결과의 예 (1) - AspectJ


버전을 클릭하면, Maven Pom이 나온다.

이걸 복사 붙여넣기를 해도 된다.


다만 <version>만 복사해서 관리하는 방법도 있으니 자세한 건 POM.xml 소스를 참고하면 좋겠다.



그림 10. pom.xml - 변경 작업 모습(1)


<java-version>14</java-version>으로 변경한다.

<org.springframework-version>5.2.9.RELEASE</org........>로 변경한다.

<org.aspectj-version>1.9.6</org......>으로 변경한다.


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

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd">

<modelVersion>4.0.0</modelVersion>

<groupId>com.local</groupId>

<artifactId>example</artifactId>

<name>springAOP-javaConfig</name>

<packaging>war</packaging>

<version>1.0.0-BUILD-SNAPSHOT</version>

<properties>

<!-- 자바 버전 변경함 -->

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

<!-- 스프링프레임워크 버전 변경함 -->

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

<!-- AspectJ 변경함 -->

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

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

</properties>

<dependencies>

<!-- Spring -->

<dependency>

<groupId>org.springframework</groupId>

<artifactId>spring-context</artifactId>

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

<exclusions>

<!-- Exclude Commons Logging in favor of SLF4j -->

<exclusion>

<groupId>commons-logging</groupId>

<artifactId>commons-logging</artifactId>

</exclusion>

</exclusions>

</dependency>

<dependency>

<groupId>org.springframework</groupId>

<artifactId>spring-webmvc</artifactId>

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

</dependency>

<!-- AspectJ 버전 변경 -->

<dependency>

<groupId>org.aspectj</groupId>

<artifactId>aspectjrt</artifactId>

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

</dependency>

<!-- AspectJWeaver 추가 -->

<dependency>

<groupId>org.aspectj</groupId>

<artifactId>aspectjweaver</artifactId>

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

</dependency>


<!-- Logging -->

<dependency>

<groupId>org.slf4j</groupId>

<artifactId>slf4j-api</artifactId>

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

</dependency>

<dependency>

<groupId>org.slf4j</groupId>

<artifactId>jcl-over-slf4j</artifactId>

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

<scope>runtime</scope>

</dependency>

<dependency>

<groupId>org.slf4j</groupId>

<artifactId>slf4j-log4j12</artifactId>

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

<scope>runtime</scope>

</dependency>

<dependency>

<groupId>log4j</groupId>

<artifactId>log4j</artifactId>

<version>1.2.15</version>

<exclusions>

<exclusion>

<groupId>javax.mail</groupId>

<artifactId>mail</artifactId>

</exclusion>

<exclusion>

<groupId>javax.jms</groupId>

<artifactId>jms</artifactId>

</exclusion>

<exclusion>

<groupId>com.sun.jdmk</groupId>

<artifactId>jmxtools</artifactId>

</exclusion>

<exclusion>

<groupId>com.sun.jmx</groupId>

<artifactId>jmxri</artifactId>

</exclusion>

</exclusions>

<scope>runtime</scope>

</dependency>


<!-- @Inject -->

<dependency>

<groupId>javax.inject</groupId>

<artifactId>javax.inject</artifactId>

<version>1</version>

</dependency>

      <!-- Servlet -->

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

<dependency>

<groupId>javax.servlet.jsp</groupId>

<artifactId>jsp-api</artifactId>

<version>2.1</version>

<scope>provided</scope>

</dependency>

<dependency>

<groupId>javax.servlet</groupId>

<artifactId>jstl</artifactId>

<version>1.2</version>

</dependency>

<!-- Test -->

<dependency>

<groupId>junit</groupId>

<artifactId>junit</artifactId>

<version>4.7</version>

<scope>test</scope>

</dependency>        

</dependencies>

    <build>

        <plugins>

            <plugin>

                <artifactId>maven-eclipse-plugin</artifactId>

                <version>2.9</version>

                <configuration>

                    <additionalProjectnatures>

                        <projectnature>org.springframework.ide.eclipse.core.springnature</projectnature>

                    </additionalProjectnatures>

                    <additionalBuildcommands>

                        <buildcommand>org.springframework.ide.eclipse.core.springbuilder</buildcommand>

                    </additionalBuildcommands>

                    <downloadSources>true</downloadSources>

                    <downloadJavadocs>true</downloadJavadocs>

                </configuration>

            </plugin>

            <plugin>

                <groupId>org.apache.maven.plugins</groupId>

                <artifactId>maven-compiler-plugin</artifactId>

                <version>2.5.1</version>

                <configuration>

                    <source>1.6</source>

                    <target>1.6</target>

                    <compilerArgument>-Xlint:all</compilerArgument>

                    <showWarnings>true</showWarnings>

                    <showDeprecation>true</showDeprecation>

                </configuration>

            </plugin>

            <plugin>

                <groupId>org.codehaus.mojo</groupId>

                <artifactId>exec-maven-plugin</artifactId>

                <version>1.2.1</version>

                <configuration>

                    <mainClass>org.test.int1.Main</mainClass>

                </configuration>

            </plugin>

        </plugins>

    </build>

</project>



파일명: pom.xml


[첨부(Attachments)]

pom.zip





4. Project의 Properties - Build Path, Project Factes 설정하기 (Java Version 변경)


프로젝트의 자바 버전을 변경할 것이다.



그림 11. 프로젝트의 마우스 오른쪽 버튼 메뉴 모습


프로젝트를 선택한 후 마우스 오른쪽 버튼을 누른다.

Properties를 클릭한다.




그림 12. Java Build Path


Java Build Path를 클릭한다.

JRE System Library를 [JavaSE-14]로 변경한다.




그림 13. Project Factes


Project Factes를 클릭한다.

Java의 버전을 14로 바꿔준다.




5. web.xml - 서블릿 스팩 (2.5에서 4.0으로 변경)


서블릿 스팩을 변경할 것이다.

web.xml에서 변경해주면 된다.



그림 14. web.xml (servlet 4.0 스팩으로 변경)



<?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_4_0.xsd"

    version="4.0">


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


</web-app>



파일명: web.xml


[첨부(Attachments)]

web.zip



6. service - Calculator.java


복잡한 설명을 적기보다는 작업화면하고 코드를 소개하겠다.



그림 15. Calculator.java


package com.local.example.service;


public class Calculator {


private long x;

private long y;

private long z;

public Calculator(long x, long y, long z) {

this.x = x;

this.y = y;

this.z = z;

}

// 작업 원본(A 프로그래머 작성함)

public long sum() {

long result = x + y + z;

return result;

}


}


파일명: Calculator.java


[첨부(Attachments)]

 Calculator-original.zip


참고로 지금 코드로는 AspectJ가 동작되지 않는 코드이다.
이유는 초기 매개변수가 없는 생성자가 없어서 그렇다.

(다음 페이지에서 소개하겠음.)



7. Controller - HomeController.java


아마 순정 코드에 Calculator의 sum()를 호출한 것을 보면, 다음과 같이 되어있다.


package com.local.example;


import java.text.DateFormat;

import java.util.Date;

import java.util.Locale;


import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import org.springframework.context.annotation.EnableAspectJAutoProxy;

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.local.example.aop.Calculator;

import com.local.example.aop.RootConfig;


/**

 * Handles requests for the application home page.

 */

public class HomeController {

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

/**

* 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);


Calculator cal = new Calculator(1, 2, 3);

System.out.printf("result of sum: %d", cal.sum());

model.addAttribute("serverTime", formattedDate );

return "home";

}

}



파일명: HomeController.java


이렇게 하면, 잘 동작할 것이다.

결과가 "result of sum: 6"이 출력될 것이다.



* 2부에서 AOP 사용 코드로 전환하는 방법에 대해서 소개하겠다.


1. [Spring-Framework] 30. AOP(Aspect-Oriented-Programming) 관점지향 프로그래밍 (Java셋팅) (2), 2020-10-04

https://yyman.tistory.com/1448


반응형
728x90
300x250

[Spring-F.] 29. MyBatis 3.5, Spring Framework 5.4, Oracle 19g - 방법5(SqlMap Spring전용)


소스 코드 위주로 소개하겠다.


[실험 결과]

1. [Spring-Framework] Spring Framework 5.4, MyBatis 3.5 연동 방법 - 실험 결과, 2020-10-02

   - https://yyman.tistory.com/1437


[이전 게시글]

1. [Spring-F.] 28. MyBatis 3.5, Spring Framework 5.4, Oracle 19g - 방법4(SqlMap Spring전용)

   - https://yyman.tistory.com/1441



41. 결과


XML 방식의 XML Mapping으로 구성하여 동작한 결과이다.



그림 25. 결과 5번



그림 26. 프로젝트 구성도



42. web.xml - 기본값


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


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


</web-app>





43. com.example.spbatis.db - SqlMapSessionFactory.java


package com.example.spbatis.db;



import java.io.IOException;

import java.io.InputStream;

import java.sql.SQLException;


import javax.sql.DataSource;


import org.apache.ibatis.io.Resources;

import org.apache.ibatis.mapping.Environment;

import org.apache.ibatis.session.Configuration;

import org.apache.ibatis.session.SqlSessionFactory;

import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import org.apache.ibatis.transaction.TransactionFactory;

import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory;

import org.mybatis.spring.SqlSessionFactoryBean;

import org.springframework.core.io.support.PathMatchingResourcePatternResolver;


import com.example.spbatis.model.CompUsers;


import oracle.jdbc.pool.OracleDataSource;


public class SqlMapSessionFactory {


private static SqlMapSessionFactory factory = new SqlMapSessionFactory();

private final static String driverName = "oracle.jdbc.driver.OracleDriver";

private final static String dbUrl = "jdbc:oracle:thin:@127.0.0.1:1521:orcl";

private final static String userName = "사용자계정명";

private final static String userPassword = "비밀번호";

public static SqlSessionFactory ssf;


public static SqlMapSessionFactory getInstance() {

return factory;

}

private SqlMapSessionFactory () {    }

static {

/* 방법1

DataSource dataSource = getOracleDataSource();

TransactionFactory transactionFactory = new JdbcTransactionFactory();

Environment environment = new Environment("development", transactionFactory, dataSource);

Configuration configuration = new Configuration(environment);

configuration.addMapper(CompUsersMapper.class);

ssf = new SqlSessionFactoryBuilder().build(configuration);

*/

}

    

    public static SqlSessionFactory getSqlSessionFactory(){

   


/* 방법2: 공식 메뉴얼 참고 */

DataSource dataSource = getOracleDataSource();


SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean(); // Spring Framework만 지원

factoryBean.setDataSource(dataSource);

try {

//쿼리가 정의된 xml 파일들의 위치 지정

        factoryBean.setMapperLocations(

                new PathMatchingResourcePatternResolver().getResources("com/example/spbatis/mapper/*.xml")

        );

    

ssf = factoryBean.getObject();

// 클래스 등록

// ssf.getConfiguration().addMapper(CompUsersMapper.class);

} catch (Exception e) {

e.printStackTrace();

}

   

    // 방법 1, 방법 2 공통

        return ssf;

    }

    

    /*

* Description: 순정 오라클 데이터소스

*/

    private static DataSource getOracleDataSource(){


    OracleDataSource oracleDS = null;


    try {

            oracleDS = new OracleDataSource();

            oracleDS.setURL(dbUrl);

            oracleDS.setUser(userName);

            oracleDS.setPassword(userPassword);


        } catch (SQLException e) {

            e.printStackTrace();

        }


        return oracleDS;


    }

    

}



파일명: SqlMapSessionFactory.java


[첨부(Attachments)]

SqlMapSessionFactory.zip




44. com.example.spbatis.mapper - CompUsersMapper.xml


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

<!DOCTYPE mapper

  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">


<mapper namespace="com.example.spbatis.mapper">


<select id="allCompUsers" resultType="com.example.spbatis.model.CompUsers">

select * from comp_users

</select>

<!-- 

<select id="allAddress" resultType="com.edu.db.AddressDto">

select * from addressbook

</select>

<select id="selectAddress" parameterType="Integer" resultType="com.edu.db.AddressDto">

select NUM, NAME, ADDRESS, BIRTHDATE

from addressbook

  where num=#{num}

</select>

<insert id="insertAddress" parameterType="com.edu.db.AddressDto">

insert into

addressbook(NAME, ADDRESS, BIRTHDATE)

values

(#{name},#{address},#{birthdate})

</insert>

<delete id="deleteAddress" parameterType="Integer">

DELETE FROM AddressBook

WHERE NUM = #{num}

</delete>

<update id="updateAddress" parameterType="com.edu.db.AddressDto" >

update addressbook

set birthdate = #{birthdate}, name = #{name}, address =#{address}

where num = #{num}

</update>

 -->

</mapper>


파일명: CompUsersMapper.xml


[첨부(Attachments)]

CompUsersMapper.zip





45. com.example.spbatis.dao - CompUsersDao.java


package com.example.spbatis.dao;


import java.util.List;


import org.apache.ibatis.session.SqlSession;

import org.apache.ibatis.session.SqlSessionFactory;


import com.example.spbatis.db.SqlMapSessionFactory;

import com.example.spbatis.model.CompUsers;



public class CompUsersDao {


    SqlSessionFactory factory = SqlMapSessionFactory.getSqlSessionFactory();

    

    public CompUsersDao() {

        

    }

    

    // SQL 세션 열기

    public List<CompUsers> selectAddress() {


    List<CompUsers> user = null;

try (SqlSession session = factory.openSession()) {

 

user = session.selectList("com.example.spbatis.mapper.allCompUsers");

session.close();

// System.out.println("계정명:" + user.getUsername());


}

return user;


    }

    

}



파일명: CompUsersDao.java


[첨부(Attachments)]

CompUsersDao.zip





46. com.example.spbatis.service - CompUsersService.java


package com.example.spbatis.service;


import java.util.List;


import com.example.spbatis.dao.CompUsersDao;

import com.example.spbatis.model.CompUsers;


public class CompUsersService {


private CompUsersDao dao = null;

public CompUsersService() {

dao = new CompUsersDao();

}

public List<CompUsers> getAllCompUsers() {

return dao.selectAddress();

}

 

}



파일명: CompUsersService.java


[첨부(Attachments)]

CompUsersService.zip




47. com.example.spbatis - HomeController.java


package com.example.spbatis;


import java.text.DateFormat;

import java.util.Date;

import java.util.Locale;


import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

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

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.example.spbatis.service.CompUsersService;


/**

 * Handles requests for the application home page.

 */

@Controller

public class HomeController {

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

private CompUsersService compUserService;

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

public String home(Locale locale, Model model) {

logger.info("Welcome home5 - Java(XML Mappers)! The client locale is {}.", locale);

Date date = new Date();

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

String formattedDate = dateFormat.format(date);

compUserService = new CompUsersService();

model.addAttribute("serverTime", formattedDate );

model.addAttribute("list", compUserService.getAllCompUsers()) ;

return "home";

}

}



파일명: HomeController.java


[첨부(Attachments)]

HomeController.zip





48. view - home.jsp


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

    pageEncoding="UTF-8"%>

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

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

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

<%@ page session="false" %>


<html>

<head>

<title>Home</title>

</head>

<body>

<h1>

Hello world!  

</h1>


<P>  The time on the server is ${serverTime}. </P>

<h3>SqlMapSessionFactory 방식(Java - XML Mapper - Spring 전용 버전)</h3>

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

    ${val.username} / 

    ${val.password} /

    ${val.enabled }<br>

</c:forEach>

<c:if test="${empty list }">

    ${"데이터가 존재하지않아요."}

</c:if>


</body>

</html>



파일명: home.jsp


[첨부(Attachments)]

home.zip



* 맺음글(Conclusion)


조금 작성하는데 힘이 들었지만. MyBatis 하나 셋팅에는 다양한 방법이 지원된다는 것을 알 수 있었다.



* 참고 자료(References)


1. mybatis-spring - 마이바티스 스프링 연동모듈 | 시작하기, https://mybatis.org/spring/ko/getting-started.html, Accessed by 2020-10-02, Last Modified 2020-06-05.

   [비고] - 공식 사이트이다. (이 메뉴얼만 가지고는 다 안 될 수도 있다.)


2. 스프링프레임워크 Java config로 MyBatis 사용하기, https://offbyone.tistory.com/381, Accessed by 2020-10-02, Last Modified 2019-03-17.


3. [mybatis] 다중 Database Setting, https://wfreud.tistory.com/310, Accessed by 2020-10-02, Last Modified 2019-03-21.


4. maven프로젝트 src/main/resource경로의 파일 읽기, https://blog.naver.com/down83/50092131189, Accessed by 2020-10-02, Last Modified 2010-07-13.


5. MyBatis List와 Map으로 데이터 불러오기, https://smujihoon.tistory.com/112, Accessed by 2020-10-02, Last Modified 2019-02-11.


5. [Mybatis] root-context.xml 자료(Oracle), https://datamod.tistory.com/81, Accessed by 2020-10-02, Last Modified 2018-05-20.


6. 7. 공용 클래스 작성 - commonDAo, https://tapasnote.tistory.com/21?category=697717, Accessed by 2020-10-02, Last Modified 2017-04-12.


7. DatsSource, 커넥션 풀을 이용한 DB 연결, https://m.blog.naver.com/PostView.nhn?blogId=2hyoin&logNo=220647895962, Accessed by 2020-10-02, Last Modified 2016-03-07.


8. MyBatis tutorial - Introductory MyBatis tutorial, http://zetcode.com/db/mybatis/, Accessed by 2020-10-02, Last Modified 2020-07-06.

   [영어 사이트]


반응형
728x90
300x250

[Spring-F.] 28. MyBatis 3.5, Spring Framework 5.4, Oracle 19g - 방법4(SqlMap Spring전용)


소스 코드 위주로 소개하도록 하겠다.


[실험 결과]

1. [Spring-Framework] Spring Framework 5.4, MyBatis 3.5 연동 방법 - 실험 결과, 2020-10-02

   - https://yyman.tistory.com/1437


[이전 게시글]

1. [Spring-F.] 27. MyBatis 3.5, Spring Framework 5.4, Oracle 19g - 방법3(SqlMap-XML-Class)     // 결과: 지원, 2020-10-02

    - https://yyman.tistory.com/1440



33. 결과


작업한 내용을 출력한 결과는 다음과 같다.



그림 23. 결과 모습(Java 방식) - XML Mapper - Spring Beans 객체 방식 적용 (Spring 전용)



그림 24. 프로젝트 구성도




34. 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">


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


</web-app>





35. com.example.spbatis.db - SqlMapSessionFactory.java


package com.example.spbatis.db;



import java.io.IOException;

import java.io.InputStream;

import java.sql.SQLException;


import javax.sql.DataSource;


import org.apache.ibatis.io.Resources;

import org.apache.ibatis.mapping.Environment;

import org.apache.ibatis.session.Configuration;

import org.apache.ibatis.session.SqlSessionFactory;

import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import org.apache.ibatis.transaction.TransactionFactory;

import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory;

import org.mybatis.spring.SqlSessionFactoryBean;

import org.springframework.core.io.support.PathMatchingResourcePatternResolver;


import com.example.spbatis.mapper.CompUsersMapper;

import com.example.spbatis.model.CompUsers;


import oracle.jdbc.pool.OracleDataSource;


public class SqlMapSessionFactory {


private static SqlMapSessionFactory factory = new SqlMapSessionFactory();

private final static String driverName = "oracle.jdbc.driver.OracleDriver";

private final static String dbUrl = "jdbc:oracle:thin:@127.0.0.1:1521:orcl";

private final static String userName = "사용자계정";

private final static String userPassword = "비밀번호";

public static SqlSessionFactory ssf;


public static SqlMapSessionFactory getInstance() {

return factory;

}

private SqlMapSessionFactory () {    }

static {

/* 방법1

DataSource dataSource = getOracleDataSource();

TransactionFactory transactionFactory = new JdbcTransactionFactory();

Environment environment = new Environment("development", transactionFactory, dataSource);

Configuration configuration = new Configuration(environment);

configuration.addMapper(CompUsersMapper.class);

ssf = new SqlSessionFactoryBuilder().build(configuration);

*/

}

    

    public static SqlSessionFactory getSqlSessionFactory(){

   


/* 방법2: 공식 메뉴얼 참고 */

DataSource dataSource = getOracleDataSource();


SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean(); // Spring Framework만 지원

factoryBean.setDataSource(dataSource);

try {

//쿼리가 정의된 xml 파일들의 위치 지정

/*

        factoryBean.setMapperLocations(

                new PathMatchingResourcePatternResolver().getResources("com/example/spbatis/mapper/*.xml")

        );

        */

    

ssf = factoryBean.getObject();

// 클래스 등록

ssf.getConfiguration().addMapper(CompUsersMapper.class);

} catch (Exception e) {

e.printStackTrace();

}

   

    // 방법 1, 방법 2 공통

        return ssf;

    }

    

    /*

* Description: 순정 오라클 데이터소스

*/

    private static DataSource getOracleDataSource(){


    OracleDataSource oracleDS = null;


    try {

            oracleDS = new OracleDataSource();

            oracleDS.setURL(dbUrl);

            oracleDS.setUser(userName);

            oracleDS.setPassword(userPassword);


        } catch (SQLException e) {

            e.printStackTrace();

        }


        return oracleDS;


    }

    

}



파일명: SqlSessionFactory.java


[첨부(Attachments)]

SqlMapSessionFactory.zip





36. com.example.spbatis.mapper - CompUsersMapper.java


package com.example.spbatis.mapper;


import java.util.List;


import org.apache.ibatis.annotations.Mapper;

import org.apache.ibatis.annotations.Select;


import com.example.spbatis.model.CompUsers;


@Mapper

public interface CompUsersMapper {

@Select("SELECT * FROM comp_users")

List<CompUsers> selectAll();

}


파일명: CompUsersMapper.java


[첨부(Attachments)]

CompUsersMapper.zip





37. com.example.spbatis.dao - CompUsersDao.java


package com.example.spbatis.dao;


import java.util.List;


import org.apache.ibatis.session.SqlSession;

import org.apache.ibatis.session.SqlSessionFactory;

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


import com.example.spbatis.db.SqlMapSessionFactory;

import com.example.spbatis.mapper.CompUsersMapper;

import com.example.spbatis.model.CompUsers;



public class CompUsersDao {


    SqlSessionFactory factory = SqlMapSessionFactory.getSqlSessionFactory();

    

    public CompUsersDao() {

        

    }

    

    // SQL 세션 열기

    public List<CompUsers> selectAddress() {


    List<CompUsers> user = null;

try (SqlSession session = factory.openSession()) {

CompUsersMapper mapper = session.getMapper(CompUsersMapper.class);

user = mapper.selectAll();

// System.out.println("계정명:" + user.getUsername());


}

return user;


    }

    

}



파일명: CompUsersDao.java


[첨부(Attachments)]

CompUsersDao.zip





38. com.example.spbatis.service - CompUsersService.java


package com.example.spbatis.service;


import java.util.List;


import com.example.spbatis.dao.CompUsersDao;

import com.example.spbatis.model.CompUsers;


public class CompUsersService {


private CompUsersDao dao = null;

public CompUsersService() {

dao = new CompUsersDao();

}

public List<CompUsers> getAllCompUsers() {

return dao.selectAddress();

}

 

}



파일명: CompUsersService.java


[첨부(Attachments)]

CompUsersService.zip





39. com.example.spbatis - HomeController.java


package com.example.spbatis;


import java.text.DateFormat;

import java.util.Date;

import java.util.Locale;


import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

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

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.example.spbatis.service.CompUsersService;


/**

 * Handles requests for the application home page.

 */

@Controller

public class HomeController {

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

private CompUsersService compUserService;

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

public String home(Locale locale, Model model) {

logger.info("Welcome home4(Class Mappers) - Java! The client locale is {}.", locale);

Date date = new Date();

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

String formattedDate = dateFormat.format(date);

compUserService = new CompUsersService();

model.addAttribute("serverTime", formattedDate );

model.addAttribute("list", compUserService.getAllCompUsers()) ;

return "home";

}

}



파일명: HomeController.java


[첨부(Attachments)]

HomeController.zip



40. View - Home.jsp


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

    pageEncoding="UTF-8"%>

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

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

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

<%@ page session="false" %>


<html>

<head>

<title>Home</title>

</head>

<body>

<h1>

Hello world!  

</h1>


<P>  The time on the server is ${serverTime}. </P>

<h3>SqlMapSessionFactory 방식(Java - Mapper - Spring 전용 버전)</h3>

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

    ${val.username} / 

    ${val.password} /

    ${val.enabled }<br>

</c:forEach>

<c:if test="${empty list }">

    ${"데이터가 존재하지않아요."}

</c:if>


</body>

</html>



파일명: home.jsp


[첨부(Attachments)]

home.zip




* 5부에서 만나요.


1. [Spring-F.] 29. MyBatis 3.5, Spring Framework 5.4, Oracle 19g - 방법5(SqlMap Spring전용)  // 결과: 지원, 2020-10-02

    - https://yyman.tistory.com/1442



반응형
728x90
300x250

[Spring-F.] 27. MyBatis 3.5, Spring Framework 5.4, Oracle 19g - 방법3(SqlMap-XML-Class)


소스 코드 위주로 소개하도록 하겠다.


[실험 결과]

1. [Spring-Framework] Spring Framework 5.4, MyBatis 3.5 연동 방법 - 실험 결과, 2020-10-02

   - https://yyman.tistory.com/1437


[이전 게시글]

1. [Spring-F.] 26. MyBatis 3.5, Spring Framework 5.4, Oracle 19g - 방법2(SqlMap-XML-XML 맵핑)     // 결과: 지원, 2020-10-02

    - https://yyman.tistory.com/1439



24. 결과


완성된 실험 결과이다.



그림 21. 결과



그림 22. 프로젝트 구성도




25. 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">


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


</web-app>




26. view - home.jsp


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

    pageEncoding="UTF-8"%>

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

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

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

<%@ page session="false" %>


<html>

<head>

<title>Home</title>

</head>

<body>

<h1>

Hello world!  

</h1>


<P>  The time on the server is ${serverTime}. </P>

<h3>SqlMapSessionFactory 방식(XML - 환경설정 - 클래스-Mappers)</h3>

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

    ${val.username} / 

    ${val.password} /

    ${val.enabled }<br>

</c:forEach>

<c:if test="${empty list }">

    ${"데이터가 존재하지않아요."}

</c:if>


<h3>XML - web.xml 설정방식</h3>

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

    ${val.username} / 

    ${val.password} /

    ${val.enabled }<br>

</c:forEach>

<c:if test="${empty list2 }">

    ${"데이터가 존재하지않아요."}

</c:if>


</body>

</html>



파일명: home.jsp


[첨부(Attachments)]

home.zip




27. com.example.spbatis.db - SqlMapSessionFactory.java


package com.example.spbatis.db;



import java.io.IOException;

import java.io.InputStream;


import org.apache.ibatis.io.Resources;

import org.apache.ibatis.session.SqlSessionFactory;

import org.apache.ibatis.session.SqlSessionFactoryBuilder;


import com.example.spbatis.mapper.CompUsersMapper;


public class SqlMapSessionFactory {

public SqlSessionFactory ssf;

public SqlMapSessionFactory () {


        String resource = "com/example/spbatis/mapper/mybatis-config.xml";

        InputStream is = null;


        try {

            is = Resources.getResourceAsStream(resource);

        } catch (IOException e) {

            e.printStackTrace();

        }


        ssf = new SqlSessionFactoryBuilder().build(is);

        ssf.getConfiguration().addMapper(CompUsersMapper.class);


    }

    

    public SqlSessionFactory getSqlSessionFactory(){

        return ssf;

    }

    

}



파일명: SqlMapSessionFactory.java


[첨부(Attachments)]

SqlMapSessionFactory.zip





28. com.example.spbatis.mapper - mybatis-config.xml


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


<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" 

"http://mybatis.org/dtd/mybatis-3-config.dtd">


<configuration>


<environments default="development">

    <environment id="development">

      <transactionManager type="JDBC"/>

      <!-- 커넥션 풀(MyBatis) -->

      <dataSource type="POOLED">

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

        <property name="url" value="jdbc:oracle:thin:@127.0.0.1:1521:orcl"/>

        <property name="username" value="UserName"/>

        <property name="password" value="Password"/>

        <property name="poolMaximumActiveConnections" value="20"/>

        <property name="poolMaximumIdleConnections" value="20"/>

        <property name="poolMaximumCheckoutTime" value="20000"/>

        <property name="poolPingEnabled" value="true"/>

        <property name="poolPingQuery" value="select 1"/>

        <property name="poolPingConnectionsNotUsedFor" value="10000"/>

        <property name="poolTimeToWait" value="15000"/>

      </dataSource>

    </environment>

</environments>


</configuration>


파일명: mybatis-config.xml


[첨부(Attachments)]

mybatis-config.zip




29. com.example.spbatis.mapper - CompUsersMapper.java


package com.example.spbatis.mapper;


import java.util.List;


import org.apache.ibatis.annotations.Mapper;

import org.apache.ibatis.annotations.Select;


import com.example.spbatis.model.CompUsers;


@Mapper

public interface CompUsersMapper {

@Select("SELECT * FROM comp_users")

List<CompUsers> selectAll();

}


파일명: CompUsersMapper.java


[첨부(Attachments)]

CompUsersMapper.zip




30. com.example.spbatis.dao - CompUsersDao.java


package com.example.spbatis.dao;


import java.util.List;


import org.apache.ibatis.session.SqlSession;

import org.apache.ibatis.session.SqlSessionFactory;

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


import com.example.spbatis.db.SqlMapSessionFactory;

import com.example.spbatis.mapper.CompUsersMapper;

import com.example.spbatis.model.CompUsers;



public class CompUsersDao {

    private SqlMapSessionFactory ssfc;

    private SqlSessionFactory factory;

    

    public CompUsersDao() {

   

        ssfc = new SqlMapSessionFactory();

        factory = ssfc.getSqlSessionFactory();

        

    }

    

    // SQL 세션 열기

    public List<CompUsers> selectAddress() {


    List<CompUsers> user = null;

   

try (SqlSession session = factory.openSession()) {

CompUsersMapper mapper = session.getMapper(CompUsersMapper.class);

user = mapper.selectAll();

// System.out.println("계정명:" + user.getUsername());


}

return user;


    }

    

}



파일명: CompUsersDao.java


[첨부(Attachments)]

CompUsersDao.zip





31. com.example.spbatis.service - CompUsersService.java


package com.example.spbatis.service;


import java.util.List;


import com.example.spbatis.dao.CompUsersDao;

import com.example.spbatis.model.CompUsers;


public class CompUsersService {


private CompUsersDao dao = null;

public CompUsersService() {

dao = new CompUsersDao();

}

public List<CompUsers> getAllCompUsers() {

return dao.selectAddress();

}

 

}



파일명: CompUsersService.java


[첨부(Attachments)]

CompUsersService.zip





32. com.example.spbatis - HomeController.java


package com.example.spbatis;


import java.text.DateFormat;

import java.util.Date;

import java.util.Locale;


import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

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

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.example.spbatis.service.CompUsersService;


/**

 * Handles requests for the application home page.

 */

@Controller

public class HomeController {

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

private CompUsersService compUserService;

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

public String home(Locale locale, Model model) {

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

Date date = new Date();

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

String formattedDate = dateFormat.format(date);

compUserService = new CompUsersService();

model.addAttribute("serverTime", formattedDate );

model.addAttribute("list", compUserService.getAllCompUsers()) ;

return "home";

}

}



파일명: HomeController.java


[첨부(Attachments)]

HomeController.zip



* 4부에서 만나요.


1. [Spring-F.] 28. MyBatis 3.5, Spring Framework 5.4, Oracle 19g - 방법4(SqlMap Spring전용)   // 결과: 지원, 2020-10-02

https://yyman.tistory.com/1441


반응형
728x90
300x250

[Spring-Framework] 21(번외). STS 4.4 - Spring Boot Starter 프로젝트 생성(MVC)


나의 글에서 주로 Spring Legacy Project로 환경구축에 대해서 다루었다.

하지만, 초기 STS 4.4 최신버전을 설치하면 Spring Legacy Project는 따로 구성해줘야 사용할 수 있게 된다.

(Help -> Eclipse Marketplace -> "검색어: sts" -> "Spring Tools 3 Add-on for Spring Tools 4 3.9.14.RELEASE")


Spring Boot를 소개하게 된 건, 셋팅에 있어서 그동안 조금 복잡한 과정을 거쳐야 했었는데 그런 걸 "통폐합"해서 간단하게 사용할 수 있도록 도와주고 있다.


알 필요성이 있다고 생각되서 작성하게 되었다.


[기대 효과]

(장점)

1. 복잡한 셋팅을 안 해도 된다

2. 빠른 작업이 가능해진다.


(단점)

1. Spring Framework 위주의 자동생성에서 벗어나질 못한다. ???






1. 프로젝트 생성하기


처음으로 Spring Starter Project를 생성하는 방법에 대해서 소개하도록 하겠다.



그림 1. 프로젝트 시작하기


File -> New -> Spring Starter Project를 클릭한다.



그림 2. 프로젝트 시작하기(2)


셋팅을 조금 해주면 된다.


Group명, Artifacte, Package, Description 등을 수정해도 된다.

자바 버전 등도 셋팅할 수 있다.

셋팅이 완료되었다면, Next를 클릭한다.



그림 3. 프로젝트 시작하기(3)


MySQL Driver, Oracle Driver, Spring Security, Spring Web Services를 체크한다.

Next를 누른다.



그림 4. 프로젝트 시작하기(4)


Finish를 누르면 프로젝트가 생성된다.



2. Spring Boot(Spring Starter)에서는 서블렛(Servlet) 지원하나요?


Servlet 기능이 되는지 궁금한 분들을 위해서 작성하였다.



그림 5. Servlet 생성하기 전의 모습 (결론: 생성 안 됨.)


Next를 클릭해보면, 생성할 수 없다고 나온다.


3. Run - Hello World


Spring Security를 체크한 경우에는 아래의 화면을 볼 수 있다.

Hello World 화면이라고 생각하면 된다.



그림 6. Run 누르면, 내장 톰캣으로 돌아감.


Run 아이콘을 클릭하면, 내장 톰캣 서버가 돌아간다.

웹 브라우저를 수동으로 열어서 호출 시켜보면 이런 화면이 나오면 정상이라고 보면 된다.



4. REST - 활용한 Controller "Hello, World"


REST에 대해서 소개한 적이 있다.

SpringBoot 데모에서는 JSP 파일이 없어서 REST로 태스트를 진행해야 한다.



그림 7. 클래스 만들기(1)


com.spring. (패키지폴더)를 마우스 오른쪽 버튼으로 클릭한다.

New -> Class를 클릭한다.



그림 8. 클래스 만들기(2)


예로 HomeController라고 입력하고 Finish를 누른다.

이름을 임의로 임력한다고 해서 큰 문제가 되진 않는다.




그림 9. 콘트롤러 코드 작성하기


이처럼 코드를 작성해준다.


package com.springmvc.home;


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

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

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


@RestController

public class HomeController {

@RequestMapping("/")

public @ResponseBody String home() throws Exception{

return "home";

}

}




그림 9-1, 그림 9-2. 서버 실행과 내장 웹 브라우저 사용방법, JavaEE 인터페이스 화면


모르겠으면 한번씩 눌러보길 바란다.




그림 10. 빌드 - 웹 브라우저 열어보기(1)


계정 아이디: user

비밀번호는 Using generated security password에 생성된 보안키가 비밀번호이다.


입력하고 로그인을 눌러본다.



그림 11. 빌드 - 웹 브라우저 열어보기(2)


내장 이클립스 웹 브라우저에서는 화면이 안 보이는데, 엣지나 크롬의 경우에서는 출력된 REST 화면을 볼 수 있다.




5. Web기반 - Controller 작성하기


이번에는 다소 세팅 작업이 몇 가지가 있는데 일반 jsp 웹 페이지를 출력할 수 있는 Controller(컨트롤러) 생성에 대해서 소개하겠다.



그림 12. 클래스 생성하기 (1)


패키지를 마우스 오른쪽 버튼으로 클릭한다.

New->Class를 클릭한다.




그림 13. 클래스 생성하기 (2)


Superclass의 Browse를 클릭한다.

WebSecu를 검색하면, "WebSecurityConfigurerAdapter를 선택한다.

OK를 누른다.


클래스명(Name)은 WebSecConfig를 입력한다.

Finish를 누른다.



그림 14. 클래스 생성하기 (3)


그림 14처럼 생성되면 잘 생성된 것이다.

복잡하게 코드를 만드는 게 아니다.



그림 15. 클래스 생성하기 (4)


Source -> Override/Implement Methods를 클릭한다.




그림 16. Override / Implement Methods


configure(HttpSecurity)를 체크하고 OK를 누른다.





5-1 Web기반 - SecurityConfig 설정하기


이 글을 조금 심화적으로 이해하려면, Spring Security 부분을 참고하면 된다.

자랑하는 건 아니지만, 필자의 글이 가장 잘 나와있다고 소개하고 싶다.



그림 17. Spring Security 설정하기



package com.springmvc.home.security;


import org.springframework.security.config.annotation.web.builders.HttpSecurity;

import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;


public class WebSecurityConfig extends WebSecurityConfigurerAdapter {


@Override

protected void configure(HttpSecurity http) throws Exception {

http.authorizeRequests()

.antMatchers("/").permitAll()

.antMatchers("/welcome").permitAll()

.antMatchers("/page1").hasRole("ADMIN")

.anyRequest().authenticated();

}


}



파일명: WebSecurityConfig.java


[첨부(Attachments)]

WebSecurityConfig.zip




5-2 Web기반 - HomeController.java 파일 수정하기


파일 수정을 조금 해줘야 한다.

아까 전에 만든 HomeController를 변형하도록 하겠다.


파일: com.springmvc.home.HomeController.java



그림 18. HomeController.java 만들기


package com.springmvc.home;


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

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

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


@RestController

public class HomeController {

@RequestMapping("/")

public @ResponseBody String home() throws Exception{

return "home";

}


@RequestMapping("/page1")

public @ResponseBody String page1() throws Exception{

return "Spring Boot : 1";

}

@RequestMapping("/page2")

public @ResponseBody String page2() throws Exception{

return "Spring Boot : 2";

}

}



파일명: HomeController.java


[첨부(Attachments)]

HomeController.zip


이전의 STS ("Legacy로 작업할 때, 웹 브라우저에 자동으로 재빌드되었다.")와는 다른 점이 빌드가 조금 느리게 반응하거나 수동 빌드를 해줘야 한다.

화면이 안 바뀌면, 다시 실행(Run)을 해보기 바란다. 버그가 전혀 없는 건 아니다.




그림 19. 출력 결과 - 확인하기(1)






그림 20. 출력 결과 - 확인하기(2)





6. Web기반 - WelcomeController 생성(Controller)


그림 20의 문제를 해결할 겸 Web기반 페이지를 작성하는 방법에 대해서 소개하겠다.



그림 21. 패키지 오른쪽 버튼 메뉴


com..... 패키지를 선택한다.

마우스 오른쪽 버튼 클릭한 후, New-> Class를 클릭한다.




그림 22. WelcomeController.java 생성하기


Name: "WelcomeController"

Finish를 클릭한다.



그림 23. 코드를 입력한 상태의 WelcomeController


초기에는 코드가 전혀 입력되어 있지 않다.

그림 23처럼 입력해준다.


package com.springmvc.home;


import org.springframework.stereotype.Controller;

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


@Controller

public class WelcomeController {


@RequestMapping("/welcome")

public String welcome() {

return "welcome";

}

}



파일명: WelcomeController.java


[첨부(Attachments)]

WelcomeController.zip






7. application.properties 설정 - 웹 경로


웹 페이지를 사용하려면, 경로를 설정해줘야 한다.

이전 Spring Legacy나 maven project로 프로젝트를 생성했다면, web.xml가 존재했었다.

application.properties로 통합된 것으로 보인다.




그림 24. 코드를 입력한 상태의 application.properties


spring.mvc.view.prefix=/WEB-INF/views/

spring.mvc.view.suffix=.jsp


파일명: application.properties


[첨부(Attachments)]

application.zip




7-1. 웹 홈페이지 폴더와 jsp폴더 생성 - 웹 경로


이번에는 jsp 파일의 폴더를 생성하도록 하겠다.



그림 25. 폴더 만들기(1)


src/main 폴더를 오른쪽 버튼으로 클릭한다.

New->Folder를 클릭한다.




그림 26. 폴더 만들기(2)


webapp/WEB-INF/views를 입력한다.

Finish를 클릭한다.




그림 27. 파일 만들기


/src/main/webapp/WEB-INF/views 폴더 내에 파일을 만들어준다.

welcome.jsp 파일을 만든다.


서버를 재시작해준다.



그림 28. 로그인 후의 welcome(URL 주소)


그림 28의 화면이 뜨면, 잘 된 것이다.



7-2. CSS, Images, Javascript 경로


Css/images/Javascript의 경로에 관한 것이다.



그림 29. 결과 - 외부 CSS 적용


그림 29는 css 스타일이 적용된 결과이다. 



7-2-1. /src/main/java/resources/static/css/style.css


css 폴더는 /src/main/java/resources/static 내에 만들어주면 된다.

그리고 style.css 파일은 /src/main/java/resources/static/css 폴더에 만들어주면 된다.



그림 30. Style.css 위치



7-2-2. index.jsp 파일 수정하기


index.jsp 파일을 수정해주면 된다.



그림 31. index.jsp 파일 수정하기


<link rel="stylesheet" href="/css/style.css">


서버를 재시작하면 결과를 볼 수 있다.



그림 32. 출력 결과

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

[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 프로젝트에 대해서 잘 설명되어 있음.


반응형

+ Recent posts