728x90
반응형

JSP: CSS

- ::before & ::after (feat. +버튼) -


KeyPoint
- css를 이용하여 + 버튼 만들기
- ::before >> 선택한 요소의 앞부분에 적용할 css
- ::after >> 선택한 요소의 뒷부분에 적용할 css

 


들어가며

새 프로젝트에 들어가기 전, 참고할 코드를 받았다.

분석하는 도중에 위젯 추가를 위해 +버튼이 있었는데 이미지를 넣은건가? 싶어서 jsp를 봤다. (하라는 분석은 안하고)

jsp에 class만 적용되어 있어 css파일을 열어봤는데 이곳에서도 img파일경로를 찾을 수 없었다.

그러던 중, 같은 class명에 :before와 :after가 붙은 것이 있어서 개발자도구에서 하나하나 on/off해보며 어떤 기능을 하는건지 봤다.

하다보니 흥미로워서 나중에 또 사용하기 위해 기록하기로 했다.

 


+(추가, 플러스)버튼 만들기

jsp파일 생성

먼저, 테스트를 하기 위해 jsp파일을 하나 생성하고 <body>태그 안에 <button>을 넣어주었다.

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" import="java.util.*"%>
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
	<button><span>추가</span></button>
</body>
</html>

그러면 이렇게 덩그러니 버튼 하나가 나온다.

 

 

▶ css 적용

.btnAdd CSS 추가

<head>태그 안에 <style type="text/css">태그를 넣어주고, 아래 코드를 넣었다.

.btnAdd {
    position: relative;
    width: 24px;
    height: 24px;
    margin-left: 10px;
    border-radius: 50%;
    background: #8faadc;
}

그리고 아까 생성한 <button> 태그 안에 class="btnAdd"를 추가해줬다.

<button class="btnAdd"><span>추가</span></button>

그랬더니 이렇게 버튼이 바뀌었다.

글자가 저렇게 있는게 싫어서 글자는 가려주기로 했다.

 

→ .hidden CSS 추가

.hidden {
    display: block;
    margin: 0;
    padding: 0;
    width: 0;
    height: 0;
    overflow: hidden;
    font-size: 0;
    line-height: 0;
    visibility: hidden;
}

그리고 <span>태그 안에 class="hidden" 추가

<button class="btnAdd"><span class="hidden">추가</span></button>

글자가 사라진 것을 확인

 

 

:before CSS 추가

.btnAdd:before {
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    display: block;
    content: '';
    width: 16px;
    height: 2px;
    background-color: #fff;
}

가로줄이 생겼다..!

 

 

:after CSS 추가

이번에는 :before를 잠시 주석처리하고 :after를 넣어보았다.

.btnAdd:after {
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    display: block;
    content: '';
    width: 2px;
    height: 16px;
    background-color: #fff;
}

이번엔 세로줄이 생겼다.

 

:before와 :after에서, 위치 관련 내용들은 빼고 차이가 있다면 width와 height이다.

그리고 content에 아무 내용도 넣지 않아서 width와 height만큼 background-color: #fff;(=white)로 나온 것이다.

기존의 .btnAdd 전과 후에 ㅡ ㅣ를 각각 넣고, 위치조정을 통해 +버튼을 만든 것이다.

 

이 둘을 합치면 +가 나오겠지..

 

→ 완성된 코드

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" import="java.util.*"%>
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<style type="text/css">
    .hidden {
        display: block;
        margin: 0;
        padding: 0;
        width: 0;
        height: 0;
        overflow: hidden;
        font-size: 0;
        line-height: 0;
        visibility: hidden;
    }

    .btnAdd {
        position: relative;
        width: 24px;
        height: 24px;
        margin-left: 10px;
        border-radius: 50%;
        background: #8faadc;
    }

    .btnAdd:after {
        position: absolute;
        left: 50%;
        top: 50%;
        transform: translate(-50%, -50%);
        display: block;
        content: '';
        width: 2px;
        height: 16px;
        background-color: #fff;
    }

    .btnAdd:before {
        position: absolute;
        left: 50%;
        top: 50%;
        transform: translate(-50%, -50%);
        display: block;
        content: '';
        width: 16px;
        height: 2px;
        background-color: #fff;
    }
</style>
</head>
<body>
    <button class="btnAdd"><span class="hidden">추가</span></button>
</body>
</html>

완성된.. 모양.. 완벽..

 

 


마치며

CSS is Awesome...을 또 느꼈다..

다시 코드 분석하러 가야지,,

 


참고
:before와 :after에 대한 정리 사이트

https://developer.mozilla.org/ko/docs/Web/CSS/::before

 

::before (:before) - CSS: Cascading Style Sheets | MDN

CSS에서, ::before는 선택한 요소의 첫 자식으로 의사 요소를 하나 생성합니다. 보통 content 속성과 함께 짝지어, 요소에 장식용 콘텐츠를 추가할 때 사용합니다.

developer.mozilla.org

https://developer.mozilla.org/ko/docs/Web/CSS/::after

 

::after (:after) - CSS: Cascading Style Sheets | MDN

CSS에서, ::after는 선택한 요소의 맨 마지막 자식으로 의사 요소를 하나 생성합니다. 보통 content 속성과 함께 짝지어, 요소에 장식용 콘텐츠를 추가할 때 사용합니다.

developer.mozilla.org


 

 

 

 

 

End.

heisely's 괴발개발 개발일지

 

728x90
반응형

'Programming > JSP' 카테고리의 다른 글

[JSP: CSS] white-space:pre (feat. vertical-align)  (0) 2022.04.19
728x90
반응형

JAVA

- LocalTime -


KeyPoint
- LocalTime 클래스
- 시간 객체 접근 메서드
- 시간 객체의 필드값 변경
- 시간 객체의 비교

 


 

LocalTime 클래스

LocalTime 클래스: 시간을 표현하는데 사용되는 클래스

 

시간 객체 생성 메서드

  • now(): 현재 시간을 이용하여 새로운 객체를 생성하여 반환
  • of(): 전달된 파라미터값으로 특정 시간을 표현하는 새로운 객체를 생성하여 반환

 

▶ 예제

import java.time.LocalTime;

public class Main {
    public static void main(String[] args){

        LocalTime present = LocalTime.now();
        // static LocalTime of(int hour, int minute, int second);
        LocalTime lunch = LocalTime.of(11, 30, 20);

        System.out.println("현재 시간 : " + present);
        System.out.println("점심 시간 : " + lunch);

    }
}

 


 

시간 객체 접근 메서드
- getter 메서드

▶ getter 메서드

메서드 설명
int get(TemporalField field)
long getLong(TemporalField field)
해당 시간 객체의 명시된 필드의 값을 int형이나 long형으로 반환
int getHour() 해당 시간 객체의 시(HOUR_OF_DAY) 필드의 값을 반환
int getMinute() 해당 시간 객체의 분(MINUTE_OF_HOUR) 필드의 값을 반환
int getSecond() 해당 시간 객체의 초(SECOND_OF_MINUTE) 필드의 값을 반환
int getNano() 해당 시간 객체의 나노초(NANO_OF_SECOND) 필드의 값을 반환

 

▶ 예제

import java.time.LocalTime;

public class Main {
	public static void main(String[] args){
    	
        LocalTime present = LocalTime.now();
        
        System.out.println("현재 시간 : " + present);
		System.out.println("현재 시간 : " + present.getHour() + "시 " + present.getMinute() + "분");
        
	}
}

 


 

시간 객체의 필드값 변경
- with() 메서드
- plus()/minus() 메서드

with() 메서드

메서드 설명
LocalTime with(TemporalField field, long newValue) 해당 시간 객체에서 특정 필드를 전달된 값으로 설정한 새로운 시간 객체 반환
LocalTime withHour(int Hour) 해당 시간 객체에서 시(HOUR_OF_DAY) 필드를 전달된 값으로 설정한 새로운 시간 객체 반환
LocalTime withMinute(int minute) 해당 시간 객체에서 분(MINUTE_OF_HOUR) 필드를 전달된 값으로 설정한 새로운 시간 객체 반환
LocalTime withSecond(int second) 해당 시간 객체에서 초(SECOND_OF_MINUTE) 필드를 전달된 값으로 설정한 새로운 시간 객체 반환
LocalTime withNano(int nanoOfSecond) 해당 시간 객체에서 나노초(NANO_OF_SECOND) 필드를 전달된 값으로 설정한 새로운 시간 객체 반환

 

plus()/minus() 메서드

특정 필드의 값을 더하거나 뺼 수 있는 메서드

메서드 설명
plusHours(long hoursToAdd) 해당 시간 객체에서 시(HOUR_OF_DAY) 필드에 전달된 값을 더한 값으로 설정한 새로운 시간 객체 반환
plusMinutes(long minutesToAdd) 해당 시간 객체에서 분(MINUTE_OF_HOUR) 필드에 전달된 값을 더한 값으로 설정한 새로운 시간 객체 반환
plusSeconds(long secondsToAdd) 해당 시간 객체에서 초(SECOND_OF_MINUTE) 필드에 전달된 값을 더한 값으로 설정한 새로운 시간 객체 반환
plusNanos(long nanosToAdd) 해당 시간 객체에서 나노초(NANO_OF_SECOND) 필드에 전달된 값을 더한 값으로 설정한 새로운 시간 객체 반환

minusXXX는 plus와 반대

 

▶ 예제

import java.time.LocalTime;

public class Main {
    public static void main(String[] args){

        LocalTime present = LocalTime.now();
        LocalTime setTime = present.withHour(12);

        System.out.println("현재 시간 : " + present);
        System.out.println("현재 시간 : " + present.getHour() + "시 " + present.getMinute() + "분");
        System.out.println("바뀐 시간 : " + setTime.getHour() + "시 " + setTime.getMinute() + "분");
        System.out.println("더한 시간 : " + present.plusHours(1).getHour() + "시 " + present.plusMinutes(20).getMinute() + "분");
        System.out.println("뺀 시간 : " + present.minusHours(1).getHour() + "시 " + present.minusMinutes(20).getMinute() + "분");

    }
}

 


 

시간 객체의 비교
- isBefore() / isAfter()
메서드 설명
isBefore() 두 개의 시간 객체를 비교하여 현재 객체가 명시된 객체보다 앞선 시간인지 비교
isAfter() 두 개의 시간 객체를 비교하여 현재 객체가 명시된 객체보다 늦은 시간인지 비교

 

▶ 예제

import java.time.LocalTime;

public class Main {
    public static void main(String[] args){

        LocalTime present = LocalTime.now();
        // static LocalTime of(int hour, int minute, int second);
        LocalTime lunch = LocalTime.of(11, 30, 20);

        System.out.println("현재 시간: " + present.getHour() + "시 " + present.getMinute() + "분 " + present.getSecond() + "초");
        System.out.println("점심 시간: " + lunch.getHour() + "시 " + lunch.getMinute() + "분 " + lunch.getSecond() + "초");
        System.out.println(present.isBefore(lunch));        
        System.out.println(present.isAfter(lunch));        
    }
}

 


 

참고

http://www.tcpschool.com/java/java_time_localDateTime

 

코딩교육 티씨피스쿨

4차산업혁명, 코딩교육, 소프트웨어교육, 코딩기초, SW코딩, 기초코딩부터 자바 파이썬 등

tcpschool.com

 


 

 

 

 

 

End.

heisely's 괴발개발 개발일지

728x90
반응형

'Programming > JAVA' 카테고리의 다른 글

[JAVA] CamelCase  (0) 2022.03.29
[JAVA] Dynamic Web Project > Maven Project 변환  (0) 2022.03.16
728x90
반응형

JS

- 문자열 자르기 -


KeyPoint
- replace()

 


들어가며

토이프로젝트 진행하면서 "이력"을 등록할 일이 있었다.

수정된 내용을 등록하는건데, "기존의 내용 >> 수정된 내용"의 형식으로 등록되게 하려고 했다.

하지만 모든 내용이 수정되는 것이 아니기때문에 수정된 내용만 등록되게 하려면 약간의 노가다가 필요했다.

 


수정화면 로직
> 수정 버튼 클릭
> 수정된 내용 확인
> 내용이 없으면 return 있으면 formData에 append

formData에 데이터를 넣기 전에 수정된 내용이 있는지부터 확인해야했다.

그래서 checkData()를 선언해서 그 안에서 조작하기로 했다.

 

> 수정 버튼 클릭 : @click="uptTask()"로 uptTask() 호출

<!-- 수정버튼 -->
<button @click="uptTask()">수정</button>
uptTask() {
    if(confirm('수정하시겠습니까?')){
        this.$parent.$refs.taskRegist.mode = 'update'; // taskRegist의 mode 변경
        this.dataSet(); // dataSet() 호출
        this.hide(); // 이것 감추기
        this.$parent.$refs.taskRegist.show(); // taskRegist 보이기
    }
},
dataSet(){
    var self = this;
    var taskRegist = this.$parent.$refs.taskRegist;

    taskRegist.oldTask = self.list; // 비교를 위해 list 전체 넣기
    
    // 수정화면은 등록화면과 같은 js,jsp 파일을 쓰기때문에 하나하나 세팅
    taskRegist.nttNo = self.list.nttNo;
    taskRegist.nttSubj = self.list.nttSubj;
    taskRegist.nttCtn = self.list.nttCtn;
    if(self.list.status == '신규'){
    	// 등록할때는 '신규'가 default, 수정할때는 '진행중'이 default
        taskRegist.status = '진행중';
    } else {
        taskRegist.status = self.list.status;
    }
    taskRegist.taskTrack = self.list.taskTrack;
    taskRegist.taskPrior = self.list.taskPrior;
    taskRegist.taskWorkerId = self.list.taskWorkerId;
    taskRegist.taskDoneRatio = self.list.taskDoneRatio;
    taskRegist.begDt = self.list.begDt;
    taskRegist.endDt = self.list.endDt;
},
show() {
    $(this.$el).show();
},
hide() {
    $(this.$el).hide();
}

 

> 수정된 내용 확인(등록/수정 로직)

regist() { // 등록 or 저장
    var self = this;
    var formData = new FormData();

    if(self.status != '신규' && self.taskDoneRatio == 0){
        alert('진행중인 업무는 진행도가 0일 수 없습니다. 확인해주세요.');
        return;
    }
    
    if(self.mode == 'update'){
        var histCtn = self.checkData(); // 하단에 있음
        if(histCtn == ""){
            // histCtn의 초기값이 ""이므로 해당 값이면 수정된 내용이 없다는 말
            alert('수정된 내용이 없습니다.');
            return;
        } else if (histCtn != ""){
            // ""가 아니면 수정된 내용이 있다는 말
            formData.append('histCtn', histCtn)
        }
    }

    if(self.validate().pass == false)
        return;

    var txt = (self.mode == 'regist' ? '등록' : '저장');

    if(confirm(txt + '하시겠습니까?')){
        formData.append('nttSubj', self.nttSubj);
        formData.append('nttCtn', self.nttCtn);
        formData.append('parntNttNo', self.parntNttNo); // 초기값이 0이므로 굳이 mode에 따라 나눌 필요 x
        formData.append('parntRegusrId', self.parntRegusrId); // 초기값이 ''이므로 굳이 mode에 따라 나눌 필요 x
        formData.append('status', self.status); // mode와 관련없이 status값 전송
        formData.append('taskTrack', self.taskTrack);
        formData.append('taskPrior', self.taskPrior);
        formData.append('taskWorkerId', self.taskWorkerId);
        formData.append('taskDoneRatio', self.taskDoneRatio);
        formData.append('begDt', self.begDt);
        formData.append('endDt', self.endDt);
        
        // 등록
        if(self.mode == 'regist'){ // mode == regist

            app.model.task.taskRegist(formData).then(function(){
                alert('등록되었습니다.');
                self.init();
                self.hide();
                self.$parent.$refs.taskList.init();
                self.$parent.$refs.taskList.show();
            });

        } else { // mode == update(수정)
            formData.append('nttNo', self.nttNo);

            app.model.task.taskUpdate(formData).then(function(){
                alert('수정되었습니다.');
                self.init();
                self.hide();
                self.$parent.$refs.taskList.init();
                self.$parent.$refs.taskList.show();
            });
        }
    }
},
checkData() { // 수정내용 확인
    var self = this;
    var histCtn = "";
    
    if(self.oldTask.nttSubj != self.nttSubj){
        histCtn += "업무명 변경: " + self.oldTask.nttSubj + " >> " + self.nttSubj +"\r\n";
    }
    if(self.oldTask.taskTrack != self.taskTrack){
        histCtn += "업무유형 변경: " + self.oldTask.taskTrack + " >> " + self.taskTrack +"\r\n";
    }
    if(self.oldTask.status != self.status){
        histCtn += "업무상태 변경: " + self.oldTask.status + " >> " + self.status +"\r\n";
    }
    if(self.oldTask.taskPrior != self.taskPrior){
        histCtn += "업무우선순위 변경: " + self.oldTask.taskPrior + " >> " + self.taskPrior +"\r\n";
    }
    if(self.oldTask.taskWorkerId != self.taskWorkerId){
        histCtn += "업무담당자 변경: " + self.oldTask.taskWorkerId + " >> " + self.taskWorkerId +"\r\n";
    }
    if(self.oldTask.taskDoneRatio != self.taskDoneRatio){
        histCtn += "업무진척도 변경: " + self.oldTask.taskDoneRatio + " >> " + self.taskDoneRatio +"\r\n";
    }
    if(self.oldTask.begDt != self.begDt){
        histCtn += "업무시작일 변경: " + self.oldTask.begDt + " >> " + self.begDt +"\r\n";
    }
    if(self.oldTask.endDt != self.endDt){
        histCtn += "업무종료일 변경: " + self.oldTask.endDt + " >> " + self.endDt +"\r\n";
    }
    if(self.oldTask.nttCtn != self.nttCtn){
        histCtn += "업무내용 변경: " + self.oldTask.nttCtn + " >> " + self.nttCtn +"\r\n";
    }
    
    return histCtn;
}

 


컨트롤러, 서비스, SQL, DAO 다 작성하고 정상적으로 출력되는 것까지 확인했다.

그런데 한 가지 마음에 걸렸던 것이 수정된 내용의 맨 마지막에 존재할 수밖에 없는 "\r\n" 이었다.

전부 다 제거하는게 아닌 마지막 것만 지우는 방법은 뭐가 있을까.. 해서 찾아보니

.reaplace() 가 있었다.

 

return histCtn; 위에 histCtn.replace(/\r\n$/,'');를 적어주었더니 마지막 \r\n만 사라진 채로 데이터가 잘 들어가는 것을 확인했다.

.replace(/\r\n$/, '')
- / : 정규식의 시작과 끝
- \r\n : 제거하고자 하는 것(엔터)
- $ : 문자열의 마지막 >> 이것을 안 붙여주면 모든 \r\n이 '' 으로 바뀐다.

 


마치며

replace 함수는 알았지만 정규식은 잘 몰랐다.

이번 기회에 정규식도 더 알아봐야겠다.. (공부할게 또 늘었네)


 

 

 

 

 

End.

heisely's 괴발개발 개발일지

728x90
반응형

'Programming > JS' 카테고리의 다른 글

[JS: Vue] v-for & v-bind  (0) 2022.04.05
[JS: Vue] inline-template & refs  (0) 2022.03.21
[JS: Vue] Vue와 Spring 데이터 통신  (0) 2022.03.10
[JS: Vue] Toggle로 Show/Hide 기능 구현 연습  (0) 2022.03.07
[JS: Vue] props 연습  (0) 2022.03.07
728x90
반응형

JSP

- [CSS] white-space: pre (feat. vertical-align) -


KeyPoint
- "white-space:pre" : 줄바꿈 css
-
"vertical-align: middle" : 수직중앙정렬 css

 

 


들어가면서

토이프로젝트를 진행하다가 "이력"이라는 데이터를 넣을 일이 있었다.

"이력내용"이라는 컬럼의 데이터에는 \r\n이 포함된 내용이 들어갔는데, 이를 다시 화면에 가져와 출력할 때 엔터키가 먹지 않은 채로, 한 줄로 주루룩 나와서 당황스러웠다.

 

구글링을 해봐도 replace() 함수를 쓰라고 하는데 vue의 v-for를 통해 데이터를 출력하는 나로서는 데이터 개수가 가변적이라 하나하나 설정해주기가 어려웠다.(+textarea를 쓰는 것이 아니라 더 정보를 찾기 힘들었음)

 


white-space:pre

이미 DB에 엔터키가 포함된 데이터가 있음에도 불구하고 한 줄로 나오는 데이터를 어떻게 해야할까.. 생각하다가 작년 이맘때쯤 진행했던 학원 팀프로젝트 발표날에 같은 문제가 발생했고, 이를 발표 전에 빠르게 해결했던 기억이 문득 떠올랐다.

그럼 엄청나게 어려운 방법이 아니었을텐데.. 하고 더듬더듬 기억과 기록을 거슬러 올라가다 떠오른 style 적용..

팀 프로젝트 소스를 찾아 해당 부분을 찾으니 딱! 나왔다.

style="white-space: pre;" !!

 

신나서 바로 적용했더니 문제가 해결됐다.

 

▶ 적용 전

<tr class="txt_C" v-for="hist in historyList">
    <td>{{ hist.histCategory }}</td>
    <td>{{ hist.histCtn }}</td>
    <td>{{ hist.userNm }}</td>
    <td>{{ hist.histRegDt }}</td>
</tr>

 

▶ 적용 후

<tr class="txt_C" v-for="hist in historyList">
    <td>{{ hist.histCategory }}</td>
    <td style="white-space:pre; text-align:left;">{{ hist.histCtn }}</td>
    <td>{{ hist.userNm }}</td>
    <td>{{ hist.histRegDt }}</td>
</tr>

(( 약간 편-안 ))

 


vertical-align: middle

해결하고 나니 이제 저 위에 올라가있는 문구들이 거슬리기 시작했다.

"수직 중앙 정렬"로 검색한 결과 vertical-align이라는 것을 알게됐다.

바로 td에 적용했다.

<tr class="txt_C" v-for="hist in historyList">
    <td style="vertical-align: middle;">{{ hist.histCategory }}</td>
    <td style="white-space:pre; text-align:left;">{{ hist.histCtn }}</td>
    <td style="vertical-align: middle;">{{ hist.userNm }}</td>
    <td style="vertical-align: middle;">{{ hist.histRegDt }}</td>
</tr>

(( 편-----안 ))

 


마치며

(전)우리 조 조장의 프사가 떠오르는 날이었다..

CSS IS AWESOME..


 

 

 

 

 

End.

heisely's 괴발개발 개발일지

728x90
반응형

'Programming > JSP' 카테고리의 다른 글

[JSP: CSS] ::before & ::after (feat. +버튼)  (0) 2022.04.28
728x90
반응형

구현

- projectSn(프로젝트 일련번호) 세션 처리 -


KeyPoint
- HttpServletRequest request
- HttpSession session = request.getSession()
- session.setAttribute()

 


 

들어가기 전에

기존에 로그인화면을 구현하면서 사용자정보는 세션 처리를 완료했다.

구현 내용은 아래 게시물 참고.

 

▶ 로그인 화면 구현

 

[구현] 로그인 화면 구현

구현 - 로그인 화면(feat.세션) - KeyPoint  - Spring MVC 구조  - Session 처리  - return "redirect:xxx" PMS(Project Management System)을 구축하기 위해 로그인 화면과 로그인한 유저의 데이터가 필요했다..

heisely93.tistory.com

 

Project Management System을 구축하면서 중점에 뒀던 부분 하나가 "프로젝트 별"로 대시보드/업무 등을 구분하는 것이었다.

이를 위해서는 projectSn(프로젝트 일련번호) 역시 세션처리가 불가피했는데 로그인 정보를 처리하면서 해당 사용자가 참여중인 프로젝트의 번호를 넣으려고 하다가 정보는 1가지인데 프로젝트는 여러 개가 될 수 있어 로그인 정보에서는 제외시켰다. (실제로 넣었다가 에러남)

이에 따라 일단 로그인이 되면 프로젝트 목록 화면으로 이동시키고, 프로젝트를 눌렀을 때 어차피 대시보드로 이동하게끔 하려고 구상했으니, 프로젝트를 선택했을 때 세션에 저장하기로 했다.

 


projectSn 세션 처리

▶ 로직

프로젝트 목록 화면에서 프로젝트 명을 클릭

> 프로젝트 정보에서 projectSn을 JSON 데이터로 변환하여 axios.post로 컨트롤러단에 전송

> 컨트롤러단에서 projectSn을 받아 session 설정

> 세션 처리 후 js에서 "$(location).attr("href","url")"를 이용해 대시보드 화면으로 이동

 

▶ 설명

1. 프로젝트명 클릭

프로젝트명을 클릭하면 @click="goDashboard(list)"로 projList.js의 goDashboard(list) 함수 호출

<!-- proj_list.jsp -->
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" import="java.util.*"%>
<project-list inline-template ref='projList'>
    <div>
        <div class="card-header">
            <h2 style="color:blue;">참여중인 프로젝트</h2>
        </div>
        <div class="card-body">
            <div v-for="list in list">
                <table class="table table-bordered table-hover">
                    <tr>
                        <th colspan="2" @click="goDashboard(list)">{{list.projectNm}}</th>
                    </tr>
                    <tr>
                        <td colspan="2">{{list.projectCtn}}</td>
                    </tr>
                    <tr>
                        <td>프로젝트 참여기간</td>
                        <td>{{list.projectBegDt}} <span>~</span> {{list.projectEndDt}}</td>
                    </tr>
                    <tr>
                        <td>PM : {{list.pmNm}} </td>
                        <td><span style="cursor:pointer;" @click="getMembers(list.projectSn)">참여인원 : {{list.personCnt}}명</span></td>
                    </tr>
                </table>
            </div>
        </div>
    </div>
</project-list>
// projList.js 중 goDashboard(list) 함수
goDashboard(list) {
    alert(list.projectNm+'의 대시보드로 이동합니다.');
    
    var data = {
        'projectSn' : list.projectSn
    }
    var jsonData = JSON.stringify(data);
    
    axios.post('/pmsProject/project/setProjectSn.do', jsonData, {
        headers : {
            'Content-Type' : 'application/json'
        }
    })
},

 

2. Controller

리턴 값이 필요없으므로 void 메서드로 선언

// 프로젝트 세션 설정
@RequestMapping(value = "/project/setProjectSn.do", method = RequestMethod.POST)
@ResponseBody
public void setProjectSn(@RequestBody ProjectVO project, HttpServletRequest request) {
    HttpSession session = request.getSession();
    // projectSn 세션 설정
    session.setAttribute("projectSn", project.getProjectSn());
}

 

3. projList.js

axios.post 마지막에 .then(function(){})로 axios.post가 끝난 후 처리할 내용을 코딩

여기서는 대시보드로 이동해야하므로 $(location).attr('href','url')을 이용하여 대시보드 화면으로 이동시켰다.

// projList.js 중 goDashboard(list) 함수
goDashboard(list) {
    alert(list.projectNm+'의 대시보드로 이동합니다.');
    
    var data = {
        'projectSn' : list.projectSn
    }
    var jsonData = JSON.stringify(data);
    
    axios.post('/pmsProject/project/setProjectSn.do', jsonData, {
        headers : {
            'Content-Type' : 'application/json'
        }
    }).then(function(){
        $(location).attr('href','/pmsProject/project/dashboard.do');
    });
},

 

4. Dashboard Controller

임의로 dashboard.jsp 화면을 하나 생성하고, 컨트롤러 내에서 화면을 리턴하는 메서드를 선언

package pms.controller;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import pms.service.DashboardService;
import pms.vo.UserVO;

@Controller
public class DashboardController {

    @Autowired(required = false)
    DashboardService service;

    @RequestMapping(value = "/project/dashboard.do", method = RequestMethod.GET)
    public String dashboard(HttpServletRequest request, HttpServletResponse response) {

        HttpSession session = request.getSession();

        // user객체가 null이면(== 로그인 정보가 없으면)
        if (session.getAttribute("user") == null) {
            // 로그인 화면으로 이동
            return "redirect:/ppm/login.do";
        } // projectSn 값이 null이면(== 프로젝트 선택을 하지 않은 상황이면)
        else if (session.getAttribute("projectSn") == null) {
            // 프로젝트 목록으로 이동
            return "redirect:/proejct/project.do";
        } // 전부 세션에 저장되어 있다면
        else {
            // 세션값 확인
            UserVO user = (UserVO) session.getAttribute("user");
            
            System.out.println("#####################");
            System.out.println("#####################");
            System.out.println("로그인정보: " + user.getUserId());
            System.out.println("프로젝트번호: " + session.getAttribute("projectSn"));
            System.out.println("#####################");
            System.out.println("#####################");
            
            // 대시보드로 이동
            return "/WEB-INF/pmsPrj/jsp/proj/dashboard/dashboard";
        }
    }
}

 


확인

honggildong 이라는 아이디로 로그인하고 projectSn = 7777인 것으로 이동한 후 콘솔을 확인했다.

정상적으로 넘어온 것을 확인.

 


 

 

 

 

 

End.

heisely's 괴발개발 개발일지

 

 

728x90
반응형

'Programming > 구현' 카테고리의 다른 글

[구현] 사용자 정보(feat. session)  (0) 2022.04.07
[구현] 로그인 화면 구현  (0) 2022.04.07
[구현] Project List  (0) 2022.03.21
[구현] ERD 설계  (0) 2022.02.04
[구현] 분석단계 - 준비  (0) 2022.01.24
728x90
반응형

Error

- maven project form-data 처리 -


KeyPoint
 - pom.xml dependency 추가
 - @RequestBody 삭제

 


 

 


415 error

토이 프로젝트를 진행하면서 vue를 사용하고 있다.

게시물 등록의 경우, 파일이 포함되어있지 않으면 form-data보다는 json형식으로 넘기는 것이 나아서 지금까지 구축된 화면들은 전부 headers : { 'Content-Type' : 'application/json' } 으로 데이터를 보냈다.

 

그런데 같이 토이프로젝트를 진행하는 친구의 화면에는 파일 첨부기능이 들어갈 예정이라 formData로 전송해야 하는데, json 형식처럼 진행하려다보니 에러가 발생했다.

 

https://heisely93.tistory.com/26?category=1036800 에서 이미 발생했던 에러이다. 이때는 그냥 json형식으로 전송하는 걸로 바꿨었는데, 이제는 정말로 필요해서 해결법을 찾아야 했다..

 

 

[Error] 415 error

Error - 415 Error & HttpMediaTypeNotSupportedException - 415 Error axios.min.js:2 Uncaught (in promise) Error: Request failed with status code 415 org.springframework.web.HttpMediaTypeNotSupportedEx..

heisely93.tistory.com

 

해결 방법

▶ pom.xml에 dependency 추가하기

<dependency>
    <groupId>org.webjars.npm</groupId>
    <artifactId>form-data</artifactId>
    <version>4.0.0</version>
</dependency>

▶ Controller에서 @RequestBody 제거

Json형식으로 데이터를 받을 때에는 "@RequestBody VO명 변수명" 의 형식으로 받아야 했지만, FormData의 경우 오히려 @RequestBody가 에러를 유발한다. 따라서 해당 어노테이션을 삭제했다.

 


이렇게 작업을 했더니 백단으로 넘어가지 않던 문제가 해결됐다.

이 외에 쿼리 문제도 있어서 수정후에 정상적으로 게시물이 등록되는 것을 확인할 수 있었다.


 

 

 

 

 

End.

heisely's 괴발개발 개발일지

728x90
반응형
728x90
반응형

구현

- 사용자 정보(feat.session) -


KeyPoint
 - request.getSession()
 - session.getAttribute("xxx")

 


기존에 테스트용으로 만들었던 사용자 정보 화면은 userSn을 임시로 부여해서 JSON데이터로 전송 및 UserVO에 담아 DB에서 가져오는 방법이었다.

이제 Login 화면이 구현이 되면서 session에 정보를 담아줄 수 있으니 위 방식을 session 방식으로 수정했다.

 

Back단

▶ UsersDAO.java (interface, 메서드만 정의)

package pms.dao;

import java.util.List;

import org.springframework.stereotype.Repository;

import pms.vo.UserVO;

@Repository
public interface UsersDAO {

    // 사용자 정보
    public List<UserVO> userInfo(int userSn);

    // 정보 수정
    public Object uptUserData(UserVO user);
	
}

 

▶ Users_SQL_oracle.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="pms.dao.UsersDAO">

    <resultMap type="user" id="userInfo"/>
    <select id="userInfo" parameterType="int" resultMap="userInfo">
        SELECT
            u.USER_SN as userSn,
            u.TEAM_SN as teamSn,
            t.TEAM_NM as teamNm,
            u.GRADE_SN as gradeSn,
            g.GRADE_KOR as gradeKor,
            g.GRADE_ENG as gradeEng,
            u.USER_ID as userId,
            u.PASSWORD,
            u.USER_NM as userNM,
            u.EMAIL,
            to_char(u.ENTER_DT, 'yyyy-mm-dd') as enterDT
        FROM PMS."USER" u, team t, GRADE g
        WHERE 1=1
        AND u.TEAM_SN = t.TEAM_SN 
        AND u.GRADE_SN =g.GRADE_SN 
        AND u.USER_SN = #{userSn}
    </select>

    <update id="uptUserData" parameterType="user">
    UPDATE PMS."USER"
    SET
        PASSWORD = #{password},
        EMAIL = #{email}
    WHERE 1=1
    AND USER_SN = #{userSn}
    </update>
</mapper>
ENTER_DT의 경우 Type이 DATE이므로, 가져올 때에는 to_char()함수로 가져와 String으로 받는다.

 

▶ UsersService.java

package pms.service;


import java.util.HashMap;
import java.util.List;
import java.util.Map;

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

import pms.dao.UsersDAO;
import pms.vo.UserVO;

@Service
public class UsersService {

@Autowired(required = false)
private UsersDAO dao;

    public Object userInfo(int userSn){

        // 1. 리스트 불러오기
        List<UserVO> list = dao.userInfo(userSn);

        // 2. 불러온 리스트를 HashMap에 담아주기
        Map<String, Object> result = new HashMap<String, Object>();
        result.put("list", list);

        // 3. 담은 HashMap 리턴
        return result;
    }

    public Object uptUserData(UserVO user) {

        return dao.uptUserData(user);
    }
}

 

▶ UsersController.java (Session에 저장된 userSn을 이용!)

package pms.controller;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import pms.service.UsersService;
import pms.vo.UserVO;

@Controller
public class UsersController {

    @Autowired(required = false)
    private UsersService service;

    // http://localhost:7090/pmsProject/users/users.do 
    @RequestMapping(value = "/users/users.do", method = RequestMethod.GET)
    public String userInfo(HttpServletRequest request, HttpServletResponse response) {

        // session 값을 받아옴
        HttpSession session = request.getSession();

        // 세션의 userSn이 null 이면
        if(session.getAttribute("userSn") == null) {
            // 로그인 화면으로 이동
            return "redirect:/ppm/login.do";
        }
        // 세션의 userSn값이 존재한다면
        else {
            // 사용자 정보 화면으로 이동
            return "/WEB-INF/pmsPrj/jsp/users/user_info";
        }
    }

    // 기본 정보
    @RequestMapping(value = "/users/getUserData.do", method = RequestMethod.POST)
    @ResponseBody
    public Object getUserData(HttpServletRequest request) {

        // Session에서 받아와서 userSn에 담아줌
        HttpSession session = request.getSession();
        int userSn = (int) session.getAttribute("userSn");

        return service.userInfo(userSn);
    }

    // 정보 수정
    @RequestMapping(value = "/users/uptUserData.do", method = RequestMethod.POST)
    @ResponseBody
    public Object uptUserData(@RequestBody UserVO user) {
        return service.uptUserData(user);
    }

}

 

Front 단

User의 경우 $(event.target)을 사용해서 <input>태그의 readonly 값만 변경하는 방향으로 해서 컴포넌트가 따로 없다.

오직 instance뿐..

 

▶ userInfo.js (Instance)

/**
* users instance vue
**/

var app = window.app || {};
app.components = app.components || {};

// instance
$(document).ready(function(){ // $(event.target)을 위해 추가

    app.components.userInfo = new Vue({
        el : '.users',
        data : {
            mode : 'info', // info: 기본정보, uptInfo: 수정모드
            userNm : '',
            list : [],
            confirmPw : '', // 비밀번호 확인용
        },
        mounted(){
            this.init();
        },
        methods :{
        init : function(){ // 초기화
            this.mode = 'info';
            this.userNm = '';
            this.list = [];
            this.confirmPw = '';
            this.getlist();
        },
        getlist() { // 사용자정보 불러오기
            var self = this;
			
            // 필요한 데이터: userSn >> session처리 >> 따로 보낼 데이터는 없음
            axios.post('/pmsProject/users/getUserData.do').then(function(result){
                self.userNm = result.data.list[0].userNm;
                self.list = result.data.list;
            });
        },
        changeToUpt() { // 수정화면으로 전환
            this.mode = 'uptInfo';
            this.confirmPw = '';
            // 이 버튼의 요소(event.target)의 parent요소의 parent요소에서 input요소를 찾아 readonly 제거
            $(event.target.parentNode.parentNode.parentNode).find('input').removeAttr("readonly");
        },
        changeToInfo() { // 기본화면으로 전환
            this.mode = 'info';
            // 이 버튼의 요소(event.target)의 parent요소의 parent요소의 parent요소에서 
            // input요소를 찾아 readonly 부여
            $(event.target.parentNode.parentNode.parentNode).find('input').attr("readonly", "readonly");
        },
        updateInfo(list) { // 정보 수정 후 DB 저장
            var self = this;

            if(list.password != self.confirmPw){ // 유효성체크
                alert('입력한 비밀번호를 확인하세요.');
                return;
            }

            if(confirm('저장하시겠습니까?')){
                // 전송할 데이터를 json형식으로 만들기
                var data = {
                    "password" : self.confirmPw,
                    "email" : list.email,
                    "userSn" : list.userSn
                }

                // json형식으로 만든 데이터를 JSON으로 변환
                var jsonData = JSON.stringify(data);

                // 제대로 변환되었는지 콘솔에서 확인
                console.log(data);					
                console.log(jsonData);					

                // model로 데이터 보내서 서버통신
                app.model.users.uptUserData(jsonData).then(function(){
                    alert('save complete');
                    self.getlist();
                });

                    self.changeToInfo();
                }
            }
        }
    });
});

>> mode에 따라 보여줄 요소를 가림! (confirmPw)

 

▶ users.js (model) >> 삭제 고민중

/**
* users model
*/
var app = window.app || {};
app.model = app.model || {};

(function(app){
    var users = app.model.users = {};

    // 초기화
    users.initialized = new Promise(function(resolve){
        resolve(users);
    });

    // 사용자 정보 수정
    users.uptUserData = function(data) {
        return axios.post('/pmsProject/users/uptUserData.do', data, {
            headers : {
            'Content-Type' : 'application/json'
            }
        });
    };
})(app);

▶ user_info.jsp (Content Body 부분만)

<section class="content">
 <div class="container-fluid">
  <div class="row">
   <div class="col-12">
    <div class="card">
     <div class="users">
      <div>
       <div class="card-header">
        <h3 class="card-title"><b>{{ userNm }}</b>님의 정보</h3>
       </div>
       <div class="card-body">
        <div v-if="list.length != 0" v-cloak>
         <div v-for="list in list">
          <table class="table table-bordered table-hover">
           <tr>
            <th>사용자일련번호</th>
            <td>{{list.userSn}}</td>
           </tr>
           <tr>
            <th>팀</th>
            <td>{{list.teamNm}}</td>
           </tr>
           <tr>
            <th>직책</th>
            <td>{{list.gradeKor}}({{list.gradeEng}})</td>
           </tr>
           <tr>
            <th>ID</th>
            <td>{{list.userId}}</td>
           </tr>
           <tr>
            <th>비밀번호</th>
            <td><input type="password" class="userInfo" v-model="list.password" readonly/></td>
           </tr>
           <tr v-if="mode == 'uptInfo'">
            <th>비밀번호 확인</th>
            <td><input type="password" v-model="confirmPw"/></td>
           </tr>
           <tr>
            <th>이름</th>
            <td>{{list.userNm}}</td>
           </tr>
           <tr>
            <th>이메일</th>
            <td><input type="text" class="userInfo" v-model="list.email" readonly/></td>
           </tr>
           <tr>
            <th>가입일자</th>
            <td>{{list.enterDt}}</td>
           </tr>
          </table>
          <div style="float: right;">
           <i class="fas-fa-pen"></i>
           <button id="uptUserInfo" style="cursor:pointer;" @click="changeToUpt()" v-if="mode=='info'">수정</button>
           <button id="uptUserInfo" style="cursor:pointer;" @click="updateInfo(list)" v-if="mode=='uptInfo'">저장</button>
           <button id="uptUserInfo" style="cursor:pointer;" @click="changeToInfo()" v-if="mode=='uptInfo'">취소</button>
          </div>
         </div>
        </div>
       </div>
      </div>
     </div>
    </div>
   </div>
  </div>
 </div>
</section>

 

이 방식을 응용하여 다른 화면에도 적용


 

 

 

 

 

End.

heisely's 괴발개발 개발일지

728x90
반응형

'Programming > 구현' 카테고리의 다른 글

[구현] projectSn 세션처리  (0) 2022.04.19
[구현] 로그인 화면 구현  (0) 2022.04.07
[구현] Project List  (0) 2022.03.21
[구현] ERD 설계  (0) 2022.02.04
[구현] 분석단계 - 준비  (0) 2022.01.24
728x90
반응형

구현

- 로그인 화면(feat.세션) -

 


 

KeyPoint
 - Spring MVC 구조
 - Session 처리
 - return "redirect:xxx"

PMS(Project Management System)을 구축하기 위해 로그인 화면과 로그인한 유저의 데이터가 필요했다.

유저의 데이터를 통해 참여중인 프로젝트의 개요, 대시보드, 업무, 리스크, 캘린더, 이력, 업무결재, 프로젝트 설정 등을 출력하려고 한다.

 


1. USER Table 생성

ERD 설계를 기반으로, Oracle DB 기반에서 USER Table을 생성했다.

ERD가 조금 수정되었지만 기본적인 틀은 아래 글 참고(https://heisely93.tistory.com/5?category=1036800)

 

[PMS] ERD 설계

1. 하나의 팀에 여러 명의 사용자 > 팀1 : 사용자多 1-1. 한 명의 사람이 한 팀만 가질 수 있어서 헷갈릴 수 있으나, 사용자 일련번호가 pk이므로 각각의 사용자별로 팀을 설정해 주면 됨 1-2.

heisely93.tistory.com

 

USER Table을 생성할 때 참고할 점이 두 가지 있다.

  • user 이름으로 테이블을 생성할 때엔 oracle 내의 user와 충돌이 일어날 수 있음 >> 쌍따옴표("")로 감싸서 생성
  • 직책(Grade)테이블과 팀(Team)테이블하고 관계가 맺어져 있음 >> PK 및 FK 설정 필요

이 점들을 참고하여 Create 문을 작성했다.

CREATE TABLE "USER"(
  user_sn NUMBER NOT NULL, -- USER Table의 PK
  team_sn NUMBER NOT NULL, -- TEAM Table의 PK, 여기서는 FK
  grade_sn NUMBER NOT NULL, -- GRADE Table의 PK, 여기서는 FK
  user_id varchar(10) NOT NULL, -- id
  password varchar(20) NULL, -- password
  user_nm varchar(10) NULL, -- name
  email varchar(100) NULL, -- email
  CONSTRAINT pk_user PRIMARY KEY (user_sn), -- PK 설정
  CONSTRAINT fk_team_to_user FOREIGN KEY (team_sn) REFERENCES team (team_sn), -- FK 설정
  CONSTRAINT fk_grade_to_user FOREIGN KEY (grade_sn) REFERENCES grade (grade_sn) -- FK 설정
);

 

2. VO 생성

일단 공통적으로 사용하는 컬럼들을 담은 VO를 생성하고, 다른 VO들은 공통VO를 상속받는 형식으로 했다.

// 공통 사용 VO
public class PmsCommonVO {

    private int projectSn = 0; // 프로젝트 일련번호
    private String projectNm = ""; // 프로젝트 이름
    private int teamSn = 0; // 팀 일련번호
    private String teamNm = ""; // 팀 이름
    private int userSn = 0; // 사용자 일련번호
    private String userId = ""; // 사용자 ID
    private String userNm = ""; // 사용자 이름
    private int gradeSn = 0; // 직책 일련번호
    private String gradeKor = ""; // 직책명 한글
    private String gradeEng = ""; // 직책명 영어
    private String frstRegusrId = ""; // 최초등록자ID
    private String frstRegDt = ""; // 최초등록일자
    private String lastUpdusrId = ""; // 최종수정자ID
    private String lastUpdDt = ""; // 최종수정일자
    private String authority = ""; // 권한

    // 검색용
    private String srhKeywordType; // 검색조건
    private String srhKeyword; // 검색내용
    private int totCount; // 검색 개수

    // 이하 Getter / Setter 생략

}
// User VO
public class UserVO extends PmsCommonVO {

    private String password; // 비밀번호
    private String userNm; // 사용자 이름
    private String email; // 이메일
    private String enterDt; // 가입일자

    // 이하 Getter/Setter 생략
}

 

3. Back

▶ DAO(Interface)

package pms.dao;

import java.util.List;

import org.springframework.stereotype.Repository;

import pms.vo.UserVO;

@Repository
public interface LoginDAO {

	// 로그인 정보
	public List<UserVO> loginInfo(UserVO user);
	
}

▶ Mapper(SQL)

<?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="pms.dao.LoginDAO">
    <resultMap type="user" id="loginInfo"/>
    <select id="loginInfo" parameterType="user" resultMap="loginInfo">
        SELECT 
            p.PROJECT_SN AS projectSn,
            u.USER_SN AS userSn,
            u.TEAM_SN AS teamSn,
            u.GRADE_SN AS gradeSn,
            u.USER_ID AS userId,
            u.password,
            u.USER_NM AS userNm,
            u.EMAIL,
            to_char(u.ENTER_DT, 'yyyy-mm-dd') AS enterDt
        FROM PROJECT p, "USER" u
        WHERE 1=1
        AND p.TEAM_SN = u.TEAM_SN
        AND u.USER_ID = #{userId}
        AND u.PASSWORD = #{password}
    </select>
</mapper>

▶ Service (Session 처리)

package pms.service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

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

import pms.dao.LoginDAO;
import pms.vo.UserVO;

@Service
public class LoginService {

    @Autowired(required = false)
    private LoginDAO dao;

    // 로그인
    public Object loginCheck(UserVO user, HttpServletRequest request) {

        // 세션 설정
        HttpSession session = request.getSession();

        // 사용자 정보 불러오기
        UserVO loginData = dao.loginInfo(user);

        // 사용자 정보가 존재한다면
        if(loginData != null) { // 세션 변수 저장
            session.setAttribute("user", loginData);
        }

        // Map에 담아서 보내기(View단에서 로그인 여부에 따라 화면 전환)
        Map<String, Object> result = new HashMap<String, Object>();
        result.put("loginData", loginData);

        return result;
    }

}
다른 화면에서는 session.getAttribute를 이용할 예정이다.(추후 게시물 작성 예정)

 

▶ Controller

package pms.controller;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import pms.service.LoginService;
import pms.vo.UserVO;

@Controller
public class LoginController {

    @Autowired(required = false)
    private LoginService service;

    // http://localhost:8077/pmsProject/ppm/login.do
    @RequestMapping(value = "/ppm/login.do", method = RequestMethod.GET)
    public String loginInfo(HttpServletRequest request, HttpServletResponse response) {
    	return "/WEB-INF/pmsPrj/jsp/ppm/login_main";
    }

    // 로그인
    @RequestMapping(value = "/ppm/loginCheck.do", method = RequestMethod.POST)
    @ResponseBody
    public Object loginCheck(@RequestBody UserVO user, HttpServletRequest request) {
    	// UserVO에 json데이터로 받은 userId와 password를 담고, request값을 그대로 Service에 전달
    	return service.loginCheck(user, request);
    }

    // 로그아웃
    @RequestMapping(value = "/ppm/logout.do")
    public Object logout(HttpServletRequest request) {
        HttpSession session = request.getSession();
        session.invalidate();
        request.getSession(true);

    	return "redirect:/ppm/login.do";
    }
}

 

4. Front

loginMain.js (Instance)

/**
 * login instance
 */
 
var app = window.app || {};
app.components = app.components || {};
 
$(document).ready(function(){

    app.components.loginMain = new Vue({
        el : '.loginMain',
        data : {

        },
        mounted() {
        	this.init();
        },
        methods : {
            init() {
                this.$refs.login.init();
            }
        }
    });
});

▶ login.js (Component)

/**
* 로그인화면 Components
*/

var app = window.app || {};
app.components = app.components || {};

$(document).ready(function(){

    app.components.login = Vue.component('login', {
        props : [],
        data() {
            return {
                userId : '',
                password : ''
            }
        },
        methods : {
            init() {
                this.userId = '';
                this.password = '';
            },
            loginCheck() { // 로그인하기
                var self = this;
                var data = {
                    'userId' : self.userId,
                    'password' : self.password
                }
                var jsonData = JSON.stringify(data);

                app.model.login.loginCheck(jsonData).then(function(result){
                    console.log(result.data);
                    if(result.data.loginData != null){
                        // 프로젝트 목록으로 이동
                        app.model.data.user = result.data.loginData;
                        console.log(app.model.data.user);
                        console.log(self.data.user);
                        alert("로그인 성공\n프로젝트 목록으로 이동합니다.");
                        self.hide();
                        $(location).attr("href", "/pmsProject/project/project.do");
                    } else {
                    alert('로그인 정보가 올바르지 않습니다.');
                        self.init();
                    }
                });
            }
            show() {
            	$(this.$el).show();
            },
            hide() {
            	$(this.$el).hide();
            }
        }
    });
});

▶ login.js (Model)

/**
*  login Model
*/

var app = window.app || {};
app.model = app.model || {};

(function(app){
    var login = app.model.login = {};

    login.initialized = new Promise(function(resolve){
    	resolve(login);
    });


    // 로그인정보
    login.loginCheck = function(data) {
        return axios.post('/pmsProject/ppm/loginCheck.do', data, {
            headers : {
            'Content-Type' : 'application/json'
            }
        });
    };

})(app);

▶ login.jsp (inline-template)

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" import="java.util.*"%>
<login inline-template ref='login'>
    <div>
        <div class="card-header">
            <h2 class="txt_C" style="color:blue;">로그인화면</h2>
        </div>
        <div class="card-body">
            <table class="table table-bordered table-hover">
                <tr>
                	<th>아이디</th>
                	<td><input type="text" v-model="userId"/></td>
                </tr>
                <tr>
                	<th>비밀번호</th>
                	<td><input type="password" v-model="password" @keyup.enter="loginCheck()"/></td>
                </tr>
            </table>
            <button @click="loginCheck()">로그인</button>
        </div>
    </div>
</login>

 


이제 다른 화면에서 해당 session값을 이용하여 데이터를 가져오는 것을 처리해보자.

 


 

 

 

 

 

End.

heisely's 괴발개발 개발일지

728x90
반응형

'Programming > 구현' 카테고리의 다른 글

[구현] projectSn 세션처리  (0) 2022.04.19
[구현] 사용자 정보(feat. session)  (0) 2022.04.07
[구현] Project List  (0) 2022.03.21
[구현] ERD 설계  (0) 2022.02.04
[구현] 분석단계 - 준비  (0) 2022.01.24

+ Recent posts