728x90

웹 개발을 하다보면 접속하는 사용자의 정보를 확인하기 위해서 CLIENT IP를 수집하는 경우가 있습니다.
하지만 접속하는 클라이언트가 PROXY SERVER를 사용하거나, 내부적으로 LOAD BALANCER를 하고 있다면 접속하는 클라이언트의 실제 IP를 수집하는 것이 아니라 웹 서버에 접속하는 바로 직전의 IP를 수집하게 될 것입니다.

그렇다면 그 정보는 정확한 정보가 아닌 쓰레기 정보라고 할 수 있겠죠?
그래서 접속하는 클라이언트의 실제 IP를 수집하는 방법을 설명 하려고 합니다.

먼저 보편적인 클라이언트 IP를 수집하는 방법입니다.

그렇다면 PROXY SERVER 또는 LOAD BALANCER를 거쳐나온 클라이언트의 IP는 어떻게 구할까요?

대부분의 이런 경우에는 CLIENT IP가 없어지는 것이 아니라 Request의 헤더에 X-FORWARDED_FOR라는 키워드로 정보를 남겨 놓는다고 합니다. 그래서 자바내의 로직을 처리하실 때는 다음과 같이 하시면 됩니다.

위의 자료는 STCreative에서 개발을 하면서 겪었던 일을 기반으로 작성된 자료입니다.
모두 100%정확하다는 편견을 버려주십시요.
확인해 보시고 에러가 발생한다면 디버깅과 함께 해결 방법을 적어주시면 수정하도록 하겠습니다.

출처 : http://blog.stclab.co.kr/?p=6




메소드로 구현 해 놓기


public String getClientIP(HttpServletRequest request) {


    String ip = request.getHeader("X-FORWARDED-FOR"); 

    

    if (ip == null || ip.length() == 0) {
        ip = request.getHeader("Proxy-Client-IP");
    }


    if (ip == null || ip.length() == 0) {
        ip = request.getHeader("WL-Proxy-Client-IP");  // 웹로직
    }


    if (ip == null || ip.length() == 0) {
        ip = request.getRemoteAddr() ;
    }

    

    return ip;

}

Posted by 앗뜨거
,
728x90
<c:set var="a" value="${L_att}" />
<c:set var="b" value="${'99999'}" />
      <c:set var="c" value="${'99999'}" />


<%

int a = (Integer)pageContext.getAttribute("a");

%>

Posted by 앗뜨거
,
728x90

무조건 json 파일 형식으로만 파일을 뽑으면 된다.

나는 그래서 jstl을 사용하여 Json 파일을 만들어봤다.


기본적으로 이동은

jsp <--> Dao <--> Manager <--> Mapper 로 이동한다.


JSON 으로 출력
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
<%@page import="dto.Chap07Dto"%>
<%@page import="dao.Chap07Dao"%>
<%@page import="java.util.List"%>
<%@page import="java.sql.ResultSet"%>
<%@page import="java.sql.Statement"%>
<%@page import="java.sql.Connection"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
 
 
<%-- ---------------------------------  jSon용으로 출력 -------------------------------------------%>
    
    <jsp:useBean id="dto" class="dto.Chap07Dto">    <%-- dto 객체 생성 --%>
        <jsp:setProperty property="*" name="dto"/>    <%-- dto 객체 다 받아옴 --%>
    </jsp:useBean>
    <%
        Chap07Dao dao = new Chap07Dao();    // dao객체 생성
        List<Chap07Dto> list = dao.getList();    // list변수에 dao의 getList 사용
        request.setAttribute("list", list);    
    %>
    
            <%-- json용으로 뿌려준다 --%>
        
        [
        <c:forEach items="${list }" var="v1" varStatus="i">    <%-- 위에서 만들 list를 뿌려줄 준비 --%>
            <c:if test="${!i.first }">,</c:if>    <%-- 만약 i 가 처음이 아니면 , 을 뿌려준다. --%>
            {
                "id" : "${v1.id }",
                "name" : "${v1.name }",
                "content" :"${v1.content }"
            }
        </c:forEach>
        ]



여기서 중요한건 25 ~ 34줄이다. 

나 같은 경우는

 [ { "id" : "1", "name" : "name", "content" :"content" } , { "id" : "2", "name" : "하이", "content" :"테스트1" } , { "id" : "3", "name" : "jsp", "content" :"콘텐츠" } ]

이런식으로 나온다.


14 ~21줄은 dao에서 mybatis를 거쳐 db의 자료를 가져오는 작업이다.



Ajax에서의 사용


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
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script type="text/javascript">
        $(document).ready(function () {
            // $.ajax()에서 반복 사용하는 속성을 상단에 설정 후 $.ajax에서 상속받아 사용
            $.ajaxSetup({
                url: "./commentlist.jsp",
                dataType: "json"
            });
            
            $.ajax({
                success: function (data) {
                    $.each(data, function () {
                        $('#tblList').append("<tr><td>" + this.id + "</td><td>"
                            + this["name"] + "</td></tr>");
                    });
                }
            });
        });
    </script>
</head>
<body>
    <table id="tblList" border="1"></table>
</body>
</html>


url = json파일의 위치



chap07Dao.java   -  Dao


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package dao;
 
import java.util.List;
 
import mybatis.Chap07Manager;
 
public class Chap07Dao
{
 
    public List getList() 
    {
        List list = Chap07Manager.getList();
        return list;
    }
}
 





Chap07Manager.java   -  Manager



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
package mybatis;
 
import dto.Chap07Dto;
 
import java.io.Reader;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.sql.SQLException;
 
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
 
public class Chap07Manager {
 
    private static SqlSessionFactory sqlMapper;
 
    static {
        try {
            Reader reader = Resources.getResourceAsReader("mybatis/SqlMapConfig.xml"); // classes
                                                                                // 폴더안에있으면
                                                                                // 경로가
                                                                                // 없어도된다.
            sqlMapper = new SqlSessionFactoryBuilder().build(reader);
            reader.close();
        } catch (IOException e) {
            // Fail fast.
            throw new RuntimeException(
                    "Something bad happened while building the SqlMapClient instance."
                            + e, e);
        }
    }
 
    public static List getList() 
    {
        System.out.println("Chap07Manager 의 getList");
        List list = null;
        
        SqlSession session = sqlMapper.openSession();
        list = session.selectList("getList");
        session.commit();
        session.close();
        return list;
    }
    
    
 
    
 
}
 



Chap07Mapper.xml   -  Mapper


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?xml version="1.0" encoding="UTF-8" ?>
 
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 
<mapper namespace="mybatis.Chap07Mapper">
 
  
  <!-- Select with no parameters using the result map for Account class. -->
  <select id="getList" resultType="Chap07Dto">    <!-- value값이 resultMap 값으로 사용가능  //만약 SqlMapConfig에서 typeAliases를 지정해주지않았으면 패키지이름까지 다 써줘야된다.-->
    select * from COMMENT order by ID
  </select>
  
  
  
  
 
</mapper>


Posted by 앗뜨거
,
728x90

[MySQL날짜 차이 구하기

※ 경고
높이뜬새의 모르는 사람이 없는 팁시리즈 입니다.
이 팁시리즈는 지면낭비라는 항의시에 즉각 중단됩니다.

MySQL에서 날짜간의 차이를 구하기 위해서는 TO_DAYS 함수를 사용하시면 됩니다. TO_DAY 함수는 TO_SECONDS 함수처럼 지원하는 버전대가 있는 것도 아니라서 MySQL 버전이 몇이든 상관없이 사용하실 수 있습니다.



형식) MySQL프롬프트> SELECT TO_DAYS(DATE) - TO_DAYS(DATE);


예) 2010년 2월15일과 2010년1월25일의 차이 구하기

mysql> SELECT TO_DAYS('2010-02-15') - TO_DAYS('2010-01-15' ) AS CHA;

예) 2010년의 설날연휴인 2010년 2월13일은 오늘부터 몇 일 남았나 구하기

mysql> SELECT TO_DAYS('2010-02-13') - TO_DAYS(now()) AS CHA;


※ TO_DAYS 함수는 기본 인자로 DATE 형을 취하기 때문에 아래와 같이 CAST함수를 이용해서 DATE형으로 형변환 해서 쓰실 수도 있습니다.


mysql> SELECT TO_DAYS(CAST('2010-03-01' AS DATE)) - TO_DAYS(CAST('2010-01-25' AS DATE)) AS CHA;






테이블 이름에서 근무일이 300일 미만을 출력해라

select * from테이블이름 where to_days(now())-to_days(근무시작일) < 300

Posted by 앗뜨거
,

내가 사고싶은 책 목록

2014. 11. 27. 15:15
728x90


1.아는 만큼 보이는 데이터베이스 설계와 구축

http://book.naver.com/bookdb/book_detail.nhn?bid=4640260


DB실력에 목마르기 전에 하나 사야겠다..



Posted by 앗뜨거
,
728x90
계층형 게시판( 댓글이 있는 )의 구조와 알고리즘에 대해서 알아보자.
설명을 위해 테이블에는 다음과 같은 컬럼들만 있다고 가정한다.

이해를 돕기 위해 수행되는 쿼리와 수행후 테이블의 row를 그려 넣었다. 

no : 글번호(Primary Key)
title : 글제목
grp : 같은 주제를 갖는 게시물의 고유번호. 
       부모글과 부모글로부터 파생된 모든 자식글은 같은 번호를 갖는다.
seq : 같은 그룹내 게시물의 순서
lvl : 같은 그룹내 계층

[MySQL 관련 명령어]
alter table board auto_increment = 1; 
-- 자동증가값 사용시 최초값 셋팅
 
set last_insert_id = 0;
-- 마지막으로 사용된 auto_increment 값 초기화

select last_insert_id() 
-- 마지막으로 사용된 auto_increment 값 반환


예제)
1) 게시판에 첫번째 글이 올라 올때
  

insert into board( title, grp, seq, lvl ) 
values('안녕하세요', (select last_insert_id()+1), 1, 0);
 no title grp seq lvl
 1 안녕하세요 1 1 1
새글(글 등록)의 경우,
no 는 AutoIncrement 로부터 받아온 값
grp는 no와 동일한 값 
seq는 1
lvl은 0 이된다.


2) 두번째, 세번째 글이 올라올때

insert into board( title, grp, seq, lvl ) 

values('날씨가 맑습니다', (select last_insert_id()+1), 1, 0);

no title grp  seqlvl 
1안녕하세요 
 2날씨가 맑습니다 
 3모임이 있습니다 


3) 첫번째 글에 댓글이 올라올때

update board

set seq = seq + 1

where grp = 1

and seq > 1;

insert into board( title, grp, seq, lvl ) 

values('반가워요', 1, 1+1, 0+1);

 no titlegrp seq lvl 
 1 안녕하세요
 2날씨가 맑습니다 
 3 모임이 있습니다3
 4반가워요 
 
댓글의 경우, ( 부모글 : '댓글이 달린 바로 상위글' 원본글일수도 있고 댓글일 수도 있음 )
grp 는 부모글의 grp 값
seq 는 부모글의 seq+1
lvl 은 부모글의 lvl+1 이 된다.

댓글을 삽입하기 이전에
한 글에 대한 댓글이 여러개인 경우 우선순위를 맞춰주기 위해서 
부모글과 동일한 그룹 번호에 있으면서 
부모글의 seq 번호보다 큰 게시물의 seq 번호를 모두 1만큼 증가시킨다


4) 첫번째 글의 댓글에 댓글이 올라올때 
(즉, 네번째 글의 댓글이 댓글이 삽입된 후)

update board

set seq = seq + 1

where grp = 1

and seq > 2;

insert into board( title, grp, seq, lvl ) 

values('감사합니다', 1, 2+1, 1+1);

 no titlegrp seq lvl 
 1 안녕하세요
 2날씨가 맑습니다 
 3 모임이 있습니다3
 4반가워요 
 5 감사합니다



5) 첫번째 글의 두번째 댓글이 올라올때

update board

set seq = seq + 1

where grp = 1

and seq > 1;


insert into board( title, grp, seq, lvl ) 

values('감사합니다', 1, 1+1, 0+1);

 no titlegrp seq lvl 
 1 안녕하세요
 2날씨가 맑습니다 
 3 모임이 있습니다3
 4반가워요 
 5 감사합니다
 6 환영합니다


6) 여섯번째 게시물에 댓글이 올라올때

update board

set seq = seq + 1

where grp = 1

and seq > 2;


insert into board( title, grp, seq, lvl ) 

values('감사합니다', 1, 2+1, 1+1);

 no titlegrp seq lvl 
 1 안녕하세요
 2날씨가 맑습니다 
 3 모임이 있습니다3
 4반가워요 
 5 감사합니다
 6 환영합니다
 7 감사합니다

검색(select) 할 때는 grp를 내림차순으로
seq를 오름차 순으로 정렬하면 된다. 
인덱스는 기본키와 grp+seq의 복합 인덱스를 설정하면 된다.

select * from board order by grp desc, seq asc;

[검색결과]
no title     grp seq lvl
--------------------------------------------
3 모임이 있습니다 3 1 0
2 날씨가 맑습니다 2 1 0
1 안녕하세요 1 1 0
6 환영합니다 1 2 1
7 감사합니다 1 3 2
4 반가워요        1 4 1
5 감사합니다 1 5 2




아래 예는 오라클에서 테이블을 구성하고 검색해 볼 수 있는 환경을 위한 SQL 이다. 

오라클은 AutoIncrement 기능이 없기때문에 sequence 를 이용한다.

<DDL> 예제
 

drop table board;


create table board(

no int primary key,

title varchar2(45),

grp int,

seq int,

lvl int);


drop sequence board_no_seq;


create sequence board_no_seq start with 1 increment by 1;


create index board_grp_seq on board(grp desc, seq asc);


<DML> 예제


[첫번째 게시물 입력 - 새 글 입력]

insert into board

values(board_no_seq.nextval, board_no_seq.currval, 1, 0);


[두번째 게시물 입력 - 새 글 입력]

insert into board

values(board_no_seq.nextval, board_no_seq.currval, 1, 0);


[세번째 게시물 입력 - 새 글 입력]

insert into board

values(board_no_seq.nextval, board_no_seq.currval, 1, 0);


[네번째 게시물 입력 - 첫번째 게시물의 답글]

(답글이 올라오는 경우에는 답글에 부여 할 seq를 먼저 확보해준다.)

update board

set seq=seq+1

where grp=1 and seq > 1;


insert into board

values(board_no_seq.nextval, '반가워요', 1, 2, 1);


[다섯번째 게시물 입력 - 네번째 게시물의 답글]

update board

set seq=seq+1

where grp=1 and seq > 2;


insert into board

values(board_no_seq.nextval, '감사합니다', 1, 3, 2);


[여섯번째 게시물 입력 - 첫번째 게시물의 두번째 답글]

update board

set seq=seq+1

where grp=1 and seq > 1;


insert into board

values(board_no_seq.nextval, 1, 2, 1);


[일곱번째 게시물 입력 - 여섯번째 게시물의 답글]

update board

set seq=seq+1

where grp=1 and seq > 2;


insert into board

values(board_no_seq.nextval, '감사합니다', 1, 3, 2);



[게시판을 검색하는 경우, grp로 내림차순, seq로 오름차순으로 정렬하면 됩니다.]

select case when lvl=0 then no

when lvl>0 then null end no

, rpad('+', lvl, '-')||title title

from board

order by grp desc, seq;


[검색결과]

no    title 

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

3 모임이 있습니다 

2 날씨가 맑습니다 

1 안녕하세요  

+환영합니다  

+-감사합니다  

+반가워요 

+-감사합니다 


출처 : http://hdm6337.tistory.com/entry/%EA%B3%84%EC%B8%B5%ED%98%95-%EA%B2%8C%EC%8B%9C%ED%8C%90-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%EB%8C%93%EA%B8%80-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98

Posted by 앗뜨거
,
728x90

<c:set var="checkDate" var='${request.getParameter("Date")}' />

이렇게 받아온 CheckDate를

 

javascript의 변수인

var chDate 라는 변수가 있을 때

checkDate값을 chDate에 넣어주고 싶습니다.


이런질문이있었다 


답은


var chDate = '<c:out value="${checkDate}"/>';  이렇게 하면된다.

Posted by 앗뜨거
,
728x90

<c:forEach items="${gamelist}" var="b" varStatus="status">
   [${status.index}]: ${gamelist[status.index]}
   <TR>
    <TD>${b.gameid}</TD>
    <TD>${b.displaytype}</TD>
    <TD>${b.displayno}</TD>
    <TD>${b.gamelink}</TD>
    <td><c:if test="${b.ishidden=='T'}"><span style="color:red">Hidden</span></c:if></td>
    <td>${b.lang}</td>
    <td><a href="javascript:edit(${b.bid})">[Edit]</a></td>
   </TR>
  </c:forEach>

.index는 0부터 시작하고

.count는 1부터 시작한다.



출처 : http://jsonlee.tistory.com/52

Posted by 앗뜨거
,
728x90

sqlMapper를 작성할 때 #과 $ 기호의 차이점은 아래와 같다.


# : 매개변수로 전달받은 파라메터를 그대로 삽입한다.

ex) 만약 아래와 같이 SQL이 작성되어 있다고 네임 스페이스는 test.select 라고 하자.

    select * from MEMBER where name = #{name}

    호출시 인자 전달 방법은 아래와 같다.

    getSqlSession.selectOne("test.select", "이지형");


$ : key와 value로 이루어진 Map 형태로 전달된다.

    select * from MEMBER where name = ${name}

    이라고 하면 파라메터 타입을 HashMap으로 넘겨줘야하며 

    name(key)에 해당하는 값(value) SQL 구문에 넣어주게 된다.

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

    map.put("name", "이지형");

    getSqlSession.selectOne("test.select", map);






1. #는 쿼리가 수행될 때, 다음과 같이 된다 

SELECT * FROM USER 

WHERE 
col = ?  


parameter : [값]


?에 bind된 값이 들어가게 된다. 

이 쿼리의 컴파일 된 내용을 재사용 할 수 있고, 파라미터에 따라 대입해주므로 효율적이다.
내부적으로 preparedStatement 객체에서 ? 에 들어갈 파라미터의 값을 set 해줌으로써 사용이 된다.
 
preparedStatement는 한번 수행한 쿼리를 캐싱하는 객체


사용 용도 >>

#일 경우, 에 사용한다.

myBatis : 컬럼명 = #{값}   
iBatis : 컬럼명 = #값#

* 쿼리에 작은 따옴표가 붙게 된다.


2. $는 쿼리가 수행될 때, 다음과 같이 된다

SELECT * FROM USER
WHERE 
col = 



값이 넣어진 쿼리 자체로 수행이 된다.(상수)
즉, 문장 전체가 preparedStatement가 된다.

사용 용도 >>

$일 경우는 컬럼명이 동적으로 바뀌어야 할 때 사용한다. 또는 테이블명.

myBatis : ${컬럼명} = #{값}   
iBatis : $컬럼명$ = #{값}

* 쿼리에 작은따옴표가 붙지 않는다. 
값에 $를 사용하면 스트링의 경우 작은따옴표로 감싸지지 않기 때문에 에러 발생한다.


이렇게 사용하지 않으면 unknown column 이나 There is no readable property named  등등의 에러가 뜨게 된다


출처 : http://warmz.tistory.com/744
   http://marobiana.tistory.com/60


'프로그래밍 > ibatis' 카테고리의 다른 글

iBatis 복수 parameter넘기는법  (0) 2014.11.18
Mybatis 기본 사용법  (0) 2014.10.28
[스크랩]resultMap, resultClass, parameterClass  (0) 2014.10.14
Posted by 앗뜨거
,
728x90

DAO용도인 .JAVA 파일에 다음과 같은 메서드를 만들어 넣는다 단지 map한개만 만들어서 보내고 싶은 파라미터 다 집어 넣으면 된다. 변수 이름과 key값은 같은게 좋을 듯 하다. 

그리고 그냥 MAP만 한개 던저주면 게임 끝이다.

아 이 얼마나 쉬운가 이거 어찌 하나 몇시간 생각했었는데. 혹시 되나하고 해봤는데 되니까 참 .. iBatis 레퍼런스 찾아봐도 되는데 이리 하면 기억에 오래 남아서 머리 싸매고 고민하는게 난 좋다 ㅎㅎㅎ(멍청한 짓인가) 이 프레임워크 만든사람이 나보다 똑똑한 사람일텐데 파라미터 하나 복수로 넘길수 없는 걸 만들었을리 없다는 확신이 있었다. ㅋㅋㅋㅋㅋ

public ArrayList getTimePriceList(String contractCode,String sdate,String edate,String stime,String etime) throws SQLException {
         HashMap map = new HashMap();
         map.put("contractCode", contractCode);
         map.put("sdate", sdate);
         map.put("edate", edate);
         map.put("stime", stime);
         map.put("etime", etime);
         
   list=(ArrayList)sqlMap.queryForList("getTimePriceList",map);  
   return list;
  }

SQL을 지정한 XML에서 다음과 같이 parameterClass를 맵으로 하면 된다. 꼭 MAP이 아니라 list 나 table도 되는지는 귀찮아서 안해봤다. 뭐 되지 않을까 싶다 안되면 되는거 쓰면 되니까 뭐 문제는 없을 듯하다. 
어짜피 parameter넘길뿐인데 뭐든 어떠냐 잘 넘어가기만 하면 되지 ㅎㅎㅎ

<select id="getTimePriceList" parameterClass="java.util.HashMap" resultClass="timeprice">
    <![CDATA[SELECT contractCode,date,time,close,sum(vol) as sumvol from timeprice 
    where 
    contractCode=#contractCode# 
    and date>=#sdate# 
    and date<#edate# 
    and time>=#stime# 
    and time<#etime# 
    group by close order by close
    ]]></select>


출처 : http://hedging.tistory.com/entry/iBatis-%EB%B3%B5%EC%88%98-parameter%EB%84%98%EA%B8%B0%EB%8A%94%EB%B2%95

'프로그래밍 > ibatis' 카테고리의 다른 글

[MyBatis] $ 과 # 차이점  (0) 2014.11.18
Mybatis 기본 사용법  (0) 2014.10.28
[스크랩]resultMap, resultClass, parameterClass  (0) 2014.10.14
Posted by 앗뜨거
,