728x90
300x250

[JSP] 23(번외). JSP/Servlet - MVC2 index.do 시작페이지 만들기 (FrontController, Command패턴)



index.html이나 index.jsp 페이지처럼 시작페이지를 index.do로 할 수 없는지에 대한 글이다.




1. /src/main/webapp/index.jsp - 수정하기


<jsp:forward page="index.do" />를 넣어준다.



그림 1. index.jsp 수정하기


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

    pageEncoding="UTF-8"%>

<jsp:forward page="index.do" />


파일명: index.jsp



2. web.xml - 수정하기


web,xml에 <welcome-file-list><welcome-file>을 만들어준다.



그림 2. web.xml 수정하기


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

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

xmlns="http://java.sun.com/xml/ns/javaee" 

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

id="WebApp_ID" version="3.0">

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

  <welcome-file-list>

  <welcome-file>index.jsp</welcome-file>

  </welcome-file-list>

  <servlet>

  <servlet-name>FrontController</servlet-name>

  <servlet-class>com.example.web.controller.FrontController</servlet-class>

  <init-param>

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

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

</init-param>

  </servlet>

  <servlet-mapping>

  <servlet-name>FrontController</servlet-name>

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

  </servlet-mapping>

</web-app>


파일명: web.xml


[첨부(Attachments)]

web.zip




3. FrontController.java - 수정하기


서블릿으로 작성한 FrontController.java를 수정해준다.



그림 3. FrontController.java


아래의 소스 코드는 HttpUtil.java에 관한 코드이다.


package com.example.web.util;


import java.io.IOException;


import javax.servlet.RequestDispatcher;

import javax.servlet.ServletException;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;


public class HttpUtil extends HttpServlet {


private static final long serialVersionUID = 1L;


private static String charset = null;


public static void forward(HttpServletRequest req, HttpServletResponse res,

String path) throws ServletException, IOException {


try {

RequestDispatcher dispatcher = req.getRequestDispatcher(path);

dispatcher.forward(req, res);


}catch(Exception e) {

e.printStackTrace();

}

}

}


파일명: HttpUtil.java


[첨부(Attachments)]

HttpUtil.zip





* 맺음글(Conclusion)


간단한 형태로 시작페이지를 지정하는 방법에 대해서 소개하였다.

반응형
728x90
300x250

[JSP] 22. JSP/Servlet MVC2 - jQuery기반의 Ajax POST 전송 및 MVC패턴 Action 식별자


jQuery를 활용하는 방법에 대해서 소개하려고 한다.

그림 일기 수준으로 매우 편안한 마음으로 입문할 수 있는 학습 기반을 제공해주려고 한다.

심도적인 부분은 전문서적 등도 찾아보기도 하고, 검색도 많이 해보시면 좋을 듯 싶다. (변화가 워낙 빠른 분야인 만큼)



1. 결과


동적인 부분인 관계로 영상으로 올려주도록 하겠다.



영상 1. 출력 결과


jQuery가 어떤 결과물을 만들어 내는 도구인지 이해가 되었으면 하는 바램이다.

원래는 jQuery가 먼저 나온 것이 아니고, Javascript가 먼저이다.


그리고 2006년도에 약 Ajax라는 규격이 나왔는데, Javascript 파일 형태로 ajax 파일을 배포하여 동적인 처리에 대해서 접근하게 되었다.


그리고 조금 시간이 지나서 jQuery라는 게 나왔는데, 분명한 건 이건 표준은 아니다.

다만, 편하게 사용하도록 도와주는 오픈소스 진형의 library이다.




2. 프로젝트 생성하기


이러한 저차원 수준으로 작성한 이유는 프로그래밍에 겁먹지 말라는 것이다.



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


File -> New -> Maven Project를 클릭한다.



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


org.apache.maven.archetypes | maven-archetype-webapp를 선택한다.

Next를 클릭한다.


검색 키워드로 검색할 때, "webapp"로 하면, 조금 찾는데 시간이 절약될 수 있다.

다만, HDD 사용자는 조금 버벅될 가능성이 있다. (검색 기능이 매우 느림.)




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


GroupId, Artifact Id를 적당히 입력한 후 Finish를 누른다.



3. Pom.xml - 설정하기


http://mvnrepository.com에 들어가서 "servlet"을 검색해서 최신 버전으로 해준다.

Maven Project를 아끼고 있는 이유는 정말 사용하기가 편리하다.


셋팅하는데, /src/main/webapp/WEB-INF/lib인가 폴더에 넣고, 프로젝트 속성에 들어가서 BuildPath 클릭하고 Add External Library 등록하고 

확인 몇 번하고 복잡했는데, Maven을 알게 되면서 많이 좋아진 것 같다.



그림 4. pom.xml


<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">

  <modelVersion>4.0.0</modelVersion>


  <groupId>com.webedu</groupId>

  <artifactId>exampleAjax</artifactId>

  <version>0.0.1-SNAPSHOT</version>

  <packaging>war</packaging>


  <name>exampleAjax Maven Webapp</name>

  <!-- FIXME change it to the project's website -->

  <url>http://www.example.com</url>


  <properties>

    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

    <maven.compiler.source>1.7</maven.compiler.source>

    <maven.compiler.target>1.7</maven.compiler.target>

  </properties>


  <dependencies>

    <dependency>

      <groupId>junit</groupId>

      <artifactId>junit</artifactId>

      <version>4.11</version>

      <scope>test</scope>

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

  </dependencies>


  <build>

    <finalName>exampleAjax</finalName>

    <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->

      <plugins>

        <plugin>

          <artifactId>maven-clean-plugin</artifactId>

          <version>3.1.0</version>

        </plugin>

        <!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging -->

        <plugin>

          <artifactId>maven-resources-plugin</artifactId>

          <version>3.0.2</version>

        </plugin>

        <plugin>

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

          <version>3.8.0</version>

        </plugin>

        <plugin>

          <artifactId>maven-surefire-plugin</artifactId>

          <version>2.22.1</version>

        </plugin>

        <plugin>

          <artifactId>maven-war-plugin</artifactId>

          <version>3.2.2</version>

        </plugin>

        <plugin>

          <artifactId>maven-install-plugin</artifactId>

          <version>2.5.2</version>

        </plugin>

        <plugin>

          <artifactId>maven-deploy-plugin</artifactId>

          <version>2.8.2</version>

        </plugin>

      </plugins>

    </pluginManagement>

  </build>

</project>



파일명: pom.xml


[첨부(Attachments)]

pom.zip




4. Project Factes와 Build Path - 자바 버전 바꿔주기


자바 버전을 변경해줘야 한다. Maven Project 초기 셋팅이 현재 1.6으로 잡혀서 생성되기 때문이다.



그림 5. 프로젝트의 오른쪽 메뉴 모습


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

Properties를 클릭한다.



그림 6. Build-Path


JRE System Library [JavaSE-14]로 바꿔준다.

Edit 버튼을 누르면 바꿀 수 있다.



그림 7. Project Factes


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




5. jQuery 사이트 - 접속하기


인터넷 웹 브라우저를 켠다.


그림 8. 윈도우 10 - 엣지 클릭하기


웹 브라우저 아이콘을 못 찾는 경우에는 그림처럼 생긴 거 클릭하면 된다. 

(그 옆에도 비슷하게 생긴 e자 아이콘을 클릭해도 무방하다.)



그림 11. jQuery 웹 사이트 접속하기


https://jquery.com/download


링크를 웹 주소창에 입력해서 접속한다.

또는 클릭해도 무방하다.


표기해놓은 것 5개 중 하나만 잘 다운로드 받으면 된다.




그림 12. jQuery 다운받기


문서 클릭\workspace-spring-tool-suite-4-4.7.2.RELEASE\{프로젝트명}\src\main\webapp\js에 저장해준다.

js폴더가 없으니깐 하나 만들어준다.

js폴더 안에 저장해준다.



영상 2. jQuery 다운로드 받는 모습



6. jQuery - ajaxPost - API 접속하기


https://api.jquery.com/jquery.post/


사이트에 접속해준다.



그림 13. jQuery 예제


이렇게 생긴 HTML태그를 복사하여 Eclipse에 옮겨갈 것이다.

참고로 이 코드가 완벽한 코드는 절대 아니다. (태스트 해 봤음.)




그림 14. index.jsp 파일에 복사 붙여넣기 해주기


그림 14와는 다르게 태스트를 완료한 코드는 아래에 있으니 참고하면 되겠다.

WEB-INF내에 views폴더 생성해준다.

그리고 index.jsp 파일을 views 폴더 안으로 이동해준다.



영상 3. views 폴더 생성 방법 및 파일 이동 시키기



그림 15. 이동을 완료한 모습 - views 폴더 내용


<!doctype html>

<html lang="en">

<head>

<meta charset="utf-8">

<title>jQuery.post demo</title>

<script src="js/jquery-3.5.1.js"></script>


</head>

<body>

 

<form action="board/insert.do" id="searchForm">

  <input type="text" name="s" placeholder="Search...">

  <input type="submit" value="Search">

</form>

<div id="result"></div>


<script type="text/javascript">

// Attach a submit handler to the form

$( "#searchForm" ).submit(function( event ) {

 

  // Stop form from submitting normally

  event.preventDefault();

 

// Get some values from elements on the page:

  var $form = $( this ),

    term = $form.find( "input[name='s']" ).val(),

    url = $form.attr( "action" );

 

  // Send the data using post

  var posting = $.post( url, { s: term } );

 

  // Put the results in a div

  posting.done(function( data ) {

    alert( "Data Loaded: " + data );

    var content = data ;

    $( "#result" ).html( content );

   

  });

 

});


</script>

<!-- the result of the search will be rendered inside this div --> 

 

</body>

</html>


파일명: index.jsp


[첨부(Attachments)]

index.zip




7. Servlet 작성하기


MVC2 패턴을 만들거니깐 서블렛을 잘 따라 해야 한다.



그림 16. Java Resources 폴더 - 마우스 오른쪽 버튼 메뉴 모습


Java Resources 폴더를 선택한 후, 마우스 오른쪽 버튼으로 클릭한다.

New-> Servlet을 클릭한다.



그림 17. Servlet 생성 작업창 - 모습 (Create Servlet)


Java Package명을 입력한다. (예: com.example.web.controller)

Class Name명을 입력한다. (예: FrontController)


Finish를 누른다.



8. web.xml 파일 - 수정작업하기


경로 위치: /src/main/webapp/WEB-INF/web.xml


문자열하고, FrontController의 *.do로 변경 작업을 해주면 된다.



그림 18. web.xml - 수정작업하기


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

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

xmlns="http://java.sun.com/xml/ns/javaee" 

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

id="WebApp_ID" version="3.0">

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

  <servlet>

  <servlet-name>FrontController</servlet-name>

  <servlet-class>com.example.web.controller.FrontController</servlet-class>

  <init-param>

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

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

</init-param>

  </servlet>

  <servlet-mapping>

  <servlet-name>FrontController</servlet-name>

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

  </servlet-mapping>

</web-app>



파일명: web.xml


[첨부(Attachments)]

web.zip




9. Class 만들기 - HttpUtil


HttpUtil 클래스를 만들어주려고 한다.



그림 19. Java Resources의 오른쪽 버튼 메뉴 모습


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

New->Class를 클릭한다.



그림 20. 클래스 생성 마법사 모습


Package명은 com.example.web.util

Name은 HttpUtil로 한다.


Finish를 누른다.





그림 21. 코드를 입력한 모습 - HttpUtil.java


package com.example.web.util;


import java.io.IOException;


import javax.servlet.RequestDispatcher;

import javax.servlet.ServletException;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;


public class HttpUtil extends HttpServlet {


private static final long serialVersionUID = 1L;


private static String charset = null;


public static void forward(HttpServletRequest req, HttpServletResponse res,

String path) throws ServletException, IOException {


try {

RequestDispatcher dispatcher = req.getRequestDispatcher(path);

dispatcher.forward(req, res);


}catch(Exception e) {

e.printStackTrace();

}

}

}


파일명: HttpUtil.java


[첨부(Attachments)]

HttpUtil.zip



10. Controller - Interface 만들기


Controller 인터페이스를 하나 만들 것이다.



그림 22. Controller.java


package com.example.web.controller;


import java.io.IOException;

import javax.servlet.ServletException;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;


public interface Controller {


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


}




파일명: Controller.java


[첨부(Attachments)]

Controller.zip



11. InsertController.java - Class


앞서 만든 Interface(Controller)로 InsertController.java를 작성할 것이다.



그림 23. InsertController.java


Package 명은 com.example.web.board라고 입력한다.

Name명은 InsertController라고 입력한다.


Interfaces의 Add버튼을 누른다.



그림 24. Implemented Interfaces.......


Controller를 입력한 후 작성한 Controller 인터페이스를 선탁한다.

OK를 누른다.

Finish를 누른다.


package com.example.web.controller.board;


import java.io.IOException;


import javax.servlet.ServletException;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;


import com.example.web.controller.Controller;

import com.example.web.util.HttpUtil;


public class InsertController implements Controller {


@Override

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

HttpUtil.forward(req, res, "/WEB-INF/views/board/insert.jsp");


}


}



파일명: InsertController.java


[첨부(Attachments)]

InsertController.zip



13. FrontController - 코드 작성하기 (수정)


코드를 자세히 보면, flag가 추가되었다.

doAction에서 POST, GET 등을 인식할 수 있게 되었다.


package com.example.web.controller;


import java.io.IOException;


import javax.servlet.ServletConfig;

import javax.servlet.ServletException;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;


import com.example.web.controller.board.InsertController;

import com.example.web.util.HttpUtil;


public class FrontController extends HttpServlet {

private static final long serialVersionUID = 1L;

private String charset = null;

       

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

doAction(req, res, "GET");

}


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

       doAction(req, res, "POST");

}


protected void doAction(HttpServletRequest req, 

HttpServletResponse res,

String flag) 

throws ServletException, IOException {

ServletConfig sc = this.getServletConfig();

charset = sc.getInitParameter("charset");


req.setAttribute("charset", charset);

req.setCharacterEncoding(charset);

res.setContentType("text/html; charset=" + charset);


String uri = req.getRequestURI();

String conPath = req.getContextPath();

String command = uri.substring(conPath.length());


Controller subController = null;


// POST 전송방식만

if(command.equals("/board/insert.do") && 

flag.contentEquals("POST")){


System.out.println("insert");

System.out.println("----------------");

subController = new InsertController();

subController.execute(req, res);

}else if (command.equals("/index.do")){

HttpUtil.forward(req, res, "/WEB-INF/views/index.jsp");

}

}

}



파일명: FrontController.java


[첨부(Attachments)]

FrontController.zip



14. View - webapp/WEB-INF/views/board/insert.jsp


POST처리 후에 출력할 페이지를 작성하도록 하겠다.

PrintWriter out으로 해도 무방하지만, MVC패턴을 적용했으니 뷰 파일에서 작성하겠다.


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

    pageEncoding="UTF-8"%>

<%

String text = (String)request.getParameter("s");

%>

<%= text %>


파일명: insert.jsp


[첨부(Attachments)]

insert.zip



* 맺음글(Conclusion)


jQuery를 통해서 ajax 전송에 대해서 간단한 형태로 살펴보았다.

반응형
728x90
300x250

[JSP] 17. JSP/Servlet MVC2 - 페이징네이션과 검색 그리고 오라클 프로젝트 (1)


Command 패턴과 Front Controller 패턴을 적용한 페이징네이션과 검색에 대해서 소개하려고 한다.

불필요한 기능은 다 제거하고 순수한 페이징네이션과 검색 그리고 오라클 연동에 대해서 다뤄보았다.


IDE: Spring-Tool Suite 4-4.7.2 RELEASES

Databases: Oracle Databases 19g

 - Maven 3.6.3/1.16.0.20200610-1735

 - javax.servlet-api (4.0.1) - servlet(서블렛)

 - jstl (1.2) - jstl 태그 적용

 - taglibs (1.1.2) - c태그 적용

 - HikariCP (3.4.2) - 커넥션 풀

 - com.oracle.database.jdbc - ojdbc8 (19.7.0.0)



[쿼리 관련해서 조금 더 보충한 글이다.]
1. [Oracle Databases] 번외글 - 게시판 페이징 관련 로직 쿼리, 2020-10-11.
- https://yyman.tistory.com/1466




1. 프로젝트 구조


작성할 프로젝트를 미리 살펴보면 조금 작업해야 할 양이 의외로 상당하다는 것을 알 수 있다.



그림 1, 그림 2. 프로젝트 작성 구조도




2. 게시판 - 설계


데이터베이스 설계는 매우 간단하게 작성하였다.


그림 3. Board - 테이블 설계(1)




그림 4. Board 게시판 설계(2)





3. 사용자 인터페이스 - 결과


이번 주제에서 다뤄볼 프로젝트의 완성 모습이다.

참고로 페이징네이션 로직에 대해서 다 기억할 수 없다.


다만 어떤 흐름인지는 대략적으로 알고는 있으면 하는 바람이다.

워낙 페이징 로직에 대해서 전문적으로 잘 연구하시는 분들이 많이 계시니깐 그건 골고루 참고도 해보고 개선도 해보고 하면 될 것 같다.



그림 5. list.do - 첫 화면



그림 6. list.do - 7번 페이지 / 기초



그림 7. list.do - 10106번 페이지 / 기초


10106번 페이지를 통해서 알 수 있는 것은 약 10106 * 10 = 101,106개의 DB가 존재한다는 것을 알 수 있다.

그림 8부터는 응용부분에 가까워진다.



그림 8. list.do - 키워드 검색 및 페이징 처리(1) / 심화


의외로 응용력이 많이 요구되는 부분이다.



그림 9. list.do - 키워드 검색 및 페이징 처리(2) / 심화


키워드 검색을 했을 때 "친"은 약 13개가 있었다는 사실을 유추할 수 있다.



그림 10. list.do - 키워드 검색 및 페이징 처리(3)


참고로 list.do 반응에 대해서 여러 조건으로 튜닝이 필요하다.



4. 프로젝트 생성하기


프로젝트는 Maven Project로 생성하여 진행하였다.



그림 11. Maven Project 생성하기(1)


File -> New -> Maven Project를 클릭한다.



그림 12. Maven Project 생성하기(2)


org.apache.maven.archetypes | maven-archetype-web을 선택하고 Next를 누른다.



그림 13. Maven Project 생성하기(3)


프로젝트의 Group Id, Artifact Id를 입력한다.

Finish를 누른다.




5. POM.xml - 설정하기


다음은 pom.xml 파일에 대한 설정이다.


<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">

  <modelVersion>4.0.0</modelVersion>


  <groupId>com.boardMaven</groupId>

  <artifactId>web</artifactId>

  <version>0.0.1-SNAPSHOT</version>

  <packaging>war</packaging>


  <name>board Maven Webapp</name>

  <!-- FIXME change it to the project's website -->

  <url>http://www.example.com</url>


  <properties>

    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

    <maven.compiler.source>1.7</maven.compiler.source>

    <maven.compiler.target>1.7</maven.compiler.target>

  </properties>


  <dependencies>

    <dependency>

      <groupId>junit</groupId>

      <artifactId>junit</artifactId>

      <version>4.11</version>

      <scope>test</scope>

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

<!-- JSTL -->

<dependency>

<groupId>javax.servlet</groupId>

<artifactId>jstl</artifactId>

<version>1.2</version>

</dependency>

<!-- taglibs -->

<dependency>

<groupId>taglibs</groupId>

<artifactId>standard</artifactId>

<version>1.1.2</version>

<scope>compile</scope>

</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.7.0.0</version>

</dependency>

  </dependencies>


  <build>

    <finalName>board</finalName>

    <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->

      <plugins>

        <plugin>

          <artifactId>maven-clean-plugin</artifactId>

          <version>3.1.0</version>

        </plugin>

        <!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging -->

        <plugin>

          <artifactId>maven-resources-plugin</artifactId>

          <version>3.0.2</version>

        </plugin>

        <plugin>

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

          <version>3.8.0</version>

        </plugin>

        <plugin>

          <artifactId>maven-surefire-plugin</artifactId>

          <version>2.22.1</version>

        </plugin>

        <plugin>

          <artifactId>maven-war-plugin</artifactId>

          <version>3.2.2</version>

        </plugin>

        <plugin>

          <artifactId>maven-install-plugin</artifactId>

          <version>2.5.2</version>

        </plugin>

        <plugin>

          <artifactId>maven-deploy-plugin</artifactId>

          <version>2.8.2</version>

        </plugin>

      </plugins>

    </pluginManagement>

  </build>

</project>



파일명: pom.xml


[첨부(Attachments)]

pom.zip



6. 프로젝트의 Build-Path, Properties 수정하기


프로젝트의 자바 버전에 대한 환경설정이다.



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


프로젝트를 클릭한다.

마우스 오른쪽 버튼을 누른다.

Properties를 클릭한다.



그림 15. Build-Path 환경설정


JRE System Library를 JavaSE-14버전으로 변경한다. (14버전으로 변경)

Apply를 누른다.



그림 16. Project Facets 환경 설정


Project Facets의 Java 버전을 14로 변경한다.

Apply를 누른다.

Apply and close를 누른다.



7. Resource 폴더와 db.properties 만들기


Resource 폴더와 db.properties를 생성할 것이다.



그림 17. /src/main 폴더 - 오른쪽 버튼 메뉴 모습


src/main 폴더를 마우스 오른쪽으로 클릭한다.

New-> Folder를 클릭한다.


폴더명: Resource



그림 17. /src/main/resource 폴더 - 오른쪽 버튼 메뉴 모습


src/main/resource 폴더를 마우스 오른쪽으로 클릭한다.

New-> File를 클릭한다.


파일명: db.properties



그림 18. /src/main/resource 폴더와 db.properties 모습


성공적으로 만들어진 것을 확인할 수 있다.



그림 19. db.propeties 모습


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

dataSourceClassName=oracle.jdbc.driver.OracleDriver

dataSource.user=userName

dataSource.password=password

cachePrepStmts=true

prepStmtCacheSize=250

prepStmtCacheSqlLimit=2048


파일명: db.propeties


[첨부(Attachments)]

db.zip




9. Servlet 생성하기


servlet 생성하고 나서 web.xml 수정을 진행하면 타이핑을 적게 해도 되는 장점이 생긴다.



그림 20. 프로젝트 오른쪽 버튼 - 메뉴 모습


프로젝트를 선택한다.

마우스 오른쪽 버튼을 클릭한다.

New->Servlet을 클릭한다.



그림 21. Servlet 생성하기


Java package명을 입력한다. ("예: com.smile.web.controller // 이런 형식으로 작성하면 됨.)

Class name을 입력한다. ("예: FrontController" )

Finish를 누른다.



10. web.xml - 수정하기


charset 초기값을 추가하였다.

Servlet 2.5 문서 양식에서 3.1 양식으로 변경하였다.


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

xmlns="http://java.sun.com/xml/ns/javaee" 

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

id="WebApp_ID" version="3.0">

 

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

  

  <servlet>

  <servlet-name>FrontController</servlet-name>

  <servlet-class>com.smile.web.controller.FrontController</servlet-class>

  <init-param>

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

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

</init-param>

  </servlet>

  <servlet-mapping>

  <servlet-name>FrontController</servlet-name>

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

  </servlet-mapping>

  

</web-app>


파일명: web.xml


[첨부(Attachments)]

web.zip




10. 폴더 2개(views, settings), 파일 하나 만들기(root-servlet.xml)


추가적으로 만들어줄 폴더와 파일이 있다.


폴더1: /src/main/webapp/WEB-INF/settings

폴더2: /src/main/webapp/WEB-INF/views

파일: /src/main/webapp/WEB-INF/settings/root-servlet.xml


Settings 폴더는 큰 의미는 없지만, 활용할 여지를 고려하여 생성하였다.
이 프로젝트에서는 root-servlet.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 -->
</beans>


파일명: root-servlet.xml


[첨부(Attachments)]

root-servlet.zip



그림 22. 작업된 프로젝트의 모습




11. FrontController.java - 서블렛(Servlet)


실제경로: /target/generated-sources/annotations/com/smile/web/controller

패키지명: com.smile.web.controller

파일명: FrontController.java


FrontController를 list만 정의하였다.

의외로 코드를 살펴보면, 간단하다는 것을 알 수 있다.


package com.smile.web.controller;


import java.io.IOException;

import java.sql.SQLException;


import javax.servlet.ServletConfig;

import javax.servlet.ServletException;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;


import com.smile.web.db.DBFactory;


public class FrontController extends HttpServlet {

private static final long serialVersionUID = 1L;

private String charset = null;

/**

* @see HttpServlet#doGet(HttpServletRequest req, HttpServletResponse res)

*/

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

doAction(req, res);

}


/**

* @see HttpServlet#doPost(HttpServletRequest req, HttpServletResponse res)

*/

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

doAction(req, res);

}

// FrontController 패턴 & Command 패턴

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


ServletConfig sc = this.getServletConfig();

charset = sc.getInitParameter("charset");


req.setAttribute("charset", charset);

req.setCharacterEncoding(charset);

res.setContentType("text/html; charset=" + charset);


String uri = req.getRequestURI();

String conPath = req.getContextPath();

String command = uri.substring(conPath.length());


Controller subController = null;


if(command.equals("/board/list.do")){

System.out.println("-----------------------------");

System.out.println("게시판 목록");

System.out.println("-----------------------------");

req.setAttribute("controllerName", "list");

subController = new com.smile.web.controller.board.ListController();

subController.execute(req, res);

}

}


}



파일명: FrontController.java


[첨부(Attachments)]

FrontController.zip




12. Controller.java - 인터페이스


실제경로: /target/generated-sources/annotations/com/smile/web/controller

패키지명: com.smile.web.controller

파일명: Controller.java


인터페이스에 관한 것이다. (forward 정의 관련한 것)


package com.smile.web.controller;


import java.io.IOException;


import javax.servlet.ServletException;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;


public interface Controller {

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


}


파일명: Controller.java


[첨부(Attachments)]

Controller.zip



12. /Board/ListController.java - 클래스


실제경로: /target/generated-sources/annotations/com/smile/web/controller/board

패키지명: com.smile.web.controller.board

파일명: ListController.java


게시판 목록에 관한 컨트롤러 명세이다.


package com.smile.web.controller.board;


import java.io.IOException;

import java.net.URLEncoder;

import java.util.List;


import javax.servlet.ServletException;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;


import com.smile.web.controller.Controller;

import com.smile.web.logic.Paging;

import com.smile.web.model.Board;

import com.smile.web.service.BoardService;

import com.smile.web.util.HttpUtil;


public class ListController implements Controller {


@Override

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

String controllerName = (String) req.getAttribute("controllerName");

BoardService service = BoardService.getInstance();

List<Board> boardList = null;

// long totalCount = boardList.size();

long currentPage = 1; // 기본값

long pageSize = 10;

long totalCount = service.getTotalCount();

long startNum, endNum;

String keyword = null;

String pagingUrl = controllerName + ".do?";

// 페이지 번호 존재할 때

if (req.getParameter("page") != null){

currentPage = Integer.valueOf( req.getParameter("page") );

}

// 키워드가 존재할 때

if (req.getParameter("keyword") != null) {

keyword = req.getParameter("keyword");

totalCount = service.getTotalKeywordCount(keyword);

// 키워드 값이 하나라도 존재할 때

if ( keyword.length() > 0) {

pagingUrl = pagingUrl + "keyword=" + URLEncoder.encode(keyword, "UTF-8") + "&";

}

}

        Paging paging = new Paging();

        /*

        paging.setPageNo(1);

        paging.setPageSize(10);

        paging.setTotalCount(totalCount);

        */

        

        paging.setPageNo(currentPage);

        paging.setPageSize(pageSize);

        paging.setTotalCount(totalCount);


        System.out.println("현재페이지번호:" + currentPage);

        System.out.println("페이지크기:" + pageSize);

        System.out.println("키워드:" + keyword);

        System.out.println("페이징URL:" + pagingUrl);

        

        startNum = paging.getDbStartNum();

        endNum = paging.getDbEndNum();


        

// 키워드가 존재할 때

if (keyword != null) {

// 키워드 값이 하나라도 존재할 때

if ( keyword.length() > 0) {

boardList = service.getBoardKeywordList(keyword, startNum, endNum);

}

else {

boardList = service.getBoardList(startNum, endNum);

}

}

else {

        boardList = service.getBoardList(startNum, endNum);

}

        

        req.setAttribute("paging", paging);

        req.setAttribute("list", boardList);

        req.setAttribute("pagingUrl", pagingUrl);

HttpUtil.forward(req, res, "/WEB-INF/views/board/" + controllerName + ".jsp");

}


}



파일명: ListController.java


[첨부(Attachments)]

ListController.zip



13. HttpUtil.java - 클래스


실제경로: /target/generated-sources/annotations/com/smile/web/util

패키지명: com.smile.web.controller.util

파일명: HttpUtil.java


RequestDispatcher와 forward에 대한 정의이다.

추가로 업로드 기능에 대한 명세도 있다.


package com.smile.web.util;


import java.io.File;

import java.io.FileInputStream;

import java.io.FileNotFoundException;

import java.io.IOException;

import java.io.InputStream;

import java.io.OutputStream;

import java.io.PrintWriter;


import javax.servlet.RequestDispatcher;

import javax.servlet.ServletConfig;

import javax.servlet.ServletException;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;



public class HttpUtil extends HttpServlet {

private static final long serialVersionUID = 1L;

private static String charset = null;


public static void forward(HttpServletRequest req, HttpServletResponse res,

String path) throws ServletException, IOException {

try {

RequestDispatcher dispatcher = req.getRequestDispatcher(path);

dispatcher.forward(req, res);

}catch(Exception e) {

e.printStackTrace();

}

}

public static void fileUpload(HttpServletRequest req, HttpServletResponse res,

String path) throws ServletException, IOException {


charset = (String) req.getAttribute("charset");

System.out.println(charset);

PrintWriter out = res.getWriter();

// 파일 업로드된 경로

String root = req.getSession().getServletContext().getRealPath("/");

String savePath = root + "upload" + File.separator + "upload";

// 서버에 실제 저장된 파일명

String filename = "1600955663095" ;

System.out.println("파일 실제 폴더경로:" + savePath);

// 실제 내보낼 파일명

String orgfilename = "license한글.txt" ;

req.setCharacterEncoding(charset);

res.setCharacterEncoding(charset);

InputStream in = null;

OutputStream os = null;

File file = null;

boolean skip = false;

String client = "";

try{

    // 파일을 읽어 스트림에 담기

    try{

        file = new File(savePath, filename);

        in = new FileInputStream(file);

    }catch(FileNotFoundException fe){

        skip = true;

    }

    client = req.getHeader("User-Agent");

    // 파일 다운로드 헤더 지정

    res.reset() ;

    res.setContentType("application/octet-stream");

    res.setHeader("Content-Description", "JSP Generated Data");

    if(!skip){

        // IE

        if(client.indexOf("MSIE") != -1){

            res.setHeader ("Content-Disposition", "attachment; filename="+new String(orgfilename.getBytes("KSC5601"),"ISO8859_1"));

        }else{

            // 한글 파일명 처리

            orgfilename = new String(orgfilename.getBytes("KSC5601"),"iso-8859-1");

            res.setHeader("Content-Disposition", "attachment; filename=\"" + orgfilename + "\"");

            res.setHeader("Content-Type", "application/octet-stream; charset=utf-8");

        }  

        res.setHeader ("Content-Length", ""+file.length() );

        os = res.getOutputStream();

        

        byte b[] = new byte[(int)file.length()];

        int leng = 0;

        while( (leng = in.read(b)) > 0 ){

            os.write(b,0,leng);

        }

    }else{

    // 한글 깨짐 - 해결

    res.setContentType("text/html;charset=" + charset);

        out.println("<html><head>");

        out.println("<script language='javascript'>alert('파일을 찾을 수 없습니다.');history.back();</script>");

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

    }

    in.close();

    os.close();

}catch(Exception e){

e.printStackTrace();

}

    

}


}



파일명: HttpUtil.java


[첨부(Attachments)]

HttpUtil.zip



13. DBFactory.java - 커넥션 풀 적용


실제경로: /target/generated-sources/annotations/com/smile/web/db

패키지명: com.smile.web.controller.db

파일명: DBFactory.java


HikariCP 3.4.2를 적용한 코드이다.


package com.smile.web.db;



import java.io.IOException;

import java.sql.Connection;

import java.sql.DriverManager;

import java.sql.PreparedStatement;

import java.sql.ResultSet;

import java.sql.SQLException;

import java.sql.Statement;

import java.util.Properties;

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 com.zaxxer.hikari.HikariConfig;

import com.zaxxer.hikari.HikariDataSource;


import oracle.jdbc.pool.OracleDataSource;


public class DBFactory {


private static final Logger logger = LoggerFactory.getLogger(DBFactory.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 HikariConfig config;


    

    public DBFactory() {


    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("jdbcurl:" + properties.getProperty("jdbcUrl"));

            System.out.println("className" + 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 {

   

    /*

        try(Connection con = ds.getConnection()){

            System.out.println("연결상태확인:" + con);

            

            String sql = "SELECT * from board where id > 4 and id < 10";

            

            PreparedStatement pstmt = con.prepareStatement(sql);

            ResultSet rs = pstmt.executeQuery();

            

            while (rs.next()) {

                System.out.println("진짜 연결되었는가:" + rs.getString(2));

            }

        }

        catch(Exception e) {

        System.out.println("연결실패확인:" + e.getMessage());

        }

    */

   

        return ds.getConnection();

    }

    

    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 구조 응용(재귀 함수)

} // end of if


}


public void close(Connection conn, PreparedStatement ps) {


if (ps != null ) {


try {

ps.close();

}

catch(Exception ex) {

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

}

} // end of if


if (conn != null ) {

try {

conn.close();

}

catch(Exception ex) {

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

}

} // end of if


}

    

}


파일명: DBFactory.java


[첨부(Attachments)]

DBFactory.zip



* 2부에서는 핵심적인 로직 등에 대해서 소개하겠다.


2부에서 만나요.


1. [JSP] 17. JSP/Servlet MVC2 - 페이징네이션과 검색 그리고 오라클 프로젝트 (2), 2020-09-30

https://yyman.tistory.com/1429


반응형
728x90
300x250

[Spring-Framework] 20. Spring MVC - Spring Framework 5 REST, Jackson, Commons-FileUpload - (2)


2부에서는 Controller, Model, View, Util(한글 문제)을 집중적으로 소개하겠다.


1. [Spring-Framework] 19. Spring MVC - Spring Framework 5 REST, Jackson, Commons-FileUpload - (1), 2020-09-28

https://yyman.tistory.com/1425



12. Controller - HomeController.java



초기 프로젝트를 생성하면 자동으로 만들어지는 HomeController.java이다.

REST 프로젝트 작업에 필요한 형태로 추가 작성 및 변형하였다.


- REST Client에 대해서 자세히 소개하였음. (CRUD - GET, POST, PUT, DELETE 클라이언트)


package com.example.restexample2.controller;


import java.io.UnsupportedEncodingException;

import java.net.URI;

import java.net.URLDecoder;

import java.nio.charset.Charset;

import java.text.DateFormat;

import java.util.ArrayList;

import java.util.Arrays;

import java.util.Date;

import java.util.HashMap;

import java.util.List;

import java.util.Locale;

import java.util.Map;

import java.util.concurrent.atomic.AtomicLong;


import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.springframework.http.HttpEntity;

import org.springframework.http.HttpHeaders;

import org.springframework.http.HttpMethod;

import org.springframework.http.MediaType;

import org.springframework.http.ResponseEntity;

import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;

import org.springframework.http.converter.FormHttpMessageConverter;

import org.springframework.http.converter.HttpMessageConverter;

import org.springframework.http.converter.StringHttpMessageConverter;

import org.springframework.stereotype.Controller;

import org.springframework.ui.Model;

import org.springframework.util.LinkedMultiValueMap;

import org.springframework.util.MultiValueMap;

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

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

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

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

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

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

import org.springframework.web.client.HttpClientErrorException;

import org.springframework.web.client.HttpServerErrorException;

import org.springframework.web.client.RestTemplate;

import org.springframework.web.util.UriComponents;

import org.springframework.web.util.UriComponentsBuilder;


import com.example.restexample2.model.Board;

import com.example.restexample2.model.Greeting;

import com.fasterxml.jackson.databind.ObjectMapper;

import com.fasterxml.jackson.databind.deser.impl.CreatorCandidate.Param;


@Controller

public class HomeController {

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

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

model.addAttribute("serverTime", formattedDate );

return "home";

}


    /**

     * 파일 업로드 입력 화면

     */

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

public String fileUploadView(Locale locale, Model model) {

logger.info("Welcome FileUpload! 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 "file/upload";

}



    /**

     * GET 방식 - 클라이언트

     */

@SuppressWarnings("unchecked")

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

public String helloClient(String regId, String time) throws UnsupportedEncodingException{

// Get 응답 방법론

String url = "http://localhost:8080/restexample2/testValue2";

        String serviceKey = "서비스키";

        String decodeServiceKey = URLDecoder.decode(serviceKey, "UTF-8");

        

        RestTemplate restTemplate = new RestTemplate();

        HttpHeaders headers = new HttpHeaders();

        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));    //Response Header to UTF-8  

        

        UriComponents builder = UriComponentsBuilder.fromHttpUrl(url)

                .queryParam("serviceKey", decodeServiceKey)

                .queryParam("regId", regId)

                .queryParam("tmFc", time)

                .queryParam("_type", "json")

                .build(false);    //자동으로 encode해주는 것을 막기 위해 false

        

        //Object response = restTemplate.exchange(builder.toUriString(), HttpMethod.GET, new HttpEntity<String>(headers), String.class);

        

        // Object response = restTemplate.getForEntity(builder.toUriString(), List.class);

        Object response = restTemplate.getForObject(builder.toUriString(), List.class);

        

        if ( response != null) {


            List<Integer> map = (List<Integer>) response;

        System.out.println("map" + map);

        }

        

        //return response;


return "home";

}


    /**

     * POST 방식 - 클라이언트

     */

@SuppressWarnings("unchecked")

@RequestMapping(value = "/client/listMapPost")

public String helloClient2(String regId, String time) throws UnsupportedEncodingException{

// POST 응답 방법

//String url = "http://..............";

String url = "http://localhost:8080/restexample2/testValue2";

        String serviceKey = "서비스키";

        String decodeServiceKey = URLDecoder.decode(serviceKey, "UTF-8");

        

        RestTemplate restTemplate = new RestTemplate();

        HttpHeaders headers = new HttpHeaders();

        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));    //Response Header to UTF-8  

        

        /*

        UriComponents builder = UriComponentsBuilder.fromHttpUrl(url)

                .queryParam("serviceKey", decodeServiceKey)

                .queryParam("regId", regId)

                .queryParam("tmFc", time)

                .queryParam("_type", "json")

                .build(false);    //자동으로 encode해주는 것을 막기 위해 false

        */

        

        MultiValueMap<String, String> parameters = new LinkedMultiValueMap<String, String>();

        parameters.add("servicekey", decodeServiceKey);

        parameters.add("regId", regId);

        parameters.add("tmFc", time);

        parameters.add("_type", "json");

        

        //Object response = restTemplate.exchange(builder.toUriString(), HttpMethod.GET, new HttpEntity<String>(headers), String.class);

        

        // Object response = restTemplate.getForEntity(builder.toUriString(), List.class);

        Object response = restTemplate.postForObject(url, parameters, List.class);

        // Object response = restTemplate.postForEntity(url, parameters, List.class);

        

        if ( response != null) {


            List<Integer> map = (List<Integer>) response;

        System.out.println("map" + map.get(0));

        }

        

        //return response;


return "home";

}

    /**

     * PUT 방식 - 클라이언트

     */

@SuppressWarnings("unchecked")

@RequestMapping(value = "/client/listMapPut/{boardIdx}")

public String helloClient3(String regId, 

String time,

@PathVariable(name="boardIdx", required=true) int boardIdx)

throws  UnsupportedEncodingException{

// PUT 방법

String url = "http://localhost:8080/restexample2/v1/api/board/2";

        String serviceKey = "서비스키";

        String decodeServiceKey = URLDecoder.decode(serviceKey, "UTF-8");

        

        RestTemplate restTemplate = new RestTemplate();

        HttpHeaders headers = new HttpHeaders();

        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));    //Response Header to UTF-8  

        

        // 파라메터

        MultiValueMap<String, String> parameters = new LinkedMultiValueMap<String, String>();

        parameters.add("servicekey", decodeServiceKey);

        parameters.add("regId", regId);

        parameters.add("tmFc", time);

        parameters.add("_type", "json");

        

        //Object response = restTemplate.exchange(builder.toUriString(), HttpMethod.GET, new HttpEntity<String>(headers), String.class);

        

        Board updatedBoard = new Board();

        updatedBoard.setId(boardIdx);

        updatedBoard.setSubject("앙하하");

        updatedBoard.setName("수정했다.");

        updatedBoard.setMemo("메모지");

        

        

        // Object response = restTemplate.getForEntity(builder.toUriString(), List.class);

        //Object response = restTemplate.postForObject(url, parameters, List.class);

        restTemplate.put ( url, updatedBoard, parameters );

        

        // 데이터 확인하기

        url = "http://localhost:8080/restexample2/v1/api/board";


        UriComponents builder = UriComponentsBuilder.fromHttpUrl(url)

                .queryParam("serviceKey", decodeServiceKey)

                .build(false);


        Board[] response = restTemplate.getForObject(builder.toUriString(), Board[].class );

        // Object response = restTemplate.postForEntity(url, parameters, List.class);

        

        if ( response != null) {


            List<Board> listData = Arrays.asList(response);

        System.out.println("list(Size):" + listData.size());

       

        try {

        if ( listData.size() != 0 && (boardIdx - 1) >= 0) {

            System.out.println("boardIdx:" + (boardIdx - 1));

        Board boardTmp = listData.get(boardIdx - 1);

        System.out.println("board:" + boardTmp.getId() + "/" + boardTmp.getSubject());

        }

        }catch(Exception e) {

        e.printStackTrace();

        }

       

        }

        

        //return response;

return "home";

}


    /**

     * PUT 방식 - 클라이언트

     */

@SuppressWarnings("unchecked")

@RequestMapping(value = "/client/listMapDelete/{boardIdx}")

public String helloClient4(String regId, 

String time,

@PathVariable(name="boardIdx", required=true) int boardIdx)

throws  UnsupportedEncodingException{

   // PUT 방법

  String url = "http://localhost:8080/restexample2/v1/api/board/" + boardIdx;

        String serviceKey = "서비스키";

        String decodeServiceKey = URLDecoder.decode(serviceKey, "UTF-8");

        

        RestTemplate restTemplate = new RestTemplate();

        HttpHeaders headers = new HttpHeaders();

        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));    //Response Header to UTF-8  

        

        // 파라메터

        MultiValueMap<String, String> parameters = new LinkedMultiValueMap<String, String>();

        parameters.add("servicekey", decodeServiceKey);

        parameters.add("regId", regId);

        parameters.add("tmFc", time);

        parameters.add("_type", "json");

        

        //Object response = restTemplate.exchange(builder.toUriString(), HttpMethod.GET, new HttpEntity<String>(headers), String.class);

        

        // Object response = restTemplate.getForEntity(builder.toUriString(), List.class);

        //Object response = restTemplate.postForObject(url, parameters, List.class);

        restTemplate.delete ( url, parameters );

        

        // 데이터 확인하기

        url = "http://localhost:8080/restexample2/v1/api/board";


        UriComponents builder = UriComponentsBuilder.fromHttpUrl(url)

                .queryParam("serviceKey", decodeServiceKey)

                .build(false);


        Board[] response = restTemplate.getForObject(builder.toUriString(), Board[].class );

        // Object response = restTemplate.postForEntity(url, parameters, List.class);

        

        if ( response != null) {


            List<Board> listData = Arrays.asList(response);

        System.out.println("list(Size):" + listData.size());

       

        try {

        if ( listData.size() != 0 && (boardIdx - 1) >= 0) {

            System.out.println("boardIdx:" + (boardIdx - 1));

        Board boardTmp = listData.get(boardIdx - 1);

        System.out.println("board:" + boardTmp.getId() + "/" + boardTmp.getSubject());

        }

        }catch(Exception e) {

        e.printStackTrace();

        }

       

        }

        

        //return response;

return "home";

}

}



파일명: HomeController.java


[첨부(Attachments)]

HomeController.zip





13. Controller - JSONController.java



REST를 간단하게 입문하는 용도로 작성하였다.


package com.example.restexample2.controller;


import java.util.ArrayList;

import java.util.HashMap;

import java.util.List;

import java.util.Map;

import java.util.concurrent.atomic.AtomicLong;


import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

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

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

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

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


import com.example.restexample2.model.Greeting;


/**

 * Handles requests for the application home page.

 */

@RestController

public class JSONController {

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


private static final String template = "Hello, %s!";

private final AtomicLong counter = new AtomicLong();

@GetMapping("/greeting")

public Greeting greeting(@RequestParam(value = "name", defaultValue = "World") String name) {

return new Greeting(counter.incrementAndGet(), String.format(template, name));

}

@GetMapping(value="/testValue") 

public String getTestValue(){

String TestValue = "레스트컨트롤러 테스트";

return TestValue;

}


@GetMapping(value="/testValue2") 

public List<Integer> getTestValue2(){

List<Integer> mList = new ArrayList<Integer>();

mList.add(1);

mList.add(2);

mList.add(3);

mList.add(4);

return mList;

/* 

* Error: pom.xml의 jackson-databind, jackson-core 추가할 것

* onverter found for return value of type: class java.util.ArrayList]

*/

}

@PostMapping(value="/testValue2") 

public List<Integer> getTestValue3(){

List<Integer> mList = new ArrayList<Integer>();

mList.add(1);

mList.add(2);

mList.add(3);

mList.add(4);

return mList;

/* 

* Error: pom.xml의 jackson-databind, jackson-core 추가할 것

* onverter found for return value of type: class java.util.ArrayList]

*/

}

@GetMapping(value="/getMap")

public Map<String, Greeting> getMap(){

Map<String, Greeting> map = new HashMap<>();

map.put("First", new Greeting(1, "Hello"));

map.put("Second", new Greeting(2, "Rest"));

return map;

}

}



파일명: JSONController.java


[첨부(Attachments)]

JSONController.zip




14. Model - Board.java



매우 간단한 게시판 구조에 대한 모델이다. 방명록도 어찌보면, 게시판의 한 종류가 될 수 있다.


package com.example.restexample2.model;


public class Board {

private long id;

private String subject;

private String name;

private String memo;

public long getId() {

return id;

}

public void setId(long id) {

this.id = id;

}

public String getSubject() {

return subject;

}

public void setSubject(String subject) {

this.subject = subject;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public String getMemo() {

return memo;

}

public void setMemo(String memo) {

this.memo = memo;

}

}



파일명: Board.java


[첨부(Attachments)]

Board.zip



15. Model - Greeting.java



사실 쉽고 간단한 코드가 더 어려운 코드라고 본다.

꼭 반드시 게시판 형태만 생각할 필요가 없다고 본다.

공부하는 데 있어서는 간단한 것이 사실 더 어려운 부분이라고 본다.


package com.example.restexample2.model;


public class Greeting {


private final long id;

private final String content;


public Greeting(long id, String content) {

this.id = id;

this.content = content;

}


public long getId() {

return id;

}


public String getContent() {

return content;

}

}


파일명: Greeting.java


[첨부(Attachments)]

Greeting.zip




16. Model - FileInfo.java


경로: /src/main/java/com/example/restexample2/model/FileInfo.java


파일에 관한 명세이다.


package com.example.restexample2.model;


import org.springframework.web.multipart.MultipartFile;


public class FileInfo {


private long num;

private String filename;

private long filesize;

private MultipartFile mediaFile;


public long getNum() {

return num;

}

public void setNum(long num) {

this.num = num;

}

public String getFilename() {

return filename;

}

public void setFilename(String filename) {

this.filename = filename;

}

public long getFilesize() {

return filesize;

}

public void setFilesize(long filesize) {

this.filesize = filesize;

}

public MultipartFile getMediaFile() {

return mediaFile;

}


public void setMediaFile(MultipartFile mediaFile) {

this.mediaFile = mediaFile;

}

}



파일명: FileInfo.java


[첨부(Attachments)]

FileInfo.zip





17. Controller - FileController.java


경로: /src/main/java/com/example/restexample2/controller/FileController.java


파일 업로드에 대한 기능이다.


package com.example.restexample2.controller;


import java.io.BufferedOutputStream;

import java.io.File;

import java.io.FileOutputStream;

import java.io.IOException;


import javax.servlet.ServletContext;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;


import org.apache.commons.fileupload.disk.DiskFileItemFactory;

import org.apache.commons.fileupload.servlet.ServletFileUpload;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

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

import org.springframework.http.HttpHeaders;

import org.springframework.http.HttpStatus;

import org.springframework.http.ResponseEntity;

import org.springframework.ui.Model;

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

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

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

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

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

import org.springframework.web.multipart.MultipartFile;


import com.example.restexample2.model.Board;

import com.example.restexample2.model.FileInfo;

import com.example.restexample2.util.HttpUtil;


@RestController

@RequestMapping ("/file")

public class FileController {

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

     

     /**

      * 파일 멀티파트 업로드 Rest

      * {/

      * @param inputFile

      * @return 

      *  (주석 스타일 참고)

      */

     @RequestMapping(value = "/uploadFileModelAttribute/new", 

    method = {RequestMethod.POST },

    produces="text/plain;charset=UTF-8")

     public String multiFileUpload(@ModelAttribute Board boardVO, 

    @RequestParam("mediaFile")MultipartFile[] files, 

    Model model,

    HttpServletRequest req,

    HttpServletResponse res) throws IOException {

     

    boolean filechk = false;

     

         //디스크상의 프로젝트 실제 경로얻기

         //String contextRootPath = "c:" + File.separator + "upload";

    // String charset = "UTF-8";


    // req.setAttribute("charset", charset);

    // req.setCharacterEncoding(charset);

    // res.setContentType("text/html; charset=" + charset);

     

    String dirName = "upload" ; 

String contextRootPath = req.getSession().getServletContext().getRealPath("/") + dirName;

 

         System.out.println("실제경로:" + contextRootPath);


         //1. 메모리나 파일로 업로드 파일 보관하는 FileItem의 Factory 설정

         DiskFileItemFactory diskFactory = new DiskFileItemFactory(); //디스크 파일 아이템 공장

         diskFactory.setSizeThreshold(4096); //업로드시 사용할 임시 메모리

         diskFactory.setRepository(new File(contextRootPath + "/WEB-INF/temp")); //임시저장폴더

         

         //2. 업로드 요청을 처리하는 ServletFileUpload생성

         ServletFileUpload upload = new ServletFileUpload(diskFactory);

         upload.setSizeMax(3 * 1024 * 1024); //3MB : 전체 최대 업로드 파일 크기

         

         

         // 한글 깨짐 해결(버그)

         // String kor_a = new String(boardVO.getSubject().getBytes("8859_1"), "UTF-8");  

         System.out.println("게시물제목:" + HttpUtil.getISO8859toUTF8( boardVO.getSubject()) );

System.out.println("게시물작성자:" + HttpUtil.getISO8859toUTF8( boardVO.getName()) );

System.out.println("게시물내용:" + HttpUtil.getISO8859toUTF8( boardVO.getMemo()) );

System.out.println("파일(길이):" + files.length );

 

 

         for(MultipartFile mFile : files) {


             // 3. 파일 가져오기

    if ( mFile.getOriginalFilename().isEmpty() && 

      filechk == false ) {


            String msg = "Please select at least one mediaFile.<br/>(미디어 파일을 하나 이상 선택하십시오.)";

            model.addAttribute("msg", msg);

           

            return model.getAttribute("msg").toString();

    }

     

             // 4. 파일명 - 현재시간으로 생성

             String uploadedFileName = System.currentTimeMillis() + ""; 

             

        if (!mFile.getOriginalFilename().isEmpty()) {

         

        BufferedOutputStream outputStream = new BufferedOutputStream(

        new FileOutputStream(

        new File( contextRootPath + File.separator + "upload" + File.separator, uploadedFileName )

));

       

       

                  System.out.println("파일명:" + mFile.getOriginalFilename());

                 

                  outputStream.write(mFile.getBytes());

                  outputStream.flush();

                  outputStream.close();

                 

                  filechk = true;                 

              } 

         

         }

         

    return "fileUploadForm";

   

     }

     

}


파일명: FileController.java


[첨부(Attachments)]

FileController.zip


비고: HttpUtil.java의 HttpUtil에 정의된 한글 출력 문제 등이 적용되어 있음.




18. Controller - BoardRestController.java


경로: /src/main/java/com/example/restexample2/controller/BoardRestController.java


게시판 시스템을 적용한 Rest 컨트롤러이다.

자료구조를 적절하게 재배치하여 실습에는 DB없이 가능한 수준으로 구현하였다.


package com.example.restexample2.controller;


import java.util.ArrayList;

import java.util.HashMap;

import java.util.List;

import java.util.Map;


import javax.servlet.http.HttpServletRequest;


import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

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

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

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

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

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

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

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

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

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

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


import com.example.restexample2.model.Board;


@RestController

@RequestMapping("/v1/api")

public class BoardRestController {

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


private static int num = 1;

private List<Object> tmpBoard = new ArrayList<Object>(); 

//@Autowired

    //private BoardService boardService;


    // 조회 = GET

    // (전체 게시물)

@GetMapping("board")

    public List<Object> listBoard(HttpServletRequest request, @ModelAttribute Board board) throws Exception {

   

    logger.info("게시판 목록");

    logger.info("----------------------------------");

   

    Board createNode = new Board();

    createNode.setId(num);

    createNode.setName("홍길동");

    createNode.setMemo("메모");

    createNode.setSubject("주소지");

   

    // tmpBoard.put(num, createNode);

    // num = num + 1;

   

    return tmpBoard;

    //return this.boardService.selectBoardList(request, board);

    }


    // 조회 = GET

    // (특정 세부 게시물)

    @GetMapping("board/{boardIdx}")

    public Board detailBoard(HttpServletRequest request, 

    @PathVariable(name="boardIdx", required=true) int boardIdx)

    throws Exception {


    logger.info("게시판 조회");

    logger.info("----------------------------------");

    logger.info("게시판 특정 게시물 번호" + boardIdx);

   

    //return this.boardService.selectBoard(request, boardIdx);

    return (Board) tmpBoard.get(boardIdx);

    }

    

    // 등록 = POST

    @PostMapping("board/new")

    public void insertBoard(HttpServletRequest request, @RequestBody Board board) throws Exception {

   

    logger.info("게시판 삽입");

   

    board.setId(num);


    tmpBoard.add(board);

    System.out.println(num);

    num = num + 1;

        //this.boardService.insertBoard(request, board);

    }


    // 수정 = PUT, PATCH (전송 방식)

    // /member/{id} + body (json데이터 등)

    @PutMapping("board/{boardIdx}")

    @PatchMapping("board/{boardidx}")

    public void updateBoard(HttpServletRequest request, 

    @PathVariable(name="boardIdx", required=true) int boardIdx, 

    @RequestBody Board board) throws Exception {

   

    logger.info("게시판 수정");

   

    if ( !tmpBoard.isEmpty() ) {

   

    board.setId(boardIdx); // 고유키 그대로 유지할 것

    tmpBoard.set(boardIdx - 1, board);

    }

    //board.setBoardIdx(boardIdx);

        //this.boardService.updateBoard(request, board);

   

    }

    

    // 삭제 = DELETE(전송 방식)

    @DeleteMapping("board/{boardIdx}")

    public void deleteBoard(HttpServletRequest request,

    @PathVariable(name="boardIdx", 

    required=true) int boardIdx) throws Exception {

   

    logger.info("게시판 삭제");

   

    try {   

    tmpBoard.remove(boardIdx);

    }

    catch(Exception e) {

        logger.info("Null값");

    e.getStackTrace();

    }

   

    //this.boardService.deleteBoard(request, boardIdx);

    }


}



파일명: BoardRestController.java


[첨부(Attachments)]

BoardRestController.zip




19. Util - HttpUtil.java


경로: /src/main/java/com/example/restexample2/util/HttpUtil.java


한글 언어에 대한 문제 해결에 대해서 정의하였다.


package com.example.restexample2.util;


import java.io.UnsupportedEncodingException;


public class HttpUtil {



    // 버그 개선: euc-kr 검증

    public static boolean isEucKr(String s) {

        int len = s.length();

        char c;

        for (int i = 0; i < len; i++) {

            c = s.charAt(i);

            /// System.out.println("" + c + " = " + toHex(c));

            if (((c & 0xFFFF) >= 0xAC00) && ((c & 0xFFFF) <= 0xD7A3))

                return true;

            /// else if (((c & 0xFF00) != 0) && ((c & 0x00) == 0))

            ///     return false;

        }

        return false;

    }

    // 버그 개선: ISO8859-1 검증

    public static boolean isISO8859(String s) {

     

        int len = s.length();

        char c;

        for (int i = 0; i < len; i++) {

            c = s.charAt(i);

            /// System.out.println("" + c + " = " + toHex(c));

            if ((c & 0xFF00) != 0)

                return false;

        }

        

        return true;

    }

    

    public static String getISO8859toUTF8(String s) {

   

    try {

return new String(s.getBytes("8859_1"), "UTF-8");

} catch (UnsupportedEncodingException e) {

e.printStackTrace();

return s;

}

   

    }

}



파일명: HttpUtil.java


[첨부(Attachments)]

HttpUtil.zip



20. View - home.jsp


경로: /src/main/webapp/WEB-INF/views/home.jsp


기본 생성된 jsp파일이다.


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

<%@ page session="false" %>

<html>

<head>

<title>Home</title>

</head>

<body>

<h1>

Hello world! - Rest(REST)

</h1>


<P>

</P>

</body>

</html>



파일명: home.jsp


[첨부(Attachments)]

home.zip



21. View - upload.jsp


경로: /src/main/webapp/WEB-INF/views/file/upload.jsp


업로드 페이지에 관한 정의이다.



그림 33. login.jsp 파일 모습 - 사용자 인터페이스(User Interfaces)


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

<%@ page session="false" %>

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

<html>

<head>

<title>다중 파일 업로드</title>

<meta charset="UTF-8">

</head>

<body>

<h3>다중 파일 업로드 및 다중 변수</h3>


<form action="file/uploadFileModelAttribute/new" method="POST"

  enctype="multipart/form-data">

    <table>

        <tr>

            <td>

            제목:

            <input type="text" name="subject" >

            </td>

            <td>

            이름:

            <input type="text" name="name" >

            </td>

            <td>

            내용:

            <input type="text" name="memo" >

            </td>

        </tr>

        <tr>

            <td>Select Files(파일을 선택하시오)</td>

            <td>

            <input type="file" name="mediaFile" multiple>

            </td>

            <td>

            <input type="file" name="mediaFile" multiple>

            </td>

        </tr>

        <tr>

        <td colspan="3">

                <button type="submit">Upload(업로드)</button>

        </td>

        </tr>

    </table>

</form>

</body>

</html>



파일명: login.jsp


[첨부(Attachments)]

upload.zip



22. 의외로 어려운 REST 작업 - Client에서 작업하기


REST Client 앱을 설치하여 작업을 시도했을 때 명세 등을 정의하질 못해서 작업이 쉽게 이뤄지지 못한 경우도 있다.

그래서 하나 만들어보게 되었다.


비고: 작업할 때는 조금 많이 찍어봐야 한다. (힘들고 더딘 작업 중 하나이다.)



그림 34. REST Client에서 처리할 때 사용될 수 있는 정보들


이러한 정보는 그냥 나온 것은 아니고, 조금 코드로 셈플이 나오도록 찍어봐야 한다.

안 찍어보면, 어떤 구조인지 모른다. 알 길이 없다.



그림 35. 코드 등으로 객체를 찍어보는 형태로 변형해주기


셈플 코드가 출력될 수 있는 환경으로 코드를 변형해준다.



그림 36. 객체 정보의 체계 - 출력


이런 형태로 정보들이 나오면, 잘 대입해보고 정리해보기도 하고 그래야 한다.

(태스트 작업이 소요됨)



그림 37. YARC REST Client에서 사용하기


자료를 가공해서 입력한 후, Send Request를 누른다.



예를 들면, GET 관련 코드를 통해서 Send Request를 누른 후에 아래에서 결과를 찾아볼 수 있다.

그러면 아래처럼 관련 유추할 수 있는 정보 단위 코드를 출력해볼 수 있다.


"3":{"id":3,"subject":"주소지","name":"홍길동","memo":"메모"}}

(양식)


(응용 -> POST 등록 명령)

-> {"id":3,"subject":"주소지","name":"홍길동","memo":"메모"}



(응용 -> PUT, PATCH 수정 명령)

-> {"id":3,"subject":"주소지","name":"홍길동","memo":"메모"}



-----------------------------------------------------


POST /restexample2/file/uploadFileModelAttribute/new HTTP/1.1

Host: localhost:8080

Connection: keep-alive

Content-Length: 24211

Cache-Control: max-age=0

Upgrade-Insecure-Requests: 1

Origin: http://localhost:8080

Content-Type: multipart/form-data; boundary=----WebKitFormBoundarya1HOiexOytPpWx8U

User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.121 Safari/537.36 Edg/85.0.564.63

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9

Sec-Fetch-Site: same-origin

Sec-Fetch-Mode: navigate

Sec-Fetch-User: ?1

Sec-Fetch-Dest: document

Referer: http://localhost:8080/restexample2/fileUploadView

Accept-Encoding: gzip, deflate, br

Accept-Language: ko,en;q=0.9,en-US;q=0.8,ja;q=0.7,de;q=0.6

Cookie: JSESSIONID=C1BB03C6629263A6B77084AA15CDF947

         }


파일명: sample-keyword.txt


[첨부(Attachments)]

sample-keyword.txt

sample-keyword.zip




* 맺음글(Conclusion)


실전에서 REST를 쉽고 빠르게 적용할 수 있는 방법이 없는지 충분히 고민하였다.

시중 책도 정말 많이 사보고, 인터넷 정보 검색, 공식 메뉴얼 등 삽질을 많이 하였다.


그리하여 이 프로젝트가 작성된 것이다.

REST를 쉽고 빠르게 사용할 수 있었으면 하는 바람이다.



* 참고자료(References)


[RESTEasy - 프로젝트에 대한 것]

1. A Guide to RESTEasy, https://www.baeldung.com/resteasy-tutorial, Accessed by 2020-09-28, Last Modified 2020-02-12.

2. tutorials/resteasy at master · eugenp/tutorials · GitHub, https://github.com/eugenp/tutorials/tree/master/resteasy, Accessed by 2020-09-28, Last Modified .

3. jersey, resteasy(JBoss)

[비고] 

-> resteasy는 현재 xml 출력을 못함. (POST, GET 등은 동작함)

-> jersey는 최신 버전도 인식을 못해버림.


[RestController, RESTful Service - Spring Framework ]

4. Building a RESTful Web Service, https://spring.io/guides/gs/rest-service/, Accessed by 2020-09-28, Last Modified .

[참고할 때 메모]

-> Library없이 가능한지 확인할 것 

[비고]

-> Gradle 기반과 Spring Boot로 작성되었는데, Gradle 생략하고 Spring Framework 작업은 동일해서 많은 도움을 받았다.


5. RestController에 대해 알아보자, https://milkye.tistory.com/283, Accessed by 2020-09-28, Last Modified 2018-12-02.

[비고]

매우 간단하게 RestController를 사용하는 방법에 대해서 소개하고 있음.


6. [Spring Error] No converter found for return value of type: class java.util.ArrayList, https://keichee.tistory.com/274, Accessed by 2020-09-28, Last Modified 2016-11-27.

[비고]: jackson-bind의 적용 방법에 대해서 소개하고 있음. 클래스 변환에 대한 오류 해결은 미약함.


[다중 업로드]

7. Spring MVC - 유연한 다중 파일업로드 핸들러 만들기 (Multipart upload), https://galid1.tistory.com/684, Accessed by 2020-09-28, Last Modified 2020-01-29.


8. 스프링 파일 업로드 처리, https://advenoh.tistory.com/26, Accessed by 2020-09-28, Last Modified 2019-01-01.



[RESTful - 게시판 설계]

9. 4. springboot restful 방식으로 게시판 변경, https://linked2ev.github.io/gitlog/2019/12/28/springboot-restful-4-rest-%EB%B0%A9%EC%8B%9D%EC%9C%BC%EB%A1%9C-%EB%B3%80%EA%B2%BD/ , Accessed by 2020-09-28, Last Modified 2019-12-28.

[비고]: REST 기반의 게시판 설계 아이디어를 많이 얻었음.


[RESTTemplate 관련]

10. Spring REST API 생성, 호출, https://www.leafcats.com/173, Accessed by 2020-09-28, Last Modified 2017.


11. 스프링 (Spring) RestTemplate으로 POST 파라미터 (Parameter) 전송해보기, https://soshanstory.tistory.com/entry/스프링-Spring-RestTemplate으로-POST-파라미터-Parameter-전송해보기, Accessed by 2020-09-28, Last Modified 2014-08-31.

[비고]: Rest Template 사용방법을 매우 간단하게 잘 적어놨음.


[공부하면서 메모]

- XML, Java 설정 방식이 있다. (REST 셋팅 관련 - 범위가 방대해지므로 줄임)


12. RestTemplate (4가지 - 자바 내에서 클라이언트 작업), https://howtodoinjava.com/spring-boot2/resttemplate/spring-restful-client-resttemplate-example/, Accessed by 2020-09-28, Last Modified 2015-03.

[비고]: 추천하고 싶음. 매우 RestTemplate에 대해서 가장 깔끔하게 잘 정리하였음.


(공식적으로는 HTML에서는 POST, GET만 지원함.)


13. RestTemplate list 반환하기, https://luvstudy.tistory.com/52, Accessed by 2020-09-28, Last Modified 2018-11-16.


[REST 한글 깨짐 Response]

14. spring에서 json response 한글 깨짐, https://thswave.github.io/spring/2015/02/22/korean-json-response.html, Accessed by 2020-09-28, Last Modified 2015-02-22.


[POST, GET 이외의 문제]

15. Using PUT method in HTML form, https://stackoverflow.com/questions/8054165/using-put-method-in-html-form, Accessed by 2020-09-28, Last Modified 2012.

[비고]: 8년 전 문제이긴 하지만, 현재에도 해당되는 문제이다.


16. REST - HTML Form에서 GET/POST만 지원하는 이유, http://haah.kr/2017/05/23/rest-http-method-in-html-form/, Accessed by 2020-09-28, Last Modified 2017-05-23.

[비고]: 이론적으로 REST에 대해서 아주 잘 소개하고 있는 사이트이다.


17. HTML 양식에 PUT 및 DELETE 메소드가없는 이유는 무엇입니까?, https://qastack.kr/software/114156/why-are-there-are-no-put-and-delete-methods-on-html-forms, Accessed by 2020-09-28, Last Modified .

[비고]: 토론 형태로 문제에 대해서 의견을 공유하고 있다.


18. [REST] PUT, PATCH, DELETE 미지원 처리, https://velog.io/@ette9844/REST-PUT-PATCH-DELETE-%EB%AF%B8%EC%A7%80%EC%9B%90-%EC%B2%98%EB%A6%AC, Accessed by 2020-09-28, Last Modified 2020-05-19.

[비고]: 이 코드는 동작하지 않음. (이론적으로 동작되는 방법이라고 보는 게 타당함.)


[번외의 주제: Node.js - REST]

19. REST API 예제, https://hyun-am-coding.tistory.com/entry/REST-API-%EC%98%88%EC%A0%9C, Accessed by 2020-09-28, Last Modified 2019-11-17.

[비고]: REST Client와 Server 흐름에 대해서 살펴볼 수 있다. 물론 자바 코드에 직접 도움은 되는 건 아니지만 동일하게 구성될 수 있다는 아이디어를 제공해준다.



반응형
728x90
300x250

[JSP] 15. Jsp/Servlet(MVC) - Session(세션) 프로젝트(로그인) - (2)


1부에 이어서 "JSP/Servlet 기반의 세션 프로젝트"를 진행하도록 하겠다.


[JSP] 14. Jsp/Servlet(MVC) - Session(세션) 프로젝트(로그인) - (1), 2020-09-25

https://yyman.tistory.com/1416




10. View - Login.jsp


/member/login.do에 관한 페이지이다.


생성해야 할 경로 위치: /src/main/webapp/WEB-INF/views/member


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

    pageEncoding="UTF-8"%>

<!DOCTYPE html>

<html>

<head>

<meta charset="UTF-8">

<title>로그인 - Member Login(세션 - Session)</title>

<style>

a { 

text-decoration:none 

}

body{

font-size:12px;

font-family:'Arial';

}

#memberTbl{

width:700px;

border:1px solid #e2e2e2;

text-align:center;

margin:auto;

}

div{

text-align:center;

}

</style>


</head>

<body>


<div>


<h3>로그인 페이지(Login - Page) - 세션(Session)</h3>

<!-- 본문 -->

<form action="process.do" method="POST">

<table id="memberTbl">

<tr>

<td style="width:20%; text-align:center;">

아이디(userID)

</td>

<td style="border-left:1px solid #e2e2e2; text-align:center;">

<input type="text" name="userID" style="width:90%">

</td>

</tr>

<tr>

<td style="width:20%; border-top:1px solid #e2e2e2; text-align:center;">

비밀번호(password)

</td>

<td style="border-left:1px solid #e2e2e2; border-top:1px solid #e2e2e2; text-align:center;">

<input type="text" name="password" style="width:90%">

</td>

</tr>

<tr>

<td colspan="2" style="border-top:1px solid #e2e2e2; text-align:center;">

<input type="submit" value="로그인(Login)" style="width:90%">

</td>

</tr>

</table>

</form>

</div>


</body>

</html>


파일명: login.jsp


[첨부(Attachments)]

login.zip



11. View - error_alert.jsp


에러 페이지에 관한 것이다.

시중 책을 보면, ServletController 내에 PrintWriter 함수로 구현되어 있는데, 해당 부분을 아예 분리시켰다.


생성해야 할 경로 위치: /src/main/webapp/WEB-INF/views/member



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

    pageEncoding="UTF-8"%>

<!-- 구현 영역(서버 사이드) -->

<%

String msg = (String)session.getAttribute("member_error_msg");

String redirect_url = (String)session.getAttribute("member_redirect_url");

%>


<!DOCTYPE html>

<html>

<head>

<meta charset="UTF-8">

<title>에러 - 페이지(Error - Page / Session)</title>

<script>

alert('<%= msg %>');

location.href('<%= redirect_url %>');

</script>

</head>

<body>


</body>

</html>


파일명: error_alert.jsp


[첨부(Attachments)]

error_alert.zip



12. View - logon.jsp


logon.jsp 페이지에 관한 것이다.


생성해야 할 경로 위치: /src/main/webapp/WEB-INF/views/member


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

    pageEncoding="UTF-8"%>

<!-- 구현 -->

<%

String userID = (String)session.getAttribute("userID");

%>

<!DOCTYPE html>

<html>

<head>

<meta charset="UTF-8">

<title>로그인 상태 - <%= userID %> 세션(Session)</title>

<style>

<!-- 바디 영역 -->

body{

font-family:'Arial';

font-size:13px;

}

#memberTbl{

font-family:'Arial';

font-size:13px;

width:700px;

border:2px solid #e2e2e2;

text-align:center;

margin:auto;

}

a { 

text-decoration:none 

}

div{

text-align:center;

}


</style>


<script>

function welcome(){

alert("Hello World");

}


function logout(){


location.href ('logout.do');

}

</script>

</head>

<body>


<div>

<h3>로그인 상태 출력 - 페이지(Session)</h3>


<!-- 화면 출력 -->

<table id="memberTbl">

<tr>

<td style="width:20%">

아이디(ID)

</td>

<td style="border-left:2px solid #e2e2e2;">

<%= userID %>

</td>

</tr>

<tr>

<td colspan="2" style="border-top:2px solid #e2e2e2;">

<a href="javascript:welcome();">인사말 출력</a>

&nbsp;&nbsp;

<a href="javascript:logout();">로그아웃</a>

</td>

</tr>

</table>

</div>


</body>

</html>


파일명: logon.jsp


[첨부(Attachments)]

logon.zip



13. Controller - MemberLoginController.java


MemberLoginController.java에 관한 것이다.

로그인 시작 페이지에 대한 처리 내용을 기술한 영역이다.


package com.member.web.controller;


import java.io.IOException;


import javax.servlet.ServletException;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;


public class MemberLoginController implements Controller {


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

HttpUtil.forward(req, res, "/WEB-INF/views/member/login.jsp");

}


}



파일명: MemberLoginController.jsp


[첨부(Attachments)]

MemberLoginController.zip




14. Controller - MemberProcessController.java


로그인 과정에 대한 처리 내용을 기술한 영역이다.


package com.member.web.controller;


import java.io.IOException;


import javax.servlet.ServletException;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import javax.servlet.http.HttpSession;


public class MemberProcessController implements Controller {


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


String id;

String passwd;

String charset;

HttpSession session;

charset = (String) req.getAttribute("charset");

req.setCharacterEncoding(charset);

id = req.getParameter("userID");

passwd = req.getParameter("password");

// System.out.println("userID:" + id);

// System.out.println("password:" + passwd);

// 세션 정보

session = req.getSession();

// 세션 생성

if ( id.equals("user") && passwd.equals("1234") ) {

session.setAttribute("userID", id);

session.setAttribute("userName", "회원");


res.sendRedirect("logon.do");

}

else {

session.setAttribute("member_error_msg", "아이디와 비밀번호를 확인하세요.");

session.setAttribute("member_redirect_url", "login.do");

res.sendRedirect("errorAlert.do");

}

}


}


파일명: MemberProcessController.jsp


[첨부(Attachments)]

MemberProcessController.zip



15. Controller - MemberLogonController.java


로그인이 되었을 때 출력되는 화면에 관한 것이다.


package com.member.web.controller;


import java.io.IOException;


import javax.servlet.ServletException;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import javax.servlet.http.HttpSession;


public class MemberLogonController implements Controller {


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


HttpSession session = req.getSession();

String userID = (String) session.getAttribute("userID");

// 세션이 존재할 때

if ( userID != null )

{

System.out.println("세션 존재 - 로그인");

HttpUtil.forward(req, res, "/WEB-INF/views/member/logon.jsp");

}

else {

System.out.println("세션 없음.");


session.setAttribute("member_error_msg", "로그인 상태를 확인해주세요.");

session.setAttribute("member_redirect_url", "login.do");

res.sendRedirect("errorAlert.do");

} // end of if

}


}



파일명: MemberLogonController.jsp


[첨부(Attachments)]

MemberLogonController.zip



16. Controller - MemberLogoutController.java


로그아웃 처리에 관한 기술이다.


package com.member.web.controller;


import java.io.IOException;


import javax.servlet.ServletException;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import javax.servlet.http.HttpSession;


public class MemberLogoutController implements Controller {


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


HttpSession session = req.getSession();

String userID = (String)session.getAttribute("userID");

// 세션이 존재할 때

if ( userID != null ) {

session.removeAttribute("userID");

session.removeAttribute("userName");

System.out.println("세션 존재: 삭제완료");

res.sendRedirect("login.do");

}

}


}



파일명: MemberLogoutController.jsp


[첨부(Attachments)]

MemberLogoutController.zip




17. Controller - MemberSessionAllKillController.java


세션 종료에 관한 영역이다.


package com.member.web.controller;


import java.io.IOException;


import javax.servlet.ServletException;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import javax.servlet.http.HttpSession;


public class MemberSessionAllKillController implements Controller {


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

HttpSession session = req.getSession();

String userID = (String)session.getAttribute("userID");

// 세션 종료

if ( userID != null ) {

session.invalidate();

System.out.println("세션 종료");

res.sendRedirect("login.do");

}

}


}


파일명: MemberSessionAllKillController.jsp


[첨부(Attachments)]

MemberSessionAllKillController.zip




18. Controller - MemberErrorAlertController.java


Error Alert에 관한 내용을 기술하였다.

특이한 점은 오류가 하나라도 발생하면, 모든 세션을 파괴시키는 형태로 구현하였다.

물론 실제 비즈니스 로직 상에서 오류 하나가 발생했다고 전부 세션을 파괴하는 행위는 하진 않을 것이다.


package com.member.web.controller;


import java.io.IOException;


import javax.servlet.ServletException;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import javax.servlet.http.HttpSession;


public class MemberErrorAlertController implements Controller {


@Override

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

HttpUtil.forward(req, res, "/WEB-INF/views/member/error_alert.jsp");

HttpSession session = req.getSession();

session.invalidate();

}


}



파일명: MemberErrorAlertController.jsp


[첨부(Attachments)]

MemberErrorAlertController.zip




19. 결론(Conclusion)


세션 구현 방법론은 알겠는데, 코드로 구현하려고 하면 아이디어가 떠오르지 않을 때 참고해서 사용하면 좋을 것으로 보인다.




* 참고 자료(References)


1. JSP & Servlet 에서 세션 사용하는 방법, https://juns0201.tistory.com/115, Accessed by 2020-09-25, Last Modified 2012-08-07.

-> 추천(50점): 세션 사용 방법에 대해서 자세히 잘 나와있다.


2. <JSP> 세션(Session)을 이용한 로그인 페이지, https://great-yo.tistory.com/73, Accessed by 2020-09-25, Last Modified 2019-02-16,
-> 추천(35점): 세션을 순수한 JSP 기반에서 사용하는 방법에 대해서 잘 나와있다.

3.  7.JSP (session을 이용한 로그인), https://jinseok12.tistory.com/13, Accessed by 2020-09-25, Last Modified 2017-10-06.
-> 추천(20점): 세션 로그인 방법에 대해서 잘 나와있다.



반응형
728x90
300x250

[JSP] 14. Jsp/Servlet(MVC) - Session(세션) 프로젝트(로그인)


Session(세션) 방식으로 로그인 페이지를 처리하는 방법에 대해서 소개하려고 한다.

시중 책보다도 훨씬 쉽고 빠르게 적용할 수 있는 수준으로 작성하기 위해서 노력을 많이 하였으니 참고해주었으면 좋겠다.


적용된 패턴: MVC2 - FrontController, Command 패턴



* Session(세선)이란?



그림 가-1) 세션 객체와 세션 ID


HTTP 기반으로 동작하는 클라이언트가 서버에 정보를 요청할 때 생성되는 "상태정보"를 세션이라고 한다.

세션은 HttpSession이라는 인터페이스 객체로 표현되며, HttpSession 객체는 HttpServletRequest의 getSession()이나 getSession(true) 메소드를 이용하여 생성할 수 있다.


- 활용 예: 로그인, 로그아웃, 장바구니 기능 등 사용자 인증 처리에 사용함.



* HttpSession 메소드


접근자&반환형

메소드

기능

public Object

getAttribute(String name)

HttpSession 객체에 등록된 정보 중 getAttribute() 메소드의 인자값으로

지정된 데이터 값을 반환한다.

public Enumeration

getAttributeNames()

HttpSession 객체에 등록되어 있는 모든 정보의 이름만을 반환한다.

public String

getId()

HttpSession 객체의 지정된 세션 ID를 반환함.

public long

getCreationTime()

HttpSession 객체가 생성된 시간을 밀리초 단위로 반환함.

public long

getLastAccessedTime()

클라이언트 요청이 마지막으로 시도된 시간을 밀리초 단위로 반환됨.

public int

getMaxInactiveInterval()

클라이언트의 요청이 없을 때 서버가 현재의 세션을 언제까지 

유지할지를 초 단위로 반환한다.

기본 유효 시간은 30분으로 지정되어 있다.

public void

invalidate()

현재의 세션을 삭제한다.

public boolean

isNew()

서버 측에서 새로운 HttpSession 객체를 생성한 경우에는 true를 반환,

기존 세션이 유지되는 경우라면 false를 반환

public void

setAttribute(String name, Object value) 

HttpSession 객체에 name으로 지정된 이름으로 value값을 등록한다.

public void

removeAttributes(String name)

HttpSession 객체에서 name으로 지정된 객체를 삭제한다.

public void

setMaxInactiveInterval(int second)

HttpSession 객체의 유지 시간을 설정한다.

지정된 시간이 지나면 HttpSession 객체는 자동 삭제된다.




1. 결과


Session 기반의 로그인 페이지를 아래처럼 만들어보려고 한다.

그림 1. 프로젝트 결과 - 로그인 페이지


그림 2. 프로젝트 결과 - 오류 출력




그림 3. 로그인 상태



그림 4. 자바스크립트 - 알람 메시지 출력



2. 프로젝트 구성도


다음은 작업할 프로젝트에 관한 것이다. 양이 조금 많아서 2~3부 정도로 컨텐츠를 구성하였다.



그림 5. 프로젝트 구성도



3. Maven Project 생성하기


새 프로젝트를 만든다.



그림 6. New-> Maven 프로젝트


Maven 폴더의 "Maven Project"를 선택한다.

"Next"를 누른다.




그림 7. New-> Maven 프로젝트


org.apache.maven.archetypes  |   maven-archetype-webapp를 선택한다.

Next를 누른다.




그림 8. New-> Maven 프로젝트


Group ID와 Artifact ID를 입력한 후 Finish를 누른다.



4. Project Facts, Build Path 설정하기


의외로 프로젝트 속성을 못 찾는 경우가 있어서 그림으로 매우 친절하게 작성하였다.



그림 9. 프로젝트 - 마우스 오른쪽 버튼 모습


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

Properties를 클릭한다.



그림 10. Build Path 설정 모습


JRE System Library [JavaSE-14] 버전으로 변경해준다.

(Edit 버튼을 눌러서 JRE 클릭 후 변경해주면 됨.)

Apply를 누른다.




그림 11. Project Factes


Project Facet의 Java 항목에 Version을 14로 변경해준다.

Apply를 누른다.



5. pom.xml 설정하기


http://mvnrepository.com에 접속한다.



그림 12. Java Servlet API - 4.0.1 - Mvnrepository.com


servlet을 찾아서 Maven 정보를 복사한다.



그림 13. pom.xml 설정하기


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



6. Servlet - FrontController 생성하기


서블릿 생성을 한다.



그림 14. 프로젝트의 "Java Resources" 메뉴


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

New->Servlet을 클릭한다.



그림 15. Create Servlet


패키지명(Java Package)은 "com.member.web.controller"로 지정하였다.

클래스명(Class Name)은 "FrontController"를 입력하였다.


Next를 누른다.


(중략)




그림 16. web.xml (src/main/webapp/WEB-INF/web.xml)


web.xml 파일을 수정해준다.


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

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

xmlns="http://java.sun.com/xml/ns/javaee" 

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

id="WebApp_ID" version="3.0">


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

  

  <welcome-file-list>

    <welcome-file>index.html</welcome-file>

    <welcome-file>index.htm</welcome-file>

    <welcome-file>index.do</welcome-file>

    <welcome-file>default.html</welcome-file>

    <welcome-file>default.htm</welcome-file>

    <welcome-file>default.do</welcome-file>

  </welcome-file-list>

  

  <servlet>

  <servlet-name>FrontController</servlet-name>

  <servlet-class>com.member.web.controller.FrontController</servlet-class>

  <init-param>

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

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

</init-param>

  </servlet>

  <servlet-mapping>

  <servlet-name>FrontController</servlet-name>

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

  </servlet-mapping>

</web-app>


파일명: web.xml


[첨부(Attachments)]

web.zip



7. Controller - HttpUtil.java


forward 함수에 관한 것이다.


package com.member.web.controller;


import java.io.IOException;


import javax.servlet.RequestDispatcher;

import javax.servlet.ServletException;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;


public class HttpUtil extends HttpServlet {


private static final long serialVersionUID = 1L;

private static String charset = null;


public static void forward(HttpServletRequest req, HttpServletResponse res,

String path) throws ServletException, IOException {

try {


RequestDispatcher dispatcher = req.getRequestDispatcher(path);

dispatcher.forward(req, res);


}catch(Exception e) {

e.printStackTrace();

}

}

}


파일명: HttpUtil.java


[첨부(Attachments)]

HttpUtil.zip



8. Controller(Interface) - Controller.java


Interface Controller를 하나 설계하였다.


package com.member.web.controller;


import java.io.IOException;


import javax.servlet.ServletException;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;


public interface Controller {


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


}


파일명: Controller.java


[첨부(Attachments)]

Controller.zip




9. Controller - FrontController.java


FrontController, Command 패턴에 관한 것이다.


package com.member.web.controller;


import java.io.IOException;


import javax.servlet.ServletConfig;

import javax.servlet.ServletException;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;


public class FrontController extends HttpServlet {

private static final long serialVersionUID = 1L;

private String charset = null;

       

    public FrontController() {

        super();

    }


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

doAction(req, res);

}


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

doGet(req, res);

}

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

ServletConfig sc = this.getServletConfig();

charset = sc.getInitParameter("charset");


req.setAttribute("charset", charset);

req.setCharacterEncoding(charset);

res.setContentType("text/html; charset=" + charset);


String uri = req.getRequestURI();

String conPath = req.getContextPath();

String command = uri.substring(conPath.length());

Controller subController = null;


if(command.equals("/member/login.do")){

System.out.println("login");

System.out.println("----------------");


subController = new MemberLoginController();

    subController.execute(req, res);


}else if (command.equals("/member/process.do")) {

System.out.println("process");

System.out.println("----------------");


subController = new MemberProcessController();

    subController.execute(req, res);

   

}else if (command.equals("/member/logon.do")) {

System.out.println("logon");

System.out.println("----------------");

subController = new MemberLogonController();

    subController.execute(req, res);

}else if (command.equals("/member/logout.do")) {

System.out.println("logout");

System.out.println("----------------");

subController = new MemberLogoutController();

    subController.execute(req, res);

   

}else if (command.equals("/member/sessionAllKill.do")) {


System.out.println("sessionAllKill");

System.out.println("----------------");

subController = new MemberSessionAllKillController();

    subController.execute(req, res);

   

}else if (command.equals("/member/errorAlert.do")) {


System.out.println("errorAlert");

System.out.println("----------------");

subController = new MemberErrorAlertController();

    subController.execute(req, res);

}

// end of if

}


}


파일명: FrontController.java


[첨부(Attachments)]

FrontController.zip


[비고]

MemberLoginController()

MemberProcessController()

MemberLogonController()

MemberLogoutController()

MemberSessionAllKillController()

MemberErrorAlertController()


번호

구현부

인터페이스

비고

1

MemberLoginController

Controller


2

MemberProcessController

Controller


3

MemberLogonController

Controller

 

4

MemberLogoutController

Controller


5

MemberSessionAllKillController

Controller

 

6

MemberErrorAlertController

Controller

 


약 6개의 Controller들은 추후 생성할 것이다.

다소 이름이 길긴 하지만, 추후 고민할 문제해봐도 되는 문제이고 진행하도록 하겠다.


실제 설계하고 코딩했을 때는 바로 저 코드가 한번에 나오지 않았다는 것이다.

단계, 단계 구간별로 필요에 의해서 하나 하나 만들어진 것이다.



* 2부에서 만나요.


2부에서는 view생성, 나머지 콘트롤러 구현에 대해서 소개하도록 하겠다.


[JSP] 14. Jsp/Servlet(MVC) - Session(세션) 프로젝트(로그인) - (2), 2020-09-25

https://yyman.tistory.com/1417


반응형

+ Recent posts