*실제로 타입을 바꾸어주는 형변환이 아니고, 컴파일시 그렇게 인지하게 하는 것

*어설션한 타입에 대해서 그 타입이 맞다는 확신이 필요하다, 왜냐하면 컴파일러만 속이는 것이기 때문에 컴파일은 통과해도 코드실행시 에러가 될 수 있기때문












*타입얼라이언스:타입에 별칭을 붙여 부르는 방법만 다르게 하는 것



























유니언 타입:any는 모든 타입이 될 수 있다인데, union타입은 몇 개의 한정적타입만 주어주고 그 타입중 하나라고 선언하는 것




























'frameworks > typescript' 카테고리의 다른 글

[typescript]iterator  (0) 2018.12.11
[typescript]generic(+additional:string literal type)  (0) 2018.12.07
[typescript]class  (0) 2018.12.07
[typescript]interface  (0) 2018.12.06
[typescript]type  (0) 2018.12.06
















































*undefined와 null은 모든 타입의 서프타입이기 때문에, 어떤 타입으로 선언된 변수에도 들어갈 수 있다.


1
2
3
4
5
6
7
8
9
10
11
12
13
class Person{
    name:string = null;
    age: number = null;
    constructor(name:string) {
        this.name = name;
    }
    hello(): void{
        console.log('what the hell');
    }
}
const person = new Person('mark');
console.log(person);
 
cs








































'frameworks > typescript' 카테고리의 다른 글

[typescript]iterator  (0) 2018.12.11
[typescript]generic(+additional:string literal type)  (0) 2018.12.07
[typescript]class  (0) 2018.12.07
[typescript]interface  (0) 2018.12.06
[typescript]type assertion  (0) 2018.12.06

PM2とは

PM2とは、Node.js製のWebアプリケーションを動かすための仕組みの一つです。例えば、Express4などで作成したアプリ(app.js)を動かしたい場合に普通だと、

$ node app.js

として起動しますが、PM2を用いると、

$ pm2 start app.js

のような形式でWebサービスを起動することができます。

node app.jsでの起動は非常にシンプルですが、以下のような問題点があります。

  • 基本的にはCPU1コアしか使えず、マルチコアに対応するのに手間がかかる
  • ログ出力や状態チェックなど自前で作る必要がある
  • その他、本番運用のための細かな手間がある

などなど。PM2を用いると、例えばCPUコア数を自動的に考慮して複数インスタンスを起動してくれるなど、便利な点が多いです。

同様の本番環境で使える起動ツールとしては、foreverなどがありますが、最近ではPM2が便利でよく使われている印象です。



今回のコードの置き場

以下におきましたので、必要あればご参照いただけたら幸いです。
https://github.com/yoheiMune/node-playground/tree/master/010-pm2

今回は、以下のようなExpress4で作成された簡単なアプリケーションを例に、話を進めます。

// app.js

const express = require('express');
app = express();

app.get('/', (req, res) => {
    res.send('Hello from index.');
});

app.listen(3000, () => {
    console.log('Express app starts, linstening port on 3000.')
});




PM2のインストール

npmから簡単にインストールすることが可能です。

# PM2をインストール
$ npm install -g pm2

インストール後に、以下のコマンドが認識されていればOKです。

$ pm2




PM2を使う

それではここから、pm2の基本的な使い方を見てみたいと思います。


起動する

起動するにはstartコマンドを利用します。


(환경변수를 삽입해 pm2가동하기는 http://valuefactory.tistory.com/258?category=765146 참고)

# pm2 start [スクリプトファイルパス]
$ pm2 start app.js
[PM2] Starting /Users/munesadayohei/git/node-playground/010-pm2/app.js in fork_mode (1 instance)
[PM2] Done.
┌──────────┬────┬──────┬───────┬────────┬─────────┬────────┬─────┬───────────┬──────────┐
 App name  id  mode  pid    status  restart  uptime  cpu  mem        watching 
├──────────┼────┼──────┼───────┼────────┼─────────┼────────┼─────┼───────────┼──────────┤
 app       0   fork  42728  online  0        0s      0%   15.3 MB    disabled 
└──────────┴────┴──────┴───────┴────────┴─────────┴────────┴─────┴───────────┴──────────┘

# --nameオプションをつけると、起動するアプリに名前をつけることができます。
# 今後の管理にも使うので、基本的には名前を明示的につけるのが良いです。
$ pm2 start app.js --name myapp
[PM2] Starting /Users/munesadayohei/git/node-playground/010-pm2/app.js in fork_mode (1 instance)
[PM2] Done.
┌──────────┬────┬──────┬───────┬────────┬─────────┬────────┬─────┬───────────┬──────────┐
 App name  id  mode  pid    status  restart  uptime  cpu  mem        watching 
├──────────┼────┼──────┼───────┼────────┼─────────┼────────┼─────┼───────────┼──────────┤
 myapp     0   fork  42882  online  0        0s      0%   13.4 MB    disabled 
└──────────┴────┴──────┴───────┴────────┴─────────┴────────┴─────┴───────────┴──────────┘



再起動する

デプロイなどでコードが変わる場合に、restartコマンドでサーバーを再起動して、変更を取り込むことができます。

# pm2 restart [アプリ名]
$ pm2 restart myapp
[PM2] Applying action restartProcessId on app [myapp](ids: 0)
[PM2] [myapp](0) 
┌──────────┬────┬──────┬───────┬────────┬─────────┬────────┬─────┬───────────┬──────────┐
 App name  id  mode  pid    status  restart  uptime  cpu  mem        watching 
├──────────┼────┼──────┼───────┼────────┼─────────┼────────┼─────┼───────────┼──────────┤
 myapp     0   fork  43059  online  1        0s      0%   15.2 MB    disabled 
└──────────┴────┴──────┴───────┴────────┴─────────┴────────┴─────┴───────────┴──────────┘

ここでrestart1に増えているからも、再起動されたことがわかります。


停止する

停止するためにはstopコマンドを利用します。

# pm2 stop [アプリ名]
$ pm2 stop myapp
[PM2] Applying action stopProcessId on app [myapp](ids: 0)
[PM2] [myapp](0) 
┌──────────┬────┬──────┬─────┬─────────┬─────────┬────────┬─────┬────────┬──────────┐
 App name  id  mode  pid  status   restart  uptime  cpu  mem     watching 
├──────────┼────┼──────┼─────┼─────────┼─────────┼────────┼─────┼────────┼──────────┤
 myapp     0   fork  0    stopped  1        0       0%   0 B     disabled 
└──────────┴────┴──────┴─────┴─────────┴─────────┴────────┴─────┴────────┴──────────┘
 Use `pm2 show ` to get more details about an app



ログの確認

logsコマンドを用いることで、出力されているログを確認することができます。

# pm2 logs [アプリ名]
$ pm2 logs myapp
[TAILING] Tailing last 15 lines for [myapp] process (change the value with --lines option)
/Users/munesadayohei/.pm2/logs/myapp-error-0.log last 15 lines:
/Users/munesadayohei/.pm2/logs/myapp-out-0.log last 15 lines:
0|myapp    | Express app starts, linstening port on 3000.
0|myapp    | Express app starts, linstening port on 3000.



モニタリング

monitコマンドを使うと、起動しているアプリのモニタリング(ログの確認やプロセスの確認)を行うことができます。

$ pm2 monit

クラスタリングモードでの起動

最初に説明したpm2 start [スクリプトファイルパス]ではforkモードという状態で起動しますが、起動モードにはクラスターモードというものも存在します。フォークモードでは起動したアプリ自体がリクエストを受け取りますが、クラスターモードではpm2のマスターノードがリクエストを受け取り、それを起動中のインスタンスに割り振ります(いわゆるロードバランシングをしてくれます)。

この機能で、複数インスタンスを同時に立ち上げることで、マシンリソースを上限まで使うことができるようになります。具体的には、以下のように起動します。

# pm2 start [スクリプトファイル名] --name [名前] -i [起動数]
# -i をつけると、クラスターモードになり、起動数=0にすると、マシンのコア数でインスタンスを起動してくれる.
$ pm2 start app.js --name myapp -i 0
[PM2] Starting /Users/munesadayohei/git/node-playground/010-pm2/app.js in cluster_mode (0 instance)
[PM2] Done.
┌──────────┬────┬─────────┬───────┬────────┬─────────┬────────┬─────┬───────────┬──────────┐
 App name  id  mode     pid    status  restart  uptime  cpu  mem        watching 
├──────────┼────┼─────────┼───────┼────────┼─────────┼────────┼─────┼───────────┼──────────┤
 myapp     0   cluster  43861  online  0        0s      13%  26.5 MB    disabled 
 myapp     1   cluster  43862  online  0        0s      30%  27.2 MB    disabled 
 myapp     2   cluster  43863  online  0        0s      28%  26.8 MB    disabled 
 myapp     3   cluster  43864  online  0        0s      25%  26.9 MB    disabled 
└──────────┴────┴─────────┴───────┴────────┴─────────┴────────┴─────┴───────────┴──────────┘

今回のマシンの場合、4コアあるので、4つのクラスターが起動しています。クラスターモードで複数インスタンスを立ち上げておけば、restartなどで再起動する場合にも、ダウンタイム0で再起動することができます。


設定ファイルを用いた起動指定

起動オプションで便利な振る舞いを指定できますが、一度にたくさんを指定するのは面倒です。起動オプションは設定ファイル(YamlまたはJSON形式)で定義することもできます。その設定ファイルをstartコマンドに渡すことで、便利なオプションを複数指定して起動することができます。

Yaml形式の場合

# ファイル名:pm2config.yml(ファイル名は自由です)

name: myapp                            # アプリ名
script: app.js                         # スクリプトファイルパス
exec_mode: "cluster"                   # 起動モード = cluster
instances: 0                           # 起動インスタンス数
log-date-format: "YYYY-MM-DD HH:mm Z"  # ログに日付を追加

JSONの場合

// ファイル名:pm2config.json(ファイル名は自由です)

{
    "name": "myapp",
    "script": "app.js",
    "exec_mode": "cluster",
    "instances": 0,
    "log-date-format": "YYYY-MM-DD HH:mm Z"
}

基本的には、Yamlの方がシンプルだしコメントも書けるので、Yaml定義が良いなぁと思います。

上記の設定ファイルを用いて起動するには、以下のように行います。

# Yamlファイルを指定して、起動する場合
$ pm2 start pm2config.yml

# JSONファイルを指定して、起動する場合
$ pm2 start pm2config.json




参考資料

今回は、以下の公式資料を利用しました。他にも色々とコマンドが紹介されているので、一読する価値は高いです。

http://pm2.keymetrics.io/docs/usage/quick-start/



最後に

PM2は非常に便利で、他にも色々な使い方をしているので、その辺もブログにアウトプットしていきたいなと思います。

最後になりますが本ブログでは、Linux・インフラ・開発環境・Python・フロントエンド・Go言語・Node.js・Swift・Java・機械学習など雑多に情報発信をしていきます。自分の第2の脳にすべく、情報をブログに貯めています。気になった方は、本ブログのRSSTwitterをフォローして頂けると幸いです ^ ^。

最後までご覧頂きましてありがとうございました!

foreverコマンドでNodeJSアプリを起動したままにする

この記事は最終更新日から1年以上が経過しています。

NodeJsアプリをデーモン化する

利点:"node app.js"をやらなくていい

npmでforeverを入れる

npm install -g forever

foreverコマンドの使い方

起動

forever start app.js

停止

forever stop app.js

再起動

forever restart app.js

foreverで実行しているリスト

forever list

こんなのが出る

info:    Forever processes running
data:        uid  command       script forever pid   id logfile                 uptime
data:    [0] ioGt /usr/bin/node app.js 39066   39068    /root/.forever/ioGt.log 0:0:0:13.174

ログ

forever logs

結果

info:    Logs for running Forever processes
data:        script logfile
data:    [0] app.js /root/.forever/ioGt.log

設定確認

forever config

結果

data:    {
data:      root: '/root/.forever',
data:      pidPath: '/root/.forever/pids',
data:      sockPath: '/root/.forever/sock',
data:      loglength: 100,
data:      logstream: false,
data:      columns: [
data:          'uid',
data:          'command',
data:          'script',
data:          'forever',
data:          'pid',
data:          'id',
data:          'logfile',
data:          'uptime'
data:      ]
data:    }

まとめ

foreverコマンドはstartしたらずっと動いてるので、便利。
便利だけど、ずっと動いてるので使い方忘れそう。
オプションもあるから、使えそうなら使ってみる。



1.  JSP/Servlet 의 내장 객체

 내장 객체

리턴 타입(Return Type) 

설명 

request 

javax.servlet.http.HttpServletRequest 

웹 브라우저의 요청 정보를 저장하고 있는 객체 

response 

javax.servlet.http.HttpServletResponse 

웹 브라우저의 요청에 대한 응답 정보를 저장하고 있는 객체 

out 

javax.servlet.jsp.jsp.jspWriter 

JSP 페이지에 출력할 내용을 가지고 있는 출력 스트림 객체이다. 

session 

javax.servlet.http.HttpSession 

하나의 웹 브라우저의 정보를 유지하기 위한 세션 정보를 저장하고 있는 객체 

application 

javax.servlet.ServletContext 

웹 어플리케이션 Context의 정보를 저장하고 있는 객체 

pageContext 

javax.servlet.jsp.PageContext 

JSP 페이지에 대한 정보를 저장하고 있는 객체 

page 

java.lang.Object 

JSP 페이지를 구현한  자바 클래스 객체

config 

javax.servlet.ServletConfig 

JSP 페이지에 대한 설정 정보를 저장하고 있는 객체 

exception 

java.lang.Throwable 

JSP 페이지서 예외가 발생한 경우에 사용되는 객체 



・request

   -  요청시마다 만들어지는 객체

   -  attribute, parameter를 가지고 있음

 

  

・application

   -  톰캣구동시 webcontext별로 만들어지는 객체

   -  톰캣중지시 없어지는 객체 LifeScope가 가장 길다

   -  서블릿 API ver 정보, 실제 경로

   -  parameter, attribute 가지고 있음

 


・pageContext

   -  현재 실행중인 JSP의 정보를 담고있다. 

   -  가장 일찍 객체가 사라진다 LifeScope가 가장 짧다

   -  JAVA SE : Object, Class, File

   -  JAVA EE : ServletContext, PageContext, EJBContext

   -  attribute 가지고 있음

   -  out / request / response / session 정보 얻는게 가능

      ex) pageContext.getOut();

            pageContext.getRequest();

            pageContext.getSession();


・session

   -  클라이언트별로 만들어지는 객체

   -  클라이언트 단에서 새로운 요청이 있어도 Session객체에 속성들은 그대로 유지된다.

   -  attribute가 있음



2. attribute와 parameter 메소드의 차이점


ⅰ. 간단히 요약


-파라미터에는 String만 사용가능

-애트리뷰트에는 다른 String외에 Object, Array 등 다양한 데이터 입력이 가능

-파라미터는 request에만 저장이 가능하고, 애트리뷰트는 session, context 등에도 저장이 가능

-애트리뷰트가 좀더 유연함

-파라미터는 HTML(클라이언트)의 form 데이터 전송시 key/value 쌍으로 사용된다.



ⅱ. 자세한 비교


・ 속성이란?

  - ServletContext, HttpServletRequest, HttpServletResponse, HttpSession 객체 중 하나에 설정해 놓는 객체(Object)이다. 



・ 내장 객체의 속성(attribute)과 관련된 메소드(http://hyeonstorage.tistory.com/78 [개발이 하고 싶어요])

메소드 

리턴 타입 

설명 

setAttribute(String key, Object value)

void 

해당 내장 객체의 속성(attribute)값을 설정하는 메소드로, 속성명에 해당하는 key 매개 변수에, 속성값에 해당하는 value 매개 변수의 값을 지정한다. 

 getAttributeNames()

java.util.Enumeration 

해당 내장 객체의 속성(attribute)명을 읽어오는 메소드로, 모든 속성의 이름을 얻어낸다. 

getAttribute(String key) 

Object 

해당 내장 객체의 속성(attribute)명을 읽어오는 메소드로, 주어진 key 매개 변수에 해당하는 속성명의 값을 얻어낸다. 

removeAttribute(String key)

void 

해당 내장 객체의 속성(attribute)을 제거하는 메소드로, 주어진 key 매개 변수에 해당하는 속성명을 제거한다. 



・  속성과 파라미터의 차이점

 

속성 

 파라미터 

 타입

 Application / Context

 Request

 Session 

 Application / context 초기화 파라미터

 Request 파라미터

 Servlet 초기화 파라미터

 설정 메소드

 setAttribute(String name, Object value)

 애플리케이션과 서블릿의 초기화 파라미터 값은 런타임 시 설정할 수 없습니다. 오로지 DD(Web.xml)에서만 가능합니다. 기억나죠? (Request 파라미터를 가지고, 좀 어렵긴 하지만 쿼리 스트링을 설정할 수 있습니다. 

 리턴 타입

 Object

 String

 참조 메소드

 getAttribute(String name)

 getInitParameter(String name) 





출처: http://yooooooo7se.tistory.com/63 [Learning Machine]





















・클라이언트가 request를 보내면 was에서 자동으로 request객체를 생성 -> requestDispatcher을 사용하면 동일한 request객체를 다른 컴포넌트로 포워딩함









・RequestObj.javs의 request객체와 포워딩한 노드인 despacher.jsp의 reuqest 객체 값이 동일한 것을 볼 수 있음









・클라이언트가 request를 보내면 was에서 자동으로 request객체를 생성 -> httpServleResponse을 사용하면 새로운 request객체를 다른 컴포넌트로 포워딩함. 때문에 기존 request객체와 새로운 곳으로 포워딩한 request객체가 다름






・RequestObj.java의 request객체와 포워딩한 노드인 redirect.jsp의 reuqest 객체 값이 상이한것을 볼 수 있음











・/Hello는 서블릿 이름 혹은 Hello.java 서블릿 파일을 Hello로 맵핑한 경우이다.


・실제 현장에서는 확장자 패턴을 많이 사용한다. Hello.do를 치건 world.do를 치건 모든 .do의 요청은 *.do 요청을 받는 서블릿으로 이동한다. 그리고 나서  *.do 서블릿 내부안에서 from이 어디 인지에 따라 다른 로직을 수행한다.







・다양한 요청을 각각의 서블릿에서 각자 받는 것이 아니라 일단 프론트 컨트롤러에서 모든 요청을 받은후, 프론트컨트롤러에서 각자의 서블릿으로 뿌려준다. 비유하자면 이런거다. 한 명한명의 고객의 자신의 니즈가 필요한 회사의 부서에 직접전화를 하면 중간에 관리해주는 사람이 없으니까 여러모로 비효율 적이다. 때문에 중간에 콜센터를 두고 콜센터에서 부서로 고객을 뿌려주는 것이다.




frontControllerEx.jsp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<%@ page language="java" contentType="text/html; charset=EUC-KR"
    pageEncoding="EUC-KR"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=EUC-KR">
<title>Insert title here</title>
</head>
<body>
 
    <a href="insert.do">insert</a>
    <hr />
    <a href="http://localhost:8181<%=request.getContextPath()%>/update.do">update</a>
    <hr />
    <a href="http://localhost:8181/jsp_25_2_ex1_frontex/select.do">select</a>
    <hr />
    <a href="<%=request.getContextPath()%>/delete.do">delete</a>
 
</body>
</html>
cs



FrontCon.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
package com.javalec.ex;
 
import java.io.IOException;
 
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
/**
 * Servlet implementation class FrontCon
 */
@WebServlet("*.do")
public class FrontCon extends HttpServlet {
    private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public FrontCon() {
        super();
        // TODO Auto-generated constructor stub
    }
 
    /**
     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        System.out.println("doGet");
        actionDo(request, response);
    }
 
    /**
     * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        System.out.println("doPost");
        actionDo(request, response);
    }
    
    private void actionDo(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        System.out.println("actionDo");
        
        String uri = request.getRequestURI();
        System.out.println("uri : " + uri);
        String conPath = request.getContextPath();
        System.out.println("conPath : " + conPath);
        String command = uri.substring(conPath.length());
        System.out.println("command : " + command);
 
        if(command.equals("/insert.do")){
            System.out.println("insert");
            System.out.println("----------------");
        }else if(command.equals("/update.do")){
            System.out.println("update");
            System.out.println("----------------");
        }else if(command.equals("/select.do")){
            System.out.println("select");
            System.out.println("----------------");
        }else if(command.equals("/delete.do")){
            System.out.println("delete");
            System.out.println("----------------");
        }
    }
 
}
 
cs


@WebServlet("*.do"): .do 로 들어오는 모든 요청을 FrontCon.java에서 받는다.

request.getContextPath(): /jsp_25_2_ex1_frontex를 나타낸다. 컨텍스트패스란, eclipse에서 클래스의 이름을 의미한다. 만약 helloworld라는  웹프로젝트 클래스를 생성하면, localhost:8090/helloworld 라는 uri가 jsp, html, servlet으로 갈 수 있는 루트 패스가 되는데 이를 컨택스트패스라고 한다.

request.getRequestURI(): /jsp_25_2_ex1_frontex/insert.do를 나타낸다. 클아이언트에서 요청한 URI를 그대로 나타내어 준다.  











・그런데 만약 위 예에서처럼 프론트 컨트롤에서 모든 로직을 처리하면, 한 서블릿 파일이 너무 길어지므로 보기 힘들다. 따라서, 

요청이 들어옴 -> 프론트 컨트롤러에서 받음 -> 프론트 컨트롤러에서 처리하지 않고 로직을 처리할 각각의 서블릿으로 보냄


jsp_25_3_ex1_commex.zip



・memersAll.jsp에서 요청 들어옴 -> FrontCon.java가 받음 -> 요청의 처리를 dao클래스에 위임 -> dao클래스에서 처리한 리턴값을 FrontCon.java에서 받음 -> memersAll.jsp에게 전달



memersAll.jsp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<%@ page language="java" contentType="text/html; charset=EUC-KR"
    pageEncoding="EUC-KR"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=EUC-KR">
<title>Insert title here</title>
</head>
<body>
 
    <a href="membersAll.do">전체 회원 정보 조회</a>
 
</body>
</html>
cs



FrontCon.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
package com.javalec.ex;
 
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Timestamp;
import java.util.ArrayList;
 
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
/**
 * Servlet implementation class FrontCon
 */
@WebServlet("*.do")
public class FrontCon extends HttpServlet {
    private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public FrontCon() {
        super();
        // TODO Auto-generated constructor stub
    }
 
    /**
     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        System.out.println("doGet");
        actionDo(request, response);
    }
 
    /**
     * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        System.out.println("doPost");
        actionDo(request, response);
    }
    
    private void actionDo(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        System.out.println("actionDo");
        
        String uri = request.getRequestURI();
        String conPath = request.getContextPath();
        String command = uri.substring(conPath.length());
        
        if(command.equals("/membersAll.do")) {
            response.setContentType("text/html; charset=EUC-KR");
            PrintWriter writer = response.getWriter();
            writer.println("<html><head></head><body>");
            
            Service service = new MembersAllService();
            ArrayList<MemberDto> dtos = service.execute(request, response);
            
            for (int i = 0; i < dtos.size(); i++) {
                MemberDto dto = dtos.get(i);
                String id = dto.getId();
                String pw = dto.getPw();
                String name = dto.getName();
                String eMail = dto.geteMail();
                Timestamp rDate = dto.getrDate();
                String address = dto.getAddress();
                
                writer.println(id + ", " + pw + ", " + name + ", " + eMail + ", " + rDate.toLocalDateTime() + ", " + address + "<hr />");
            }
            
            writer.println("</body></html>");
        }
        
    }
 
}
 
cs




MembersAllService.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package com.javalec.ex;
 
import java.util.ArrayList;
 
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
public class MembersAllService implements Service {
    
    public MembersAllService() {
        // TODO Auto-generated constructor stub
    }
 
    @Override
    public ArrayList<MemberDto> execute(HttpServletRequest request, HttpServletResponse response) {
        // TODO Auto-generated method stub
        
        MemberDao dao = MemberDao.getInstance();
        return dao.membersAll();
    }
 
}
 
cs




Service.java(인터페이스)

1
2
3
4
5
6
7
8
9
10
11
package com.javalec.ex;
 
import java.util.ArrayList;
 
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
public interface Service {
    public ArrayList<MemberDto> execute(HttpServletRequest request, HttpServletResponse response);
}
 
cs



MemberDao.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
package com.javalec.ex;
 
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Timestamp;
import java.util.ArrayList;
 
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.sql.DataSource;
 
public class MemberDao {
 
    private static MemberDao instance = new MemberDao();
    
    private MemberDao() {
    }
    
    public static MemberDao getInstance(){
        return instance;
    }
    
    public int insertMember(MemberDto dto) {
        int ri = 0;
        
        Connection connection = null;
        PreparedStatement pstmt = null;
        String query = "insert into members values (?,?,?,?,?,?)";
        
        try {
            connection = getConnection();
            pstmt = connection.prepareStatement(query);
            pstmt.setString(1, dto.getId());
            pstmt.setString(2, dto.getPw());
            pstmt.setString(3, dto.getName());
            pstmt.setString(4, dto.geteMail());
            pstmt.setTimestamp(5, dto.getrDate());
            pstmt.setString(6, dto.getAddress());
            pstmt.executeUpdate();
            ri = 1;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if(pstmt != null) pstmt.close();
                if(connection != null) connection.close();
            } catch (Exception e2) {
                e2.printStackTrace();
            }
        }
        
        return ri;
    }
    
    public int confirmId(String id) {
        int ri = 0;
        
        Connection connection = null;
        PreparedStatement pstmt = null;
        ResultSet set = null;
        String query = "select id from members where id = ?";
        
        try {
            connection = getConnection();
            pstmt = connection.prepareStatement(query);
            pstmt.setString(1, id);
            set = pstmt.executeQuery();
            if(set.next()){
                ri = 1;
            } else {
                ri = 0;
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                set.close();
                pstmt.close();
                connection.close();
            } catch (Exception e2) {
                e2.printStackTrace();
            }
        }
        
        return ri;
    }
    
    public int userCheck( String id, String pw) {
        int ri = 0;
        String dbPw;
        
        Connection connection = null;
        PreparedStatement pstmt = null;
        ResultSet set = null;
        String query = "select pw from members where id = ?";
        
        try {
            connection = getConnection();
            pstmt = connection.prepareStatement(query);
            pstmt.setString(1, id);
            set = pstmt.executeQuery();
            
            if(set.next()) {
                dbPw = set.getString("pw");
                if(dbPw.equals(pw)) {
                    ri = 1;        // 로그인 Ok
                } else {
                    ri = 0;        // 비번 X
                }
            } else {
                ri = -1;        // 회원 X    
            }
            
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                set.close();
                pstmt.close();
                connection.close();
            } catch (Exception e2) {
                e2.printStackTrace();
            }
        }
        return ri;
    }
    
    public MemberDto getMember(String id) {
        Connection connection = null;
        PreparedStatement pstmt = null;
        ResultSet set = null;
        String query = "select * from members where id = ?";
        MemberDto dto = null;
        
        try {
            connection = getConnection();
            pstmt = connection.prepareStatement(query);
            pstmt.setString(1, id);
            set = pstmt.executeQuery();
            
            if(set.next()) {
                dto = new MemberDto();
                dto.setId(set.getString("id"));
                dto.setPw(set.getString("pw"));
                dto.setName(set.getString("name"));
                dto.seteMail(set.getString("eMail"));
                dto.setrDate(set.getTimestamp("rDate"));
                dto.setAddress(set.getString("address"));
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                set.close();
                pstmt.close();
                connection.close();
            } catch (Exception e2) {
                e2.printStackTrace();
            }
        }
        
        return dto;
        
    }
    
    public int updateMember(MemberDto dto) {
        int ri = 0;
        
        Connection connection = null;
        PreparedStatement pstmt = null;
        String query = "update members set pw=?, eMail=?, address=? where id=?";
        
        try {
            connection = getConnection();
            pstmt = connection.prepareStatement(query);
            pstmt.setString(1, dto.getPw());
            pstmt.setString(2, dto.geteMail());
            pstmt.setString(3, dto.getAddress());
            pstmt.setString(4, dto.getId());
            ri = pstmt.executeUpdate();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                pstmt.close();
                connection.close();
            } catch (Exception e2) {
                e2.printStackTrace();
            }
        }
        
        return ri;
    }
    
    public ArrayList<MemberDto> membersAll() {
        
        ArrayList<MemberDto> dtos = new ArrayList<MemberDto>();
        Connection connection = null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;
        String query = "select * from members";
        
        try {
            connection = getConnection();
            pstmt = connection.prepareStatement(query);
            rs = pstmt.executeQuery();
            
            System.out.println("============");
            while (rs.next()) {
                MemberDto dto = new MemberDto();
                dto.setId(rs.getString("id"));
                dto.setPw(rs.getString("pw"));
                dto.setName(rs.getString("name"));
                dto.seteMail(rs.getString("eMail"));
                dto.setrDate(rs.getTimestamp("rDate"));
                dto.setAddress(rs.getString("address"));
                dtos.add(dto);
            }
            System.out.println("--------------------------");
            
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                rs.close();
                pstmt.close();
                connection.close();
            } catch (Exception e2) {
                e2.printStackTrace();
            }
        }
        
        return dtos;
        
    }
    
    private Connection getConnection() {
        
        Context context = null;
        DataSource dataSource = null;
        Connection connection = null;
        try {
            context = new InitialContext();
            dataSource = (DataSource)context.lookup("java:comp/env/jdbc/Oracle11g");
            connection = dataSource.getConnection();
        } catch (Exception e) {
            e.printStackTrace();
        }
        
        return connection;
    }
    
}
 
cs





MemberDto.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
package com.javalec.ex;
 
import java.sql.Timestamp;
 
public class MemberDto {
 
    private String id;
    private String pw;
    private String name;
    private String eMail;
    private Timestamp rDate;
    private String address;
    
//    public MemberDto(String id, String pw, String name, String eMail, Timestamp rDate, String address) {
//        this.id = id;
//        this.pw = pw;
//        this.name = name;
//        this.eMail = eMail;
//        this.rDate = rDate;
//        this.address = address;
//    }
 
    public String getId() {
        return id;
    }
 
    public void setId(String id) {
        this.id = id;
    }
 
    public String getPw() {
        return pw;
    }
 
    public void setPw(String pw) {
        this.pw = pw;
    }
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    public String geteMail() {
        return eMail;
    }
 
    public void seteMail(String eMail) {
        this.eMail = eMail;
    }
 
    public Timestamp getrDate() {
        return rDate;
    }
 
    public void setrDate(Timestamp rDate) {
        this.rDate = rDate;
    }
 
    public String getAddress() {
        return address;
    }
 
    public void setAddress(String address) {
        this.address = address;
    }
    
}
 
cs


















・압축 해제 후 톰캣 라이브러리 안에 넣어주면 된다. 































+ Recent posts