728x90

계기

1. client -> server 로 오는 url 을 매핑 시켜줄 때도 프로젝트명을 고려해야 하는 번거로움

2. resource , css , js 등 ViewResolver를 타는 것들 역시 프로젝트명을 신경써줘야함

3. 기본 url 이 '로컬호스트(혹은 IP주소):포트번호' 인데 , 모든 url요청에 일일히 프로젝트명을 넣어줘야하는 번거로움

4. 상대경로 url 요청을 절대경로 url 요청으로 변경하다보니 프로젝트명 제거의 필요성을 느끼게됨

 

원인

WAS 내부의 PATH 경로 값이 자동으로 'http://localhost:8090/PATH값' 을 베이스로 잡음

 

해결

PATH 값을 '/' 로 변경시켜줄 것

 

 

톰켓 서버 접속후 , 하단 Modules 클릭

 

설정변경할 프로젝트 선택후 , Edit 클릭

 

Path 경로를 '/' 로 변경

 

프로젝트명없이 실행됨

 

 

728x90

-jsp:include 를 이용하는 경우

jsp:include에 대한 설명 https://sesok808.tistory.com/331

jsp:include action 방식 참고 사이트 : https://all-record.tistory.com/106 

 

사용법 ex)

<jsp:include page="common/nav.jsp" flush="false"/> 

<!-- page: 이동할 jsp 파일을 의미 ,  flush: jsp:include태그를 읽는 시점에 , 현재까지 저장된 출력버퍼를 비울지 여부-->

<!-- 보통은 false 시켜 놓는다 -->

 

-Jquery 를 이용하는 경우 , Javascript의 Ajax를 이용하는 경우

https://kyung-a.tistory.com/18

728x90

- 기초 용어

smtp : 인터넷에서 이메일을 보내기 위해 이용되는 프로토콜이다.

 

간이 전자 우편 전송 프로토콜(Simple Mail Transfer Protocol)이라고 불린다.

사용하는 TCP 포트번호는 25,465,587번이다.

 

https : https를 이용한 인터넷 접속은 기존 http프로토콜에 더해서 보안프로토콜인 SSL 혹은 TLS를 이용하여 클라이언트와 서버간 보안성있는 데이터 왕래를 하게 해줍니다.

 

SSL,TLS : 보안 프로토콜이다. 

SSL TLS 는 응용계층(HTTP,FTP,SMTP)과 전송계층(TCP) 사이에 보안 계층이라는 독립적인 프로토콜계층을 생성하고,

위치합니다.

SSL 암호화 통신은 비대칭키방식으로 암호화에 사용할 키를 교환하고, 대칭키 방식으로 데이터 통신을 한다.

TLS가 SSL의 후속버전이긴 하지만,  두가지 전부 같은 의미이다.

 

- 기본설정

 

pom.xml

1
2
3
4
5
6
7
8
9
10
11
12
<!-- javax.mail -->
        <!-- https://mvnrepository.com/artifact/javax.mail/mail -->
        <dependency>
            <groupId>javax.mail</groupId>
            <artifactId>mail</artifactId>
            <version>1.4.7</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
            <version>${org.springframework-version}</version>
        </dependency>
cs

6: mvnrepository에서 JavaMail API (compat) 을 의존성에 추가한다.

최신버전은 1.5.0-b01 이지만, 1.4.7 , 1.4 버전이 주로 사용된다.

 

root-context.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<!-- 회원가입 메일 인증 -->
    <bean id="mailSender"    class="org.springframework.mail.javamail.JavaMailSenderImpl">
        <property name="host" value="smtp.gmail.com" />
        <property name="port" value="587" /><!-- 465 or (25비추 평문) or 587 -->
        <property name="username" value="1234@gmail.com" />
        <property name="password" value="12345" />
        <property name="defaultEncoding" value="utf-8" />
        <property name="javaMailProperties">
            <props>
                <prop key="mail.transport.protocol">smtp</prop>
                <prop key="mail.smtp.auth">true</prop>
                <prop key="mail.smtp.starttls.enable">true</prop>
                <prop key="mail.debug">true</prop>
            </props>
        </property>
    </bean>
cs

servlet-context.xml 이 아닌 root-context.xml 에  bean을 등록한다. ( root-context.xml은 웹뷰와 관련 없는 bean을 처리 )

4 : 포트번호를 SMTP 평문 포트번호인 25번이 아닌 다른 포트번호로 지정해주었다.

( 사실 본 내용에서는 서버->구글로 전달되는 방식만 정해주는 것이기에 그렇게 보안설정이 중요해 보이지는 않는다. )

5~6 : 서버에서 사용할 구글 아이디 , 비밀번호가 각각 들어간다.

12 : STARTTLS 를 true로 놓아 상호간 TLS버전을 통일시 하도록 한다.

 

SSL과 TLS를 지원하는 포트에 연결되거나, 안전하지 않은 연결이 STARTTLS에 의해 업그레이드되면,

서버,클라이언트양측은 이 중에 지원되는 특정 버전을 쓰도록 합의합니다. 서버가 최신의 TLS v1.3을 지원하더라도, 이메일 클라이언트가 TLS v1.1만 지원한다면, 양측은 TLS v1.1을 쓰게 된다는 겁니다.

 

구글내 설정

보안 수준이 낮은 앱의 액세스를 허용해야 spring 에서 구글 smtp 서버에 접속할 수 있다.

 

-SPRING 에서 활용하기

 

하단의 샘플은 이메일인증키를 사용자에게 발송하는 로직을 가진 서비스.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
import java.util.Random;
import javax.inject.Inject;
import javax.mail.MessagingException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMessage.RecipientType;
import javax.servlet.http.HttpSession;
 
@Service
public class userinfoServiceImpl implements userinfoService{
    
    @Inject
    private userinfoDAO dao;
    @Inject
    private JavaMailSender mailSender;
 
    ~~ 생략 ~~
 
    @Override
    public void createEmailKey(HttpSession session,String usermail) {
        String strKey=getKey(8);
        session.setAttribute("authenticationKey", strKey);
        session.setMaxInactiveInterval(60*3);
        MimeMessage mail=mailSender.createMimeMessage();
        String htmlStr="<h2>안녕하세요 TodaysFortune 웹사이트 입니다! </h2><br><br>" 
                + "<h3>회원님의 가입을 환영합니다<h3>"
                + "<p>이메일 인증 코드 : " 
                + "<span style='color:red;'>"+strKey+"</span></p>"
                + "(혹시 잘못 전달된 메일이라면 이 이메일을 무시하셔도 됩니다)";
        try {
            mail.setSubject("[TodaysFortune] 인증메일입니다.""utf-8");
            mail.setText(htmlStr,"utf-8","html");
            mail.addRecipient(RecipientType.TO,new InternetAddress(usermail));
            mailSender.send(mail);
        } catch (MessagingException e) {
            e.printStackTrace();
        }
 
    }
 
    ~~~ 생략 ~~
}
cs

14~15 : root-context.xml 에서 정의한 bean을 주입시켜준다.

24 : MimeMessage 객체를 생성해준다.

31 : 메일의 제목.

32 : 메일의 본문

33 : 메일 수신자 설정.

34 : 실제 메일 발송.

 

하단은 daum 홈페이지에서 수신된 이메일이다.

 

참고 : SSL,TLS,HTTPS정리사이트 https://blog.naver.com/skinfosec2000/222135874222

        STARTTLS 원문번역사이트 https://tech.yeon.me/blog/ssl-tls-starttls%EC%9D%98-%EC%97%AD%EC%82%AC/

        서브 OKKY 참고자료 https://okky.kr/article/329317?note=1834311

        spring javaxmail 참고자료 http://blog.naver.com/vnemftnsska2/221413314636

       

추후 볼만한 사이트 : 이미지,파일,대량의 메일을 전송하는방법 https://offbyone.tistory.com/167

728x90

-mysql5.5ver+Spring 사용중  Mysql의 시간과 Spring 시간이 불일치하는 문제 발생-

원인예측 : Mysql에서 나의 특정 테이블의 특정 시간컬럼의 속성은 TIMESTAMP이다 .
TIMESTAMP의 특성상 기본적인 TIME_ZONE을 설정해주면 저장될때는 당연히 UTC 기반으로 저장되고 ,
출력 될때는 TIME_ZONE에 맞게 변형되어서 출력된다.  다만, 나의 경우에는 TIME_ZONE을 설정해주지 않아서 이상한 문제가 발생함.

 

TIMESTAMP에 대해 자세한 설명
https://mysqldba.tistory.com/268

첫번재 시도(실패) : 
dataSource의 url 경로에 serverTimezone=KST  을 설정하려함
이유 : pom.xml 의 mysql-connector-java version이  5.1.X 이후 버전부터   serverTimezone=KST 가 먹지 않음.  

두번재 시도(성공)
https://dogcowking.tistory.com/179 의 방법 2를 따라하여 serverTimezone값을 Asia/Seoul로 직접변경.


 

-SQLYOG 저장 쿼리복구-
Mysql이 중지후 재시작 되었을때 , SQLYOG 기본 쿼리들이 제거되고 ysav(세션 세이브포인트)만 남김.
C:\Users\username\AppData\Roaming\SQLyog 에 connrestore_backup.ysav  파일이 있으니 불러오기만 하면됨.(파일-오픈세션 세이브포인트)

728x90

-개요 이자 문제점

 

하단의 코드는 게시판을 삽입하는 *mapper.xml 코드이다. 

oracle에서는 아래처럼 하면 되지만 , mysql에서는 시퀀스 사용이 불가능하다.

( mysql 에서 그나마 사용 가능한 비스무리 한건 auto_increment 를 적용해서 nextval 효과를 내는것) 

1
2
3
4
<insert id="insertBoard" parameterType="ITboardDTO">
          insert into itboard (bidx,board_ref, ~~생략~~) values
         (itboard_bidx.nextval,(itboard_bidx.currval,~~생략~~)
</insert>
cs

 

나는 mysql 에서 오라클의 시퀀스(nextval,currval)의 기능을 이용하고 싶다.

 

-방법1   MAX(auto_increment적용된 컬럼) 이용

 

하단의 코드는 사전작업으로 , bidx라는 컬럼에 auto_increment 효과를 주었다. 

1
2
3
4
<insert id="insertBoard" parameterType="ITboardDTO">
          insert into itboard (board_ref, ~~생략~~) values
          ((select max(bidx)+1 from itboard),~~생략~~)
</insert>
cs

결과로는 bidx는 하나증가된 값을 가지고 , 

이와 같은 값을 board_ref 가 가지게 된다.

( 3번째줄의 (select max(bidx)+1 from itboard)  서브쿼리가 하나의 트랜잭션으로 독립적으로 취급된다면 

레이스 컨디션 상태라고 말할수 있겠지만 , 2~3줄을 합쳐서 하나의 트랜잭션인것 같다..  그러면 문제없음. )

https://droptable.tistory.com/33 ( 사이트를 보면 맨 밑 예시는 분명 레이스 컨디션이 발생할만한 상황이다 )

 

레이스 컨디션이라는 용어는 하단의 사이트에서 자세히 알 수 있다.

http://blog.naver.com/PostView.nhn?blogId=kojaejung&logNo=40109677766 

트랜잭션의 독립성은 하단의 주소를 보자.

 https://junghn.tistory.com/entry/DataBase기초-트랜잭션이란-무엇인가-Transaction 

 

 

-방법2    시퀀스테이블,시퀀스생성프로시져,함수  이용하기

 

그냥 MAX(auto_increment적용된 컬럼) 요거를 사용할 수도 있었지만 찜찜해서 방법2로 진행하기로 하였다.

 

하단의 샘플은 SQLYOG에서 작성한 쿼리문이고 , 게시글들을 카테고리별로 구별하여 curval,nextval에 이용하게 될것이다.

순서는 1 . 시퀀스테이블 생성 ,  2. 프로시져정의 3. 두개의 함수(nextval , curval) 정의이다.

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
# mysql 에서  curval,nextval 구현하기
CREATE TABLE BOARD_SEQUENCES
(
    CATEGORY TINYINT(1)
  , CURRVAL BIGINT UNSIGNED
)
ENGINE = INNODB
 
DELIMITER $$
    CREATE PROCEDURE create_boardsequence(IN THE_CATEGORY TINYINT)
    MODIFIES SQL DATA
    DETERMINISTIC
    BEGIN
        DELETE FROM board_sequences WHERE CATEGORY = THE_CATEGORY;
        INSERT INTO board_sequences VALUES(THE_CATEGORY, 0);
   END
DELIMITER //
    CREATE FUNCTION `boardnextval` (THE_CATEGORY TINYINT(1))
    RETURNS BIGINT UNSIGNED
    MODIFIES SQL DATA
    DETERMINISTIC
    BEGIN
        DECLARE ret BIGINT UNSIGNED;
        UPDATE board_sequences SET currval = currval +1 WHERE CATEGORY = THE_CATEGORY;
        SELECT currval INTO ret FROM board_sequences WHERE CATEGORY = THE_CATEGORY LIMIT 1;
        RETURN ret;
   END
DELIMITER //
    CREATE FUNCTION `boardcurval` (THE_CATEGORY TINYINT(1))
    RETURNS BIGINT UNSIGNED
    DETERMINISTIC
    BEGIN
        DECLARE ret BIGINT UNSIGNED;
        SELECT currval INTO ret FROM board_sequences WHERE CATEGORY = THE_CATEGORY LIMIT 1;
        RETURN ret;
   END
CALL create_boardsequence('1');
cs

2~6 :    시퀀스 테이블을 정의 해주었다.   

9~16 :  인자로 들어오는 THE_CATEGORY가  BOARD_SEQUENCES테이블의  CATEGORY에 할당되며,

          BOARD_SEQUENCES테이블의  CURRVAL을 0으로 초기화 한다.

 

프로시져의 구성.

MODIFIES SQL DATA :
MODIFIES SQL DATA 는 함수혹은 프로시져가 db에 저장된 data를 수정할수있는 명령문을 포함한다는 것을 의미한다.
이것은 함수혹은 프로시저에 DELETE, UPDATE, INSERT, REPLACE 또는 DDL과 같은 명령문이 포함 된 경우 넣어준다.
DETERMINISTIC : 요약하면 함수혹은 프로시져의 인자값이 바뀌지 않는 이상 함수혹은프로시저의 호출은 한번만 한다는 것이다.

NO DETERMINISTIC 으로 설정한다면 조건에 따른 모든 경우에 함수 혹은 프로시져가 호출됨. 자세한 것은 하단의 주소를 참고한다.
http://intomysql.blogspot.com/2010/12/stored-function-not-deterministic.html 참고

프로시져를 생성하는 방법에 대해서는 하단의 주소를 참고한다.

https://m.blog.naver.com/alcmskfl17/221858522028

IN, OUT, INOUT 에 대한 설명은 하단의 주소를 참고한다.(어색하지만 잘 설명되어있음)

https://blog.duveen.me/14

 

17~27 : nextval을 구현한 함수이다.

          board_sequences 테이블에서 curval함수의 입력된 인자가 CATEGORY와 동일한 레코드를 찾아서,

          currval을 하나 증가시켜준다.

          25~26번째 줄은 증가된 currval을 리턴시키는 작업이다.

 

추가로 SELECT INTO reto ~  쿼리에서  INTO는 나온결과물을 reto에 대입시킨다는 의미이다. 자세한건 하단의 주소를 참고하자.

https://newpower.tistory.com/160

29~36 : curval을 구현한 함수이다.

37 : CALL create_boardsequence('1');  CALL을 붙여 프로시져를 호출하였다.

      시퀀스테이블에 CATEGORY=1, CURRVAL=0 인 레코드가 생성되었다. 

 

#사용법예시 INSERT INTO test (id,pw,NAME) VALUES ( boardnextval('1') , boardcurval('1'),boardcurval('1') );

예시의 결과레코드는  3개의 컬럼 모두 같은 값이 나온다.

 

이제 Mybatis  *mapper.xml 내용을 보자

1
2
3
4
  <insert id="insertBoard" parameterType="ITboardDTO">
          insert into itboard (bidx,board_ref, ~~생략~~) values
          (boardnextval(#{category}),boardcurval(#{category}), ~~생략~~ )
  </insert>
cs

3 : Mybatis+mysql 에서 sql function을 수행하는 것은 간단하다.  3번째줄 처럼 '함수명(#{인자})' 로 사용하면 된다.

결과는 내가 원하는 대로 나왔다.  bidx와 board_ref는 같은 값을 가지게 되었다.

 

mybatis+mysql 를 사용하는 환경에서 sql function 기능을 사용할때는 윗 방법대로 사용하면 되지만,

만약 sql 프로시져 기능을 사용하려 한다면 

태그 내부에 statementType="CALLABLE" 이라는 속성을 추가해 줘야 프로시져로 인식하여 프로시져를 수행한다.

옆사이트에 예시가 있다. https://krespo.net/164

 

 

 

-참고

https://proudin.tistory.com/28

 

728x90

-요약

HTTP의 특징  2가지:

1. 비연결성은 HTTP통신 이후 연결을 끊는 특징이고,

2. 비상태성은 이전 HTTP 통신의 상태를 유지하지 않는다는 것

이를 해결하고자 쿠키와 세션을 이용함.

https://velog.io/@ground4ekd/auth-cookie-session 참고.

 

쿠키 : KEY,VALUE 인 STRING 형태로 ,  클라이언트에 저장됨.    보안 약함.
세션 : Object 형태로 서버에 저장됨.   쿠키보다 보안이 좋음

 

자세한 정보는 https://devuna.tistory.com/23 을 참고하였다.

 

 

-직접사용해보기

 

하단에 있는 샘플은 사용자가 로그인 페이지에서 ID,PASSWORD()를 입력후

Login-post url 를 호출하였을때의 controller 상황이다.

-1. 쿠키생성-

1
2
3
4
5
6
7
8
9
10
11
12
13
14
    @RequestMapping(value="/Login",method = RequestMethod.POST)
    public String postLogin(~~~~,HttpServletResponse response) throws Exception {
        System.out.println("controller - Login-POST");
        if((Integer)service.selectMember(userinfoVO)==1) {
            
            //create a cookie for the user id
            Cookie theCookie = new Cookie("IcApp.userName", userinfoVO.getId());
            theCookie.setMaxAge(60*60*24 );
            
            //add the cookie to the response
            response.addCookie(theCookie);
            
            return "main";
        }
cs

2 : server ->  client  로 쿠키를 넣어주기 위하여 HttpServletResponse  객체를 생성하였다.

7 : ( KEY , VALUE ) 형태로 쿠키를 생성한다 .   (참고로 userinfoVO.getId()은 사용자가 로그인페이지 에서 입력했던 id가 저장되어있다)   

8 : 쿠키의 유효시간을 하루로 설정하였다.  단위는 1초이다.

11 ,13: 쿠키를 response 에 실어서 main 페이지를 호출하였다.

 

결과페이지에서 생성된 쿠키를 확인 할 수 있다.

 

하단에 있는 샘플은 사용자가 로그인페이지로  이동하는 요청을 서버에 보냈을 경우이다.

- 2. client -> server 쿠키전달, 및 활용 (1) 비추-  (비추의 이유 : spring 을 쓴다면 어노테이션으로 축약해서 쓰자..)  

1
2
3
4
5
6
7
8
9
10
11
@RequestMapping(value="/Login",method = RequestMethod.GET)
    public String getLogin(HttpServletRequest request,Model model) {        
        Cookie[] cookies = request.getCookies();//모든 쿠키들을 얻는다.
        for(Cookie temp : cookies) {
            if("IcApp.userName".equals(temp.getName())) {  //쿠키의 key 얻어옴    
                String userId = temp.getValue(); //쿠키의 value를 얻어옴
                model.addAttribute("userid", userId);
            }
        }
        return "Login";
    }
cs

2 : client -> server 로 넘겨주는 데이터(쿠키포함)를 받기 위해 HttpServletRequest 객체를 생성하였다.

3 : 클라이언트로부터 넘어온 모든 쿠키들을 얻는다.

4~9 :  쿠키의 key가 "IcApp.userName" 인 쿠키를 뽑는다.

         그리고 해당 쿠키의 value를 다시 model객체에 실어 client에 보낸다. 

10 : Login 페이지를 호출.

 

 

로그인페이지에 들어오자마자 자동으로 입력된 아이디를 확인 할 수있다. (물론 front부분도 dom탐색 처리해줬음)

 

 

 

@CookieValue ?

@CookieValue 어노테이션을 이용한다면 , HttpServletRequest 객체를 이용하지 않아도 

client로 부터 server가 원하는 cookie만 받아올 수 있다.

 

ex) @CookieValue(value="count", defaultValue="1", required=true) 자료형 변수

value : 적어야함.

value 속성값으로 전달 받을 쿠키의 이름을 지정한다.

required : 안적어도됨. (default : true )

required 속성을 true로 지정 하였다면,

value라는 key를 가진 쿠키가 존재하지 않을 시에 SPRING MVC는 Exception을 발생시킨다.

반대의 경우엔 Exception을 발생시키지 않는다.

defaultValue : 안적어도됨.

defaultValue은 쿠키가 존재하지 않을 경우 변수의 기본 값인듯.. 써보지 않음.

변수 : 적어야함.

변수에는 선택된 쿠키의 value가 들어감.

 

하단의 샘플은 윗 반복문 샘플과 동일한 수행을 한다.  

윗 샘플과 같이 , 사용자가 로그인페이지로  이동하는 요청을 서버에 보냈을 경우이다.

- 2. client -> server 쿠키전달, 및 활용 (2) 추천-  

1
2
3
4
5
6
@RequestMapping(value="/Login",method = RequestMethod.GET)
    public String getLogin(@CookieValue(value="IcApp.userName",required=falseString userId ,Model model) {
        System.out.println("controller - Login-GET");
        model.addAttribute("userid", userId);
        return "Login";
    }
cs

2 : required 를 false로 지정해주었다. default인 true로 하게 된다면 ,, 

"IcApp.userName"이라는 key를 가지는 쿠키가 없을때 에러를 발생시킨다. 아마 500 에러 날듯.

 

 

로그인페이지에 들어갔을때 , 자동으로 id가 완성된것을 볼수 있다.

 


-세션직접사용해보기

 

하단의 샘플은 사용자가 로그인페이지에서 로그인 정보를 입력하고 로그인 버튼을 눌렀을 경우 main페이지로 보내주는 예제이다.

1
2
3
4
5
6
7
8
9
10
    @RequestMapping(value="/Login",method = RequestMethod.POST)
    public String postLogin(UserinfoVO userinfoVO,HttpServletRequest request,~) throws Exception {
        System.out.println("controller - Login-POST");
        //id pw 비교
        if((Integer)service.selectMember(userinfoVO)==1) {
        //id pw 가 일치 할경우 , 세션 등록
            HttpSession session=request.getSession();
            session.setAttribute("Session_userID", userinfoVO.getId()); 
        return "main";
    }
cs

-기초개념-

서버가 최초로 jsp 페이지에 접근할때 , 마땅한 설정이 없다면 톰켓이 JSESSIONID 쿠키를 자동으로 생성해서 client로 전달한다. 

JSESSIONID : 톰캣 컨테이너에서 세션을 유지하기 위해 발급하는 키

 

2 :  client->server 로 JSESSIONID 쿠키를 가져오기 위해서   HttpServletRequest 객체를 선언하였다.

7 : 세션획득.    JSESSIONID 쿠키가없다면 새 사용자라는 것으로 인식하여 새로운 Session을 만들고 반환, 

    JSESSIONID 쿠키가 있으면 존재하는 Session을 반환함.

8 : 세션 key-value를 한번 설정해두면 프로젝트내 모든 파일에서 "Session_userID" 에 접근이 가능하다.

 

프로젝트내 모든 파일에서 "Session_userID" 에 접근이 가능하다는 소리는 무슨 원리냐면은 ...

SSR원리에 의해 모든 view파일을 서버에서 만들어주고 client로 보내준다.

즉 , 서버 메모리에서  뷰단내에 있는 세션 key에 value를 붙여넣는 원리이다. 

 

보조설명으로,
브라우저의 쿠키중 JSESSIONID 의  value는 특정사용자에 대한 값으로 ,  서버가 특정 유저를 추적하는데 이용한다.
클라이언트가 Session key인 "Session_userID"의 value를 이용하려 할때,
우리가 외관적으로 보기에 모든 클라이언트에 동일한 session key ("Session_userID") - value  를 가지는 것 처럼 보이지만 
실제로는 JSESSIONID를 통해 session들을 구분하고 , 구분된 세션에서  session key ("Session_userID")에 대한 값을 얻는것이다.
즉, 클라이언트마다 JSESSIONID가 다르므로 다른 Session value를 얻게된다.

 

추가로) JSESSION value와    request를 통해 얻게되는 Httpsession객체.getId() 값은 동일하다.

 

하단의 결과 이미지들로 , 우리는 다른 브라우저마다 다른 세션 value를 얻은 것을 확인 할 수 있고,

JSESSIONID도 각각 다른 것을 확인 할 수 있다.

( view 단에서는 단순히 Session : ${Session_userID}  을 이용하였다. ) 

chrome에서 teamproject/test url로 접속

 

Internet Explorer 에서 teamproject/test url로 접속

 

- 세션 value 얻기 -

메소드에서 HttpServletRequest 파라미터를 가지는 대신 HttpSession 파라미터를 넣고

HttpSession객체변수.getAttribute("key값");  을 통하여 컨트롤러에서 데이터를 얻어 올 수도 있다.

 

 

하단의 샘플은 사용자가 로그아웃 버튼을 클릭시 서버에서 세션을 삭제해준다.

-server 에서 세션 삭제 - 

1
2
3
4
5
6
    @RequestMapping(value="/Logout",method = RequestMethod.POST)
    public String logOut(HttpSession session) {
        System.out.println("controller - logOut");
            session.invalidate();
            return "main";
    }
cs

2 : HttpSession 객체를 통해 JSESSIONID 쿠키와 연관된 세션을 받아온다.

4 : JSESSIONID 의 value에 일치하는 세션을 삭제한다.

5 : main page로 이동한다. 로그아웃 된 것을 확인 할 수 있다.

 

하단의 결과를 보면 , 메인 페이지에서 기존의 JSESSIONID쿠키가 삭제되고

새로운 JSESSIONID가 생성된 것을 확인할 수 있다.

 

 

하단처럼 web.xml 파일이 있을 경우 직접 세션만료시간을 수정할수 있다.(분단위)

-web.xml(tomcat server)-

1
2
3
4
5
6
7
  <!-- ==================== Default Session Configuration ================= -->
  <!-- You can set the default session timeout (in minutes) for all newly   -->
  <!-- created sessions by modifying the value below.                       -->
 
    <session-config>
        <session-timeout>30</session-timeout>
    </session-config>
cs

 

web.xml 파일을 이용하고 있지 않거나 명령을 덮어 쓰고 싶을 경우 , 다음 명령어를 이용하여 제한을 줄 수 있다.

1
session.setMaxInactiveInterval(120);
cs

1 : 사용자가 웹사이트를 이용하고 있지 않은 경우 ,세션 만료시간 제한을 걸어준다.

    초 단위이며 , 인수가 음수일 경우 세션만료없음

 

 

-추가개념-

세션을 다룰때 ,  1.  HttpSession    2. HttpServletRequest 의 getsession  방법외에도

어노테이션을 이용하여 다음과 같이 다룰수 있다.

1
2
3
@Controller
@SessionAttributes("userinfoVO")   //실제내부에선 HttpSession 다룸
public class HomeController {
cs

  컨트롤러 클래스 윗부분에 @SessionAttributes 어노테이션을 지정한다.

자세한 사용법은 후에 필요할시에 찾아보자..

 

 

-연관없는 추가개념

servlet-context.xml와 root-context.xml의 차이 는 아랫 사이트에서 잘 정리가 되어있다.

https://thiago6.tistory.com/70

 

 

참고개념 : Selenium Express의 Session & cookie https://www.youtube.com/watch?v=cpFfzE9eGT0

728x90

-SPRING+MYSQL+MYBATIS 연동하는 방법-

https://all-record.tistory.com/175?category=733072 

윗사이트에 자세히 나와있다.

 

-한글설정-

mysql 내부에서 한글지정.

1
2
3
#한글설정
ALTER DATABASE webprojectdb CHARACTER SET utf8 COLLATE utf8_general_ci;
ALTER TABLE userinfo DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
cs

윗 두줄을 이용하여 db와 테이블 두곳에 utf8을 지정한다.

 

-Spring-DB사이 한글지정-

-root-context.xml-

1
2
3
4
5
6
7
8
9
<!-- MySQL dataSource -->
    <bean id="dataSource"
        class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="net.sf.log4jdbc.sql.jdbcapi.DriverSpy"></property>
        <property name="url"
            value="jdbc:log4jdbc:mysql://127.0.0.1:3306/webprojectdb?useUnicode=yes&amp;characterEncoding=utf8&amp;useSSL=false&amp;serverTimezone=UTC"></property>
        <property name="username" value="root"></property>
        <property name="password" value="0000"></property>
    </bean>
cs

6 : 해당 줄의 webprojectdb 이라는 DB 뒤에 useUnicode=yes&amp;characterEncoding=utf8&amp; 를 지정해줘야

Spring-DB사이 데이터가 오고가는데 UTF8 설정이 됩니다.

 

 

-Spring 한글 설정-

-web.xml-

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<filter>
    <filter-name>encodingFilter</filter-name>
    <filter-class>
        org.springframework.web.filter.CharacterEncodingFilter     
    </filter-class>
    <init-param>
        <param-name>encoding</param-name>   
        <param-value>UTF-8</param-value>
    </init-param>
    <init-param>
        <param-name>forceEncoding</param-name>  
        <param-value>true</param-value>
    </init-param>
</filter>    
 
<filter-mapping>
    <filter-name>encodingFilter</filter-name>
    <url-pattern>/*</url-pattern>                 
</filter-mapping>
cs

 

-참고-

다양한 어노테이션 방식과 여러 spring 개념들은

https://codevang.tistory.com/249?category=849481#recentEntries 

에 자세히 설명되어있다.

+ Recent posts