갑작스러운 the password has expired error 로 당황할때가 있습니다..

 

 

비밀번호는 SYSTEM 계정으로 들어가서 다음 명령으로 변경하면 됩니다.

 

ALTER USER user_id IDENTIFIED BY new_password;

 

만약 집에서 개인정으로 테스트 해보는 환경이라면 매번 비밀번호를 변경하는게 불편할 수도 있겠습니다. 다음 명령으로 만료가 되지 않도록 설정할 수 있습니다.

 

ALTER PROFILE DEFAULT LIMIT PASSWORD_LIFE_TIME UNLIMITED;

 

추가로 또 하나 이야기 하자면, 로그인 시 비밀번호가 10번 틀리면 계정이 잠기는 것이 기본 프로필 설정입니다. 잠긴 계정을 풀려면 다음 명령을 사용합니다.

 

ALTER USER user_id ACCOUNT UNLOCK;

 

시스템 계정까지 비밀번호가 비밀번호가 만료되었다면 시스템의 로컬에서 sqlplus 를 사용해서  인증없이 로그인한 후 비밀번호를 변경하면 되겠습니다. 다음처럼 합니다.



출처: https://offbyone.tistory.com/118 [쉬고 싶은 개발자]

'프로그래밍언어 > Oracle' 카테고리의 다른 글

Mariadb 백업 및 복구  (0) 2020.02.26
오라클 명령어  (0) 2018.10.15
ORA-01034: ORACLE not available 에러  (0) 2018.07.31

 

Mongodb replicaset 으로 구성하여 사용하던 도중에 .. master 이 올라가지 않는 문제가 발생했다.

 

시스템이 비정상 셧다운된이후였는데. 올라가는 로그를 보니 

 

쉽게 해결되긴 어려워 보였다..

 

slave 는 정상 구동중인 상태였으므로.

 

그냥 master 을 삭제하고 다시 구성하면 되지 않을까싶어 해보았다.

 

 

mongo --port 26026 -u "id" -p "Password" --authenticationDatabase "admin"

salve 권한이 있는 포트로 접속한후 

rs.remove("localhost:26016")

과감히 삭제이후 다시새로운 곳에 다음과 같이 폴더를 생성한후

mkdir /var/lib/mongo/master
mkdir /var/lib/mongo/master/log

 conf  파일을 생성

# mongod.conf

# Where and how to store data.
storage:
  dbPath: /var/lib/mongodb/master
  journal:
    enabled: true

# where to write logging data.
systemLog:
  destination: file
  logAppend: true
  path: /var/lib/mongodb/master/log/mongod.log

# network interfaces
net:
  port: 26016
  bindIp: 127.0.0.1

processManagement:
  timeZoneInfo:  /usr/share/zoneinfo
  fork: true 

replication:
  replSetName: "replica"

 

 

 

이후 mongodb 에 접속하여 새로운 master 다시 추가.

rs.add( { _id:0,host:"127.0.0.1:26016",priority:2} )

 

이렇게하면 모두 완료된다..

 

 

replicaset 구성방법은 이전글을 참고하시면 됩니다.

 

https://ospetabyte.tistory.com/571?category=758411

 

MongoDB 설치 MongoDB replicaset 설정

우분투 18.04 기준으로 되어있습니다.  1. MongoDB 설치 wget -qO - https://www.mongodb.org/static/pgp/server-4.2.asc | sudo apt-key add - sudo apt-get install gnupg wget -qO - https://www.mongodb.org/..

ospetabyte.tistory.com

 

 

pip install virtualenv

virtualenv python 
# python 이라는 경로로 가상환경 설치

source bin/activate

실행

 

충격적인 자바스크립트 문법을 보았다...

 

        if(x !==3){
            console.log(y);
            var y = 5;
            if(y === 5){
                var x =3;
            }
            console.log(y);
        }
        if(x ===3){
            console.log(y);
        }

이문법을 보고 console.log(y) 에서 오류가 발생할꺼라고 생각했지만. 이문법은 아래와 같이 해석된다.

 

        var x;
        var y;
        if(x !==3){
            console.log(y);
            var y = 5;
            if(y === 5){
                var x =3;
            }
            console.log(y);
        }
        if(x ===3){
            console.log(y);
        }

애초당시 처음 선언했던것처럼 코드를 짜면 안되지만.. 호이스트를 확인하기 위해서.. 보았다..

 

        f();
        function f(){
            console.log(f);
        }

함수역시..

 

         function f(){
            console.log(f);
        }
        f();

 

https://git-scm.com/download/win

 

Git - Downloading Package

Downloading Git Now What? Now that you have downloaded Git, it's time to start using it.

git-scm.com

윈도우 64비트 사용자라면 해당 파란 체크 부분을 다운로드 설치 한다.

설치할때 이렇다할것은 없다 기본 셋팅으로 다음~을 눌러 진행하면 된다.

 

설치가 완료되면.

 

 

Git Bash 를 실행한다.

 

설치가 정상적으로 되었다면

git --version

 

 

 

위와같이 확인할수있다.

 

간단한 bash 명령어는 리눅스와 동일하다

 

 

git init #깃 경로 지정

vi .gitignore #깃 커밋 제외대상 추가

vi README.md #깃 메인 설명



환경설정 

git config --global user.name "Peta"
git config --global user.email "0petabyte@gmail.com"

확인은 git config --list

git add 폴더이름 or 파일명 또는 git add . (모든 파일 추가)

git commit -m "message 를 이곳에 적는다"

git remote  (기존에 설정이 안되었다면 아무것도 안나온다.)

git remote add origin https://github.com/TEST/TEST

이제 repository 에 연결완료.

git push origin master  입력하면 push 완료.

삭제

git -rm -r 폴더 git -rm -r file.js

git commit -m 'delete'

git push origin master 

'프로그래밍언어 > Git' 카테고리의 다른 글

깃허브 프로젝트 이름 변경하여 임포트하기.  (0) 2020.02.27
Git bash 명령어  (0) 2019.06.27

깃허브에서 프로젝트 임포트하려다가 보면 똑같은 프로젝트 이름때문에 . 임포트가 되지않는다..

 

 

Some Projects cannot be imported because they already exist in the workspace.

간혹.. 이경우때문에 기존프로젝트 이름을 변경하던가..해서 받곤했는데 가끔보면 너무 불편해서.

 

가능한 방법을 찾아보았다. 아래처럼 하면 가능하다!

 

먼저 깃에서 프로젝트를 다운받는다.

 

 

그다음 압축을 풀어서 프로젝트 폴더 이름을 변경한다.

 

그이후에

 

 

 

해당 프로젝트 경로까지 선택하면 바뀐 이름으로 프로젝트를 임포트 할수있다..

 

생각보다 간단한데.. 검색해도!!

 

.project 파일 수정해야되서 귀찮더라.. 

 

다른 방법이 잘보이지 않는다!! 그래서 직접 이렇게 하면 될것같은데? 싶어서 해본 방법이다.

 

추가!


 

프로젝트 임포트후 에러가 뜬다면..

 

Java version 을 바꾸어주면된다.!

 

 

 

 

'프로그래밍언어 > Git' 카테고리의 다른 글

[Git] 깃 허브 Bash 설치 및 기본 셋팅.  (0) 2020.03.04
Git bash 명령어  (0) 2019.06.27

백업.

mysqldump -u root -p dbname > /root/mariadb/backup.sql

 

 

복구

mysql -u root -p  dbname < backup.sql 

'프로그래밍언어 > Oracle' 카테고리의 다른 글

오라클 비번 만료(the password has expired)  (0) 2020.11.04
오라클 명령어  (0) 2018.10.15
ORA-01034: ORACLE not available 에러  (0) 2018.07.31
자료형 종류 예제
수(Number) 정수

76,197,750,

-11,

-234

실수(고정소수점)

3.14,

-2.717,

45.78

실수(부동소수점)

1e4, 

2.5e34,

5.67e-9,

7.66E-3

문자열 문자열

"1234"

"true"

"apple-run"

"사랑"

"\"JSP\""

제어문자

\b (백 스페이스)

\f (폼 피드)

\n (개행)

\r (캐리지 반환)

\t (탭)

\" (따움표)

\/ (슬래시)

\\ (역슬래시)

배열

배열은 대괄호[ ] 로 나타냅니다

배열의 각 요소는 기본 자료형이거나 배열, 객체입니다.

각 요소들은 쉼표 , 로 구분합니다

"name" : ["홍길동","이순신","임꺽정"]

// 대괄호 안에 배열 요소를 콤마 , 로 구분해서 나열합니다.

객체

JSON 개게는 중괄호 {}로 둘러싸서 표현합니다.

쉼표 , 를 사용해 여러 프로퍼티를 포함 할 수 있습니다.

{

   "name" : "홍길동",

   "age" : 16,

   "weight" : 67

}

// 중괄호 안에 name/value 쌍을 콤마로 구분해서 나열합니다. 

popupTest.html

<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>

<script type="text/javascript">
window.onload = pageLoad;
function pageLoad(){
	notShowPop = getCookieValue();
	if(notShowPop != "true"){
		window.open("popUp.html","pop","width=400,height=500,history=no,resizable=no,status=no,scrollbars=yes,menubar=no");
		
	}
}

function getCookieValue(){
	var result="false";
	if(document.cookie != ""){
		cookie = document.cookie.split(";");
		for(var i=0; i<cookie.length;i++){
			element = cookie[i].split("=");
			value=element[0];
			value=value.replace(/^\s*/,'');
			if(value =="notShowPop"){
				result = element[1];
			}
		}
	}
	
	return result;
}

function deleteCookie(){
	document.cookie = "notShowPop=" + "false" + ";path=/; expires=-1";
}

</script>
</head>
<body>
	<form>
		<input type=button value="쿠기삭제" onClick="deleteCookie()">
	</form>
</body>
</html>

 

popUp.html

<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>

<script type="text/javascript">
	function setPopUpStart(obj){
		if(obj.checked == true){
			var expireDate = new Date();
			expireDate.setMonth(expireDate.getMonth() +1);
			document.cookie = "notShowPop="+"true" + ";path=/; expires="+expireDate.toGMTString();
			
			window.close();
		}
	}
</script>
</head>
<body>
	<form>
		<input type=checkbox onClick="setPopUpStart(this)">오늘 더이상 팝업창 띄우지 않기
	</form>
</body>
</html>

 

'프로그래밍언어 > JavaScript' 카테고리의 다른 글

ES6 자바스크립트 호이스트  (0) 2020.03.06
json 자료형  (0) 2020.02.26
자바스크립트 slice 요소 복사  (0) 2018.11.14
자바스크립트 splice 배열요소 삭제  (0) 2018.11.14

mongoDB 백업하기(dump)

mongodump -u user_name -p user_password --authenticationDatabase=admin --out /data/backup/ --db db_name --collection collection_name --gzip 

# 옵션 설명
-u : 계정명
-p : 계정의 비밀번호
--authenticationDatabase=admin : 인증
--host : 원격 시 IP 주소 및 포트 
--out : Dump 받을 폴더 경로
--db : Dump 받을 DB 선택 (미작성 시 DB 전체)
--collection : Dump 받을 collection(table) 선택  (미작성 시 Collection 전체)
--gzip : Dump 파일 확장자

 

mongoDB 복구하기(Restore)

mongorestore -u user_name -p user_password --host 192.168.0.100:8000 --authenticationDatabase=admin --gzip --db db_name --collection collection_name /data/backup/collection.bson.gz --drop

# 옵션 설명
-u : 계정명
-p : 계정의 비밀번호
--authenticationDatabase=admin : 인증
--host : 원격 시 IP 주소 및 포트
--db : Restore 할 DB 선택 
--collection : Restore 할 collection(table) 선택
--gzip : Restore 파일 확장자
--drop : 백업에 없는 collection 삭제



 

$currentDate 필드 값을 날짜 또는 시간 소인으로 현재 날짜로 설정합니다.
$inc 필드 값을 지정된 양만큼 증가시킵니다.
$min 지정된 값이 기존 필드 값보다 작은 경우에만 필드를 업데이트하십시오.
$max 지정된 값이 기존 필드 값보다 큰 경우에만 필드를 업데이트합니다.
$mul 필드 값에 지정된 양을 곱합니다.
$rename 필드 이름을 바꿉니다.
$set 문서에서 필드의 값을 설정합니다.
$setOnInsert 업데이트로 인해 문서가 삽입되는 경우 필드 값을 설정합니다. 기존 문서를 수정하는 업데이트 작업에는 영향을 미치지 않습니다.
$unset 문서에서 지정된 필드를 제거합니다.

 

우분투 18.04 기준으로 되어있습니다.

 

 1. MongoDB 설치

 

wget -qO - https://www.mongodb.org/static/pgp/server-4.2.asc | sudo apt-key add -

sudo apt-get install gnupg

wget -qO - https://www.mongodb.org/static/pgp/server-4.2.asc | sudo apt-key add -
echo "deb [ arch=amd64 ] https://repo.mongodb.org/apt/ubuntu bionic/mongodb-org/4.2 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-4.2.list

 

sudo apt-get update

 

sudo apt-get install -y mongodb-org=4.2.3 mongodb-org-server=4.2.3 mongodb-org-shell=4.2.3 mongodb-org-mongos=4.2.3 mongodb-org-tools=4.2.3

 

위와같이 설치할경우 리눅스에 설치된 디렉토리는

 

 

2 . 폴더 생성 및 conf 파일 생성 

 

실행파일 

/usr/bin/mongo 

 

설치경로

/var/lib/mongo

 

설치경로에 3가지의 폴더와 파일을 만들어야한다.

 

mkdir /var/lib/mongo/master
mkdir /var/lib/mongo/master/log

mkdir /var/lib/mongo/slave1
mkdir /var/lib/mongo/slave1/log

mkdir /var/lib/mongo/arbiter
mkdir /var/lib/mongo/arbiter/log

 

 

그다음 위의 경로에 아래의 conf 파일을 각각 생성해준다. 

 

 

 

master 파일.

# mongod.conf

# Where and how to store data.
storage:
  dbPath: /var/lib/mongodb/master
  journal:
    enabled: true

# where to write logging data.
systemLog:
  destination: file
  logAppend: true
  path: /var/lib/mongodb/master/log/mongod.log

# network interfaces
net:
  port: 26016
  bindIp: 127.0.0.1

processManagement:
  timeZoneInfo:  /usr/share/zoneinfo
  fork: true 

replication:
  replSetName: "replica"

 

slave 파일.

# mongod.conf

# Where and how to store data.
storage:
  dbPath: /var/lib/mongodb/slave1
  journal:
    enabled: true

# where to write logging data.
systemLog:
  destination: file
  logAppend: true
  path: /var/lib/mongodb/slave1/log/mongod.log

# network interfaces
net:
  port: 26026
  bindIp: 127.0.0.1

processManagement:
  timeZoneInfo: /usr/share/zoneinfo
  fork: true 

replication:
  replSetName: "replica"

 

arbiter

# mongod.conf

# Where and how to store data.
storage:
  dbPath: /var/lib/mongodb/arbiter
  journal:
    enabled: true

# where to write logging data.
systemLog:
  destination: file
  logAppend: true
  path: /var/lib/mongodb/arbiter/log/mongod.log

# network interfaces
net:
  port: 26036
  bindIp: 127.0.0.1

processManagement:
  timeZoneInfo: /usr/share/zoneinfo
  fork: true 

replication:
  replSetName: "replica"

 

 

3. 실행 및 종료

 

 

 

실행명령어

/usr/bin/mongod --config /var/lib/mongodb/master/master.conf 
/usr/bin//mongod --config /var/lib/mongodb/slave1/slave1.conf 
/usr/bin/mongod --config /var/lib/mongodb/arbiter/arbiter.conf 

 

종료명령어 (종료시에만 입력)

/usr/bin/mongod --shutdown --config /var/lib/mongodb/arbiter/arbiter.conf 
/usr/bin/mongod --shutdown --config /var/lib/mongodb/slave1/slave1.conf 
/usr/bin/mongod --shutdown --config /var/lib/mongodb/master/master.conf 

 

다음과같은 Shell 이 뜨게되면 아래와 같이 입력한다.

rsconf ={_id : "replica", members:[{_id:0,host:"127.0.0.1:26016",priority:2},{_id:1,host:"127.0.0.1:26026",priority:1},{_id:2,host:"127.0.0.1:26036",priority:1,arbiterOnly:true}]};

 

이렇게 하면 셋팅완료

 

 

아래부분은 보안부분이다.


#외부 접속을 허용하기위해선 bindIp : 0.0.0.0 로 설정해야 한다.

 

#계정생성 PRIMARY 로 접속하여

> use admin
> db.createUser({
    user: 'adminId',
    pwd: 'password',
    roles: ['root']
})

 

## 암호화 설정방법.

Linux에서 mongodb 키 파일을 작성하고 모드가 600그대로있는 모든 DB 서버에 복사하십시오 .

openssl rand -base64 741 > mongodb.key

chmod 600 mongodb.key

mongod.conf

security:
    authorization: enabled
    keyFile: /var/lib/mongodb/mongodb.key

 

 

<c:forEach items="${ test.numbers }" var="num">

	<c:forEach items="${ num.vec }" var="vec">

	<td>${ vec }</td>

	</c:forEach>

</c:forEach>

스프링 Controller에서 Model에 배열 데이터를 담아서 View로 전달한다면

View에서는 jstl forEach 구문을 이용해서 접근할 수 있다.

 

<c:forEach items="${ test.numbers }" var="num">

	<td>${ num }</td>



</c:forEach>

 

물론 이중구문을 이용해 배열안의 배열까지 접근이 가능하다.

 

 

forEach 구문을 사용안하고 배열 중 한 요소만을 출력하고자 한다면 다음과 같이 작성하면된다.

	<c:out value="${ test.num[1] }" />

num배열에서 2번째 요소가 출력된다.

 

배열 사이즈를 알고 싶을때는 다음과 같이 작성한다.

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

	<c:out value="${fn:length(test.num)}" />

Criteria.java

package com.peta.domain;

public class Criteria {
	private int page;
	private int perPageNum;
	private int groupnum;
	
	
	
	public int getGroupnum() {
		return groupnum;
	}

	public void setGroupnum(int groupnum) {
		this.groupnum = groupnum;
	}

	public Criteria() {
		this.page =1;
		this.perPageNum =10;
	}

	public int getPage() {
		return page;
	}

	public void setPage(int page) {
		
		if(page <= 0) {
			this.page = 1;
			return;
		}
		this.page = page;
	}

	public int getPerPageNum() {
		return this.perPageNum;
	}

	public void setPerPageNum(int perPageNum) {
		
		if(perPageNum <=0 || perPageNum >100) {
			this.perPageNum = 10;
		}
		this.perPageNum = perPageNum;
	}

	public int getPageStart() {
		return (this.page - 1) * perPageNum;
	}

	@Override
	public String toString() {
		return "Criteria [page=" + page + ", perPageNum=" + perPageNum + "]";
	}
	

	 
	
	
}

 

SearchCriteria.java

package com.peta.domain;

public class SearchCriteria extends Criteria{
	private String searchType;
	private String keyword;

	
	
	

	public String getSearchType() {
		return searchType;
	}
	public void setSearchType(String searchType) {
		this.searchType = searchType;
	}
	public String getKeyword() {
		return keyword;
	}
	public void setKeyword(String keyword) {
		this.keyword = keyword;
	}
	@Override
	public String toString() {
		return "SearchCriteria [searchType=" + searchType + ", keyword=" + keyword + "]";
	}


	
	
}

 

PageMaker.java

package com.peta.domain;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;

import org.springframework.web.util.UriComponents;
import org.springframework.web.util.UriComponentsBuilder;

public class PageMaker {
	private int totalCount;
	private int startPage;
	private int endPage;
	private boolean prev;
	private boolean next;
	
	
	//한화면에 보이는 페이지 갯수
	private int displayPageNum =10;
	
	private Criteria cri;

	public void setCri(Criteria cri) {
		this.cri =cri;
	}
	
	public void setTotalCount(int totalCount) {
		this.totalCount = totalCount;
		
		calcData();
	}
	
	private void calcData() {
		endPage = (int) (Math.ceil(cri.getPage() / (double) displayPageNum) * displayPageNum);
		
		startPage = (endPage-displayPageNum) + 1;
		
		int tempEndPage = (int) (Math.ceil(totalCount / (double) cri.getPerPageNum()));
		
		if (endPage > tempEndPage) {
			endPage = tempEndPage;
		}
		
		prev = startPage == 1? false:true;
		
		next = endPage * cri.getPerPageNum() >= totalCount ? false :true;
	}
	


	public int getStartPage() {
		return startPage;
	}

	public void setStartPage(int startPage) {
		this.startPage = startPage;
	}

	public int getEndPage() {
		return endPage;
	}

	public void setEndPage(int endPage) {
		this.endPage = endPage;
	}

	public boolean isPrev() {
		return prev;
	}

	public void setPrev(boolean prev) {
		this.prev = prev;
	}

	public boolean isNext() {
		return next;
	}

	public void setNext(boolean next) {
		this.next = next;
	}

	public int getDisplayPageNum() {
		return displayPageNum;
	}

	public void setDisplayPageNum(int displayPageNum) {
		this.displayPageNum = displayPageNum;
	}

	public int getTotalCount() {
		return totalCount;
	}

	public Criteria getCri() {
		return cri;
	}

	@Override
	public String toString() {
		return "PageMaker [totalCount=" + totalCount + ", startPage=" + startPage + ", endPage=" + endPage + ", prev="
				+ prev + ", next=" + next + ", displayPageNum=" + displayPageNum + ", cri=" + cri + "]";
	}
	
	public String makeQuery(int page) {
		UriComponents uriComponents =
				UriComponentsBuilder.newInstance()
				.queryParam("page", page)
				.queryParam("perPageNum", cri.getPerPageNum())
				.build();
		
		return uriComponents.toUriString();
	}
	
	public String makeSearch(int page) {
		UriComponents uriComponents =
				UriComponentsBuilder.newInstance()
				.queryParam("page", page)
				.queryParam("perPageNum", cri.getPerPageNum())
				.queryParam("groupnum", cri.getGroupnum())
				.queryParam("searchType", ((SearchCriteria) cri).getSearchType())
				.queryParam("keyword", encoding(((SearchCriteria) cri).getKeyword())).build();
		
		return uriComponents.toUriString();
	}
	
	private String encoding(String keyword) {
		if(keyword ==null || keyword.trim().length() ==0) {
			return "";
		}
		
		try {
			return URLEncoder.encode(keyword,"UTF-8");
		}catch(UnsupportedEncodingException e) {
		return "";
		}
	}
	
	
}

 


 

Mapper.xml

 

특이사항 : if 문의 입력을 and 로 시작시키기위해 favnum >0 을 미리 조건을 준다. CDATA 사용

 <select id="listCriteria" resultType="com.peta.domain.UrlVO">
<![CDATA[
 select favnum,url,memo,userid,groupnum,nowdate from fav_list where favnum > 0
 ]]>
 <if test="groupnum != 0">
 and groupnum = #{groupnum}
 </if>
  
 <if test="searchType != null">
 	<if test="searchType == 'u'.toString()">
 		and url like CONCAT('%', #{keyword}, '%')
 	</if>
 	<if test="searchType == 'm'.toString()">
 		and memo like CONCAT('%', #{keyword}, '%')
 	</if>
 	<if test="searchType == 'um'.toString()">
 		and (url like CONCAT('%', #{keyword}, '%') OR memo like CONCAT('%', #{keyword}, '%')) 
 	</if>
 </if>
 order by favnum desc 
 limit #{pageStart},#{perPageNum}
 </select>
 

 
 <select id="countPaging" resultType="int">
 <![CDATA[
 select count(favnum) from fav_list where favnum > 0 
 ]]>
 <if test="groupnum != 0">
 AND groupnum = #{groupnum}
 </if>
  <if test="searchType != null">
 	<if test="searchType == 'u'.toString()">
 		and url like CONCAT('%', #{keyword}, '%')
 	</if>
 	<if test="searchType == 'm'.toString()">
 		and memo like CONCAT('%', #{keyword}, '%')
 	</if>
 	<if test="searchType == 'um'.toString()">
 		and (url like CONCAT('%', #{keyword}, '%') OR memo like CONCAT('%', #{keyword}, '%')) 
 	</if>
 </if>
 </select>

DAO

public List<CodeVO> listCriteria(Criteria cri) throws Exception;
public int countPaging(Criteria cri) throws Exception;

 

DAOImpl

	@Override
	public List<CodeVO> listCriteria(Criteria cri) throws Exception{
		return session.selectList(namespace+".listCriteria",cri);
	}
	@Override
	public int countPaging(Criteria cri) throws Exception{
		return session.selectOne(namespace+".countPaging",cri);
	}

 

Service

public List<CodeVO> listCriteria(Criteria cri) throws Exception;
public int countPaging(Criteria cri) throws Exception;

ServiceImpl

	@Override
	public List<CodeVO> listCriteria(Criteria cri) throws Exception{
		return dao.listCriteria(cri);
	}
	@Override
	public int countPaging(Criteria cri) throws Exception{
		return dao.countPaging(cri);
	}

 

jsp page

	<div class="container">
		<ul class="pagination justify-content-center">
			<c:if test="${pageMaker.prev}">
				<li class="page-item"><a class="page-link" href="list${pageMaker.makeSearch(pageMaker.startPage -1)}">Previous</a></li>
			</c:if>
			
			<c:forEach begin="${pageMaker.startPage}" end="${pageMaker.endPage}" var="idx">
				<li class="page-item <c:out value="${pageMaker.cri.page == idx?'class = active':''}"/>" >
				<a class="page-link" href="list${pageMaker.makeSearch(idx)}">${idx}</a>
				</li>
			</c:forEach>
				<c:if test="${pageMaker.next && pageMaker.endPage > 0}">
					<li><a class="page-link" href="list${pageMaker.makeSearch(pageMaker.endPage +1)}">Next</a></li>
				</c:if>
		</ul>
	</div>

 

 

Controller

    @RequestMapping(value="/code", method= {RequestMethod.GET,RequestMethod.POST})
    public String codeGroupList(Model model,CodeVO vo,SearchCriteria cri) throws Exception {
    	logger.info("Code Group list start................");
    	String codeType = "code";
		int groupnum = vo.getGroupnum();
		
		model.addAttribute("nowgroupnum",groupnum);
    	model.addAttribute("codeGroup",service.codeGroupList());
    	model.addAttribute("codeType",codeType);
    	model.addAttribute("list",service.listCriteria(cri));
    	model.addAttribute("groupcount",service.groupCount(groupnum));
    	model.addAttribute("nowgroupname",service.groupName(groupnum));
		PageMaker pageMaker = new PageMaker();
		pageMaker.setCri(cri);
		model.addAttribute("cri",cri);
		pageMaker.setTotalCount(service.countPaging(cri));
		model.addAttribute("pageMaker",pageMaker);
        return "codeboard/codeList.page";
    }
    

 

Tiles Framework란?


Tiles는 웹페이지의 상단메뉴나 좌측메뉴, 공통 파일 include 등의 반복적인 부분을 한 곳에서 깔끔하게 관리할 수 있게 도와주는 템플릿 프레임워크 입니다.

 

https://tiles.apache.org/

위 URL은 Tiles Framework의 공식 사이트입니다.

Tutorial과 API문서가 상세하게 잘 나와있지만 영어라 그런지 보기가 쉽지 않습니다.

공식 사이트를 보고 따라하기 어려운 분만 아래 내용을 참고해주시면 되겠습니다.

 

 

Step 0. 최소 요구사항 확인


※ 현재 최종 버전인 3.08 버전 기준입니다.

※ Spring STS 플러그인의 Spring MVC Project 예제에 Tiles를 연동하는 방법을 기술 한 것입니다. 프로젝트 구성 별로 설정파일명이 다를 수 있습니다.

 

- JSTL 필요

* STS를 사용하고 있다면 기본적으로 탑재되어 있고, 그렇지 않다면 JSTL Dependency를 Maven에 추가해줘야 함.

* JSTL이 없으면 아래와 같은 에러 발생

HTTP Status 500 - Handler processing failed; nested exception is java.lang.NoClassDefFoundError: javax/servlet/jsp/jstl/core/Config

- JDK 1.7 이상

- Servlet 2.5 이상(2.4도 가능은 함)

- JSP 2.1 이상(2.0도 가능은 함)

- Spring 3.2 이상

* 현재 Spring 3.x의 최종 버전인 3.2.18과 4.x의 최종 버전인 4.3.18에서만 테스트 진행 하였습니다.

 

 

 

Step 1. Maven Dependency 추가


        <dependency>
            <groupId>org.apache.tiles</groupId>
            <artifactId>tiles-extras</artifactId>
            <version>3.0.8</version>
          </dependency>
        <dependency>
            <groupId>org.apache.tiles</groupId>
            <artifactId>tiles-servlet</artifactId>
            <version>3.0.8</version>
        </dependency>
        <dependency>
            <groupId>org.apache.tiles</groupId>
            <artifactId>tiles-jsp</artifactId>
            <version>3.0.8</version>
        </dependency>

 

Step 2. servlet-context.xml 파일에 Tiles 설정 추가


<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:beans="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
 
    <!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->
    
    <!-- Enables the Spring MVC @Controller programming model -->
    <annotation-driven />
 
    <!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
    <resources mapping="/resources/**" location="/resources/" />
 
    <!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory -->
    <beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <beans:property name="prefix" value="/WEB-INF/views/" />
        <beans:property name="suffix" value=".jsp" />
        <beans:property name="order" value="2" />
    </beans:bean>    
    
    <context:component-scan base-package="com.my.test" />
    
    <!-- Tiles -->
    <beans:bean id="tilesConfigurer" class="org.springframework.web.servlet.view.tiles3.TilesConfigurer">
        <beans:property name="definitions">
            <beans:list>
                <beans:value>/WEB-INF/tiles/tiles.xml</beans:value>
            </beans:list>
        </beans:property>
    </beans:bean>        
    <beans:bean id="tilesViewResolver" class="org.springframework.web.servlet.view.UrlBasedViewResolver">
        <beans:property name="viewClass" value="org.springframework.web.servlet.view.tiles3.TilesView" />
        <beans:property name="order" value="1" />
    </beans:bean>    
 
</beans:beans>

 

Step 3. tiles.xml 설정 파일 생성


<!DOCTYPE tiles-definitions PUBLIC
  "-//Apache Software Foundation//DTD Tiles Configuration 3.0//EN"
  "http://tiles.apache.org/dtds/tiles-config_3_0.dtd">
 
<tiles-definitions>
 
    <!-- 메뉴 표시 -->
    <definition name="base" template="/WEB-INF/tiles/template.jsp">
        <put-attribute name="left"   value="/WEB-INF/tiles/left.jsp" />
        <put-attribute name="header" value="/WEB-INF/tiles/header.jsp" />
        <put-attribute name="footer" value="/WEB-INF/tiles/footer.jsp" />
    </definition>
 
    <definition name="*.page" extends="base">
        <put-attribute name="body" value="/WEB-INF/views/{1}.jsp" />
    </definition>
 
     <definition name="*/*.page" extends="base">
         <put-attribute name="body" value="/WEB-INF/views/{1}/{2}.jsp" />
     </definition>
    
    <definition name="*/*/*.page" extends="base">
        <put-attribute name="body" value="/WEB-INF/views/{1}/{2}/{3}.jsp" />
    </definition>
    
      
    
</tiles-definitions>
 

 

Step 4. Template 파일 생성


/WEB-INF/tiles/template.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="tiles" uri="http://tiles.apache.org/tags-tiles" %>
<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <title>제목</title>
    <style>
        #header{            
            width:100%;
            height:50px;
            text-align: center;
            background-color: aqua;
        }
        #left{
            float:left;
             width:15%;
            background-color: gray;
        }
        #main{
            float:left;
             width:85%;
            background-color: lime;
        }
        #footer{
            width: 100%;
            height: 50px;            
            text-align: center;
            background-color: orange;
            clear:both;
        }
         #left, #main{ 
               min-height: 600px;
         } 
    </style>
    
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
</head>
<body>
    <div style="width:100%; height:100%;">
    <div id="header"><tiles:insertAttribute name="header" /></div>
    <div id="left"><tiles:insertAttribute name="left" /></div>
    <div id="main"><tiles:insertAttribute name="body" /></div>    
    <div id="footer"><tiles:insertAttribute name="footer" /></div>
    </div>
 
    <script type="text/javascript">
        $(function() {
 
        });    
    </script>    
</body>
</html>
 

 

 

/WEB-INF/tiles/header.jsp

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

/WEB-INF/tiles/left.jsp

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

/WEB-INF/tiles/footer.jsp

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

 

여기까지 하셨으면 Spring에 Tiles를 연동시키는 작업이 모두 끝난 것입니다.

이제 Tiles가 잘 연동되었는지 어떤 식으로 활용하면 되는지 살펴보도록 하겠습니다.

 

 

 

Test를 위해 test.jsp 파일을 아래와 같이 생성하고, 

HomeController.java 파일은 아래와 같이 수정합니다.

 

/WEB-INF/views/test.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<h1>테스트 Main</h1>

 

package com.my.test;
 
import java.text.DateFormat;
import java.util.Date;
import java.util.Locale;
 
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
 
/**
 * Handles requests for the application home page.
 */
@Controller
public class HomeController {
    
    private static final Logger logger = LoggerFactory.getLogger(HomeController.class);
    
    /**
     * Simply selects the home view to render by returning its name.
     */
    @RequestMapping(value = "/", method = RequestMethod.GET)
    public String home(Locale locale, Model model) {
        logger.info("Welcome home! The client locale is {}.", locale);
        
        Date date = new Date();
        DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, locale);
        
        String formattedDate = dateFormat.format(date);
        
        model.addAttribute("serverTime", formattedDate );
        
        return "home";
    }
    

    /**
     * Tiles를 사용(header, left, footer 포함)
     */        
    @RequestMapping("/testPage.do")
    public String testPage() {
        return "test.page";
    }
    
    
    
}
 

 

porm.xml

 

		<!-- 여기서부터 추가 -->
		
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-test</artifactId>
			<version>${org.springframework-version}</version>
		</dependency>

		<dependency>
		    <groupId>org.springframework</groupId>
		    <artifactId>spring-jdbc</artifactId>
		    <version>${org.springframework-version}</version>
		</dependency>
		
		<!-- maridb setting -->
		
		<dependency>
		    <groupId>org.mariadb.jdbc</groupId>
		    <artifactId>mariadb-java-client</artifactId>
		    <version>2.3.0</version>
		</dependency>
		

		<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
		<dependency>
		    <groupId>org.mybatis</groupId>
		    <artifactId>mybatis</artifactId>
		    <version>3.4.6</version>
		</dependency>
		
		
		<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis-spring -->
		<dependency>
		    <groupId>org.mybatis</groupId>
		    <artifactId>mybatis-spring</artifactId>
		    <version>1.3.2</version>
		</dependency>
		
		<dependency>
		    <groupId>org.bgee.log4jdbc-log4j2</groupId>
		    <artifactId>log4jdbc-log4j2-jdbc4</artifactId>
		    <version>1.16</version>
		</dependency>
        
        		<!-- Test -->
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.12</version>
			<scope>test</scope>
		</dependency>    
	

 

java version 수정

 

	<properties>
		<java-version>1.8</java-version>
		<org.springframework-version>4.3.8.RELEASE</org.springframework-version>
		<org.aspectj-version>1.8.9</org.aspectj-version>
		<org.slf4j-version>1.6.6</org.slf4j-version>
	</properties>

 

src/main/resources

 

mappers 생성 -> SQL xml 파일 위치

 

파일 추가

log4jdbc.log4j2.properties

log4jdbc.spylogdelegator.name=net.sf.log4jdbc.log.slf4j.Slf4jSpyLogDelegator

logback.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
	<include resource="org/springframework/boot/logging/logback/base.xml"></include>
	
	<!-- log4jdbc-log4j2 -->
	<logger name="jdbc.sqlonly" 		level="DEBUG"></logger>
	<logger name="jdbc.sqltiming" 		level="DEBUG"></logger>
	<logger name="jdbc.audit" 			level="DEBUG"></logger>
	<logger name="jdbc.resultset" 		level="DEBUG"></logger>
	<logger name="jdbc.resultsettable" 	level="DEBUG"></logger>
	<logger name="jdbc.connection" 		level="DEBUG"></logger>
</configuration>

 

mybatis-config.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
	PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
	"http://mybatis.org/dtd/mybatis-3-config.dtd">

<configuration>
	<typeAliases>
		<package name="com.peta.domain"/>
	</typeAliases>
</configuration>

 

package 는 맞는 이름으로 설정.

 

 

src/main/resources

mappers xml 파일 생성

boardMapper.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="com.peta.mapper.BoardMapper">
  
  	<insert id="create">
  	insert into tb1_board (title,content,writer) value (#{title},#{content},#{writer})
  	</insert>
  
  	<select id="read" resultType="com.peta.domain.BoardVO">
  	select bno,title,content,writer,regdate,viewcnt from tb1_board where bno=#{bno}
  	</select>
  	
  	<update id="update">
  	update tb1_board set title=#{title}, content =#{content} where bno=#{bno}
  	</update>
  
  	<delete id="delete">
  	delete from tb1_board where bno=#{bno}
  	</delete>
  
  	<select id="listAll" resultType="com.peta.domain.BoardVO">
  	<![CDATA[
  	select bno,title,content,writer,regdate,viewcnt from tb1_board where bno > 0 order by bno desc, regdate desc
  	]]>
  	</select>
  	
  	<select id="listPage" resultType="BoardVO">
  	<![CDATA[
  	select bno, title, content, writer, regdate, viewcnt from tb1_board where bno > 0 
  	order by bno desc, regdate desc limit #{page},10
  	]]>
  	</select>
  	
  	<select id="listCriteria" resultType="BoardVO">
  		<![CDATA[
  		select bno, title, content, writer, regdate, viewcnt from tb1_board where bno > 0 
  		order by bno desc, regdate desc limit #{pageStart}, #{perPageNum}
  		]]>
  	</select>
  	
  	<select id="countPaging" resultType="int">
  		<![CDATA[
  		select count(bno) from tb1_board where bno > 0
  		]]>
  	</select>
	<sql id="search">
  		<if test ="searchType !=null">
  			<if test="searchType = 't'.toString()">
  				and title like CONCAT('%',#{keyword},'%')
  			</if>
  			<if test="searchType = 'c'.toString()">
  				and content like CONCAT('%',#{keyword},'%')
  			</if>
  			<if test="searchType = 'w'.toString()">
  				and writer like CONCAT('%',#{keyword},'%')
  			</if>
  			<if test="searchType = 'tc'.toString()">
  				and (title like CONCAT('%',#{keyword},'%') OR content like CONCAT('%',#{keyword},'%'))
  			</if>
  			<if test="searchType = 'cw'.toString()">
  				and (content like CONCAT('%',#{keyword},'%') OR writer like CONCAT('%',#{keyword},'%'))
  			</if>
  			<if test="searchType = 'tcw'.toString()">
  				and (title like CONCAT('%',#{keyword},'%') OR content like CONCAT('%',#{keyword},'%')
  				OR writer like CONCAT('%',#{keyword},'%'))
  			</if>
  		</if>
	</sql>
  		
  	<select id="listSearch" resultType="BoardVO">
  		<![CDATA[
  		select * from tb1_board where bno > 0 
  		]]>
		<include refid="search"></include>
  		<![CDATA[
  		order by bno desc limit #{pageStart}, #{perPageNum}
  		]]>
  		
  	</select>
  	
  	<select id="listSearchCount" resultType="int">
  	<![CDATA[
  	select count(bno) from tb1_board where bno > 0
  	]]>
  	<include refid="search"></include>
  	</select>
 </mapper>

 

src/main/webapp/WEB-INF/spring/appServlet/servlet-content.xml

 

컨트롤러 연결

 

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:beans="http://www.springframework.org/schema/beans"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd
		http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">

	<!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->
	
	<!-- Enables the Spring MVC @Controller programming model -->
	<annotation-driven />

	<!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
	<resources mapping="/resources/**" location="/resources/" />

	<!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory -->
	<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<beans:property name="prefix" value="/WEB-INF/views/" />
		<beans:property name="suffix" value=".jsp" />
	</beans:bean>
	
	<context:component-scan base-package="com.peta.controller" />
	
	
	
</beans:beans>

 

src/main/webapp/WEB-INF/views/web.xml

 

	<filter>
		<filter-name>encoding</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>
	</filter>
	<filter-mapping>
		<filter-name>encoding</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>

encoding 추가

 

src/main/webapp/WEB-INF/spring/root-context.xml

 

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:mybatis-spring="http://mybatis.org/schema/mybatis-spring"
	xsi:schemaLocation="http://mybatis.org/schema/mybatis-spring http://mybatis.org/schema/mybatis-spring-1.2.xsd
		http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">
	
	<!-- Root Context: defines shared resources visible to all other web components -->
		
   <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
   		<!-- <property name="driverClassName" value="net.sf.log4jdbc.sql.jdbcapi.DriverSpy"></property> -->
        <property name="driverClassName" value="org.mariadb.jdbc.Driver"></property>
        <property name="url" value="jdbc:mariadb://127.0.0.1:3306/book_ex?useSSL=false"></property>
        <property name="username" value="id"></property>
        <property name="password" value="password"></property>
    </bean>
    
   	<bean id="SqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
		<property name="dataSource" ref="dataSource" />
		<property name="configLocation" value="classpath:/mybatis-config.xml"/>
		<property name="mapperLocations" value="classpath:/mappers/*Mapper.xml" />
	</bean>
	
	
	<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate"

		destroy-method="clearCache">

		<constructor-arg name="sqlSessionFactory" ref="SqlSessionFactory" />

	</bean> 
	<context:component-scan base-package="com.peta.persistence"></context:component-scan>
	<context:component-scan base-package="com.peta.service"></context:component-scan>
</beans>

 

JAVA 버전 변경

 

 

JUNIT 테스트시 추가.

 

 

test 

Mapper.xml 파일 모두 주석처리후.

 

src/test/java/DataTest.java

package com.peta.home;

import java.sql.Connection;

import javax.inject.Inject;
import javax.sql.DataSource;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations= {"file:src/main/webapp/WEB-INF/spring/**/root-context.xml"})
public class DataTest {
	@Inject
	private DataSource ds;
	
	@Test
	public void testConection()throws Exception{
		try(Connection con = ds.getConnection()){
			System.out.println("디비연결성공");
			System.out.println(con);
		}catch(Exception e) {
			System.out.println("디비연결실패");
			e.printStackTrace();
		}
		
	}
	
}

디비 연결 완료

 

jsp 양식 추가

<!DOCTYPE html>

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
    
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>

<html>
	<head>
		<meta charset="utf-8">
		<title>Welcome</title>
	</head> 
	<body>

	</body>
</html>

애노테이션 설명 사용
@Controller 스프링 MVC의 컨트롤러 객체임을 명시하는 애노테이션 클래스
@RequestMapping 특정 URI에 매칭되는 클래스나 메소드임을 명시하는 애노테이션 클래스,매소드
@RequestParam 요청(request)에서 특정한 파라미터의 값을 찾아낼때 사용 파라미터
@RequestHeader 요청(request)에서 특정 HTTP 헤더 정보를 추출할떄 사용 파라미터
@PathVariable 현재의 URI에서 원하는 정보를 추출할때 사용 파라미터
@CookieValue 현재 사용자의 쿠키가 존재하는 경우 쿠키의 이름을 이용해서 쿠키의 값을 추출 파라미터
@ModelAttribute 자동으로 해당 객체를 뷰까지 전달하도록 만드는 애노테이션 메소드,파라미터
@SessionAttribute 세션상에서 모델의 정보를 유지하고 싶은 경우에 사용 클래스
@InitBinder 파라미터를 수집해서 객체로 만들 경우에 커스터마이징 메소드
@RespnseBody 리턴 타임이 HTTP의 응답 메세지로 전송 메소드,리턴타입
@RequestBody 요청(request) 문자열이 그대로 파라미터로 전달 파라미터
@Repository DAO 객체 클래스
@Service 서비스 객체 클래스
 

Sass 사용시 node-sass 추가

$ yarn add node-sass

 

적용방법

 

src/MyComponent.js

import React from 'react';
import './MyComponent.scss';

const MyComponent = () => {
  return (
    <div className="MyComponent">
      <div className="something-inside">Hello CRA v2</div>
    </div>
  );
};

export default MyComponent;

 

src/MyComponent.scss

.MyComponent {
  background: black;
  color: white;
  padding: 1rem;
  .something-inside {
    background: white;
    color: black;
    font-size: 2rem;
    text-align: center;
    padding: 1rem;
  }
}

 

src/App.js

import React, { Component } from "react";
import MyComponent from "./MyComponent";

class App extends Component {
  render() {
    return (
      <div>
        <MyComponent />
      </div>
    );
  }
}

export default App;

 

 

CSS Module

 

CSS Module 은 사용 방식이 이전과 조금 다릅니다. 파일을 생성하실 때 파일이름.module.css 이런식으로 하시면 CSS Module 이 적용됩니다.

 

 

src/AnotherComponent.module.css

.wrapper {
  background: gray;
  color: white;
  padding: 1rem;
  font-size: 2rem;
}

 

src/AnotherComponent.js

import React from 'react';
import styles from './AnotherComponent.module.css';

const AnotherComponent = () => {
  return <div className={styles.wrapper}>What about CSS Module?</div>;
};

export default AnotherComponent;

 

src/App.js

import React, { Component } from 'react';
import MyComponent from './MyComponent';
import AnotherComponent from './AnotherComponent';

class App extends Component {
  render() {
    return (
      <div>
        <MyComponent />
        <AnotherComponent />
      </div>
    );
  }
}

export default App;

 

출처 : https://velog.io/@velopert/create-react-app-v2

'프로그래밍언어 > React' 카테고리의 다른 글

React Event 이벤트 종류  (0) 2019.07.20
React Component 불러오기 (props)  (0) 2019.07.20
React 주석  (0) 2019.07.20
React css사용방법  (0) 2019.07.20
React if문  (0) 2019.07.20

SyntheticEvent

This reference guide documents the SyntheticEvent wrapper that forms part of React’s Event System. See the Handling Events guide to learn more.

Overview

Your event handlers will be passed instances of SyntheticEvent, a cross-browser wrapper around the browser’s native event. It has the same interface as the browser’s native event, including stopPropagation() and preventDefault(), except the events work identically across all browsers.

If you find that you need the underlying browser event for some reason, simply use the nativeEvent attribute to get it. Every SyntheticEvent object has the following attributes:

boolean bubbles boolean cancelable DOMEventTarget currentTarget boolean defaultPrevented number eventPhase boolean isTrusted DOMEvent nativeEvent void preventDefault() boolean isDefaultPrevented() void stopPropagation() boolean isPropagationStopped() DOMEventTarget target number timeStamp string type

Note:

As of v0.14, returning false from an event handler will no longer stop event propagation. Instead, e.stopPropagation() or e.preventDefault() should be triggered manually, as appropriate.

Event Pooling

The SyntheticEvent is pooled. This means that the SyntheticEvent object will be reused and all properties will be nullified after the event callback has been invoked. This is for performance reasons. As such, you cannot access the event in an asynchronous way.

function onClick(event) { console.log(event); // => nullified object. console.log(event.type); // => "click" const eventType = event.type; // => "click" setTimeout(function() { console.log(event.type); // => null console.log(eventType); // => "click" }, 0); // Won't work. this.state.clickEvent will only contain null values. this.setState({clickEvent: event}); // You can still export event properties. this.setState({eventType: event.type}); }

Note:

If you want to access the event properties in an asynchronous way, you should call event.persist() on the event, which will remove the synthetic event from the pool and allow references to the event to be retained by user code.

Supported Events

React normalizes events so that they have consistent properties across different browsers.

The event handlers below are triggered by an event in the bubbling phase. To register an event handler for the capture phase, append Capture to the event name; for example, instead of using onClick, you would use onClickCapture to handle the click event in the capture phase.


Reference

Clipboard Events

Event names:

onCopy onCut onPaste

Properties:

DOMDataTransfer clipboardData


Composition Events

Event names:

onCompositionEnd onCompositionStart onCompositionUpdate

Properties:

string data


Keyboard Events

Event names:

onKeyDown onKeyPress onKeyUp

Properties:

boolean altKey number charCode boolean ctrlKey boolean getModifierState(key) string key number keyCode string locale number location boolean metaKey boolean repeat boolean shiftKey number which

The key property can take any of the values documented in the DOM Level 3 Events spec.


Focus Events

Event names:

onFocus onBlur

These focus events work on all elements in the React DOM, not just form elements.

Properties:

DOMEventTarget relatedTarget


Form Events

Event names:

onChange onInput onInvalid onSubmit

For more information about the onChange event, see Forms.


Mouse Events

Event names:

onClick onContextMenu onDoubleClick onDrag onDragEnd onDragEnter onDragExit onDragLeave onDragOver onDragStart onDrop onMouseDown onMouseEnter onMouseLeave onMouseMove onMouseOut onMouseOver onMouseUp

The onMouseEnter and onMouseLeave events propagate from the element being left to the one being entered instead of ordinary bubbling and do not have a capture phase.

Properties:

boolean altKey number button number buttons number clientX number clientY boolean ctrlKey boolean getModifierState(key) boolean metaKey number pageX number pageY DOMEventTarget relatedTarget number screenX number screenY boolean shiftKey


Pointer Events

Event names:

onPointerDown onPointerMove onPointerUp onPointerCancel onGotPointerCapture onLostPointerCapture onPointerEnter onPointerLeave onPointerOver onPointerOut

The onPointerEnter and onPointerLeave events propagate from the element being left to the one being entered instead of ordinary bubbling and do not have a capture phase.

Properties:

As defined in the W3 spec, pointer events extend Mouse Events with the following properties:

number pointerId number width number height number pressure number tangentialPressure number tiltX number tiltY number twist string pointerType boolean isPrimary

A note on cross-browser support:

Pointer events are not yet supported in every browser (at the time of writing this article, supported browsers include: Chrome, Firefox, Edge, and Internet Explorer). React deliberately does not polyfill support for other browsers because a standard-conform polyfill would significantly increase the bundle size of react-dom.

If your application requires pointer events, we recommend adding a third party pointer event polyfill.


Selection Events

Event names:

onSelect


Touch Events

Event names:

onTouchCancel onTouchEnd onTouchMove onTouchStart

Properties:

boolean altKey DOMTouchList changedTouches boolean ctrlKey boolean getModifierState(key) boolean metaKey boolean shiftKey DOMTouchList targetTouches DOMTouchList touches


UI Events

Event names:

onScroll

Properties:

number detail DOMAbstractView view


Wheel Events

Event names:

onWheel

Properties:

number deltaMode number deltaX number deltaY number deltaZ


Media Events

Event names:

onAbort onCanPlay onCanPlayThrough onDurationChange onEmptied onEncrypted onEnded onError onLoadedData onLoadedMetadata onLoadStart onPause onPlay onPlaying onProgress onRateChange onSeeked onSeeking onStalled onSuspend onTimeUpdate onVolumeChange onWaiting


Image Events

Event names:

onLoad onError


Animation Events

Event names:

onAnimationStart onAnimationEnd onAnimationIteration

Properties:

string animationName string pseudoElement float elapsedTime


Transition Events

Event names:

onTransitionEnd

Properties:

string propertyName string pseudoElement float elapsedTime


Other Events

Event names:

onToggle

Edit this page

 

reactjs/reactjs.org

The React documentation website. Contribute to reactjs/reactjs.org development by creating an account on GitHub.

github.com

https://reactjs.org/docs/events.html

'프로그래밍언어 > React' 카테고리의 다른 글

React Create-react-app V2 css , scss 변경사항 적용  (0) 2019.07.23
React Component 불러오기 (props)  (0) 2019.07.20
React 주석  (0) 2019.07.20
React css사용방법  (0) 2019.07.20
React if문  (0) 2019.07.20

MyComponent.js

 

import React, { Component } from 'react';

class MyComponent extends Component {
    render() {
        return (
            <div>
                나의 새롭고 멋진 컴포넌트
            </div>
        );
    }
}

export default MyComponent;

 

 

App.js

 

import MyComponent from './MyComponent';

1

 

import React , {Component} from 'react';
import './App.css'
import MyComponent from './MyComponent'; //MyCompopnent 파일 불러옵니다.

class App extends Component{
  render(){



    return(
<MyComponent/>
    )
  }
}

export default App;

 

 

import 를 이용하여 컴포넌트를 불러온다.

 

작동후 모습

 

 

Props

 

MyComponent.js (자식 컴포넌트)

            <div>
                안녕하세요 , 제이름은 {this.props.name} 입니다.
            </div>

 

App.js (부모 컴포넌트)

    return(
<MyComponent name="Petabyte"/>
    )

화면

 

 

defaultProps

 

class MyComponent extends Component {

    static defaultProps={
        name:'기본이름'
    }
    render() {
        return (
            <div>
                안녕하세요 , 제이름은 {this.props.name} 입니다.
            </div>
        );
    }
}

화면

 

 

PropTypes 종류

array : 배열

bool : 참, 거짓

func:함수

number:숫자

object:객체

string:문자열

symbol:ES6 문법의 심벌 개체

node :렌더링 할수 있는 모든것(숫자,문자열,element 또는 이들로 구성된 배열)

element:리액트 요소

instanseOf(myclass): 특정 클래스의 인스턴스

oneOf(['Male','Female']):주어진 배열 요소중 하나

oneOfType([React.PropTypes.string, React.PropTypes.number]):주어진 배열 안의 종류중 하나

arrayOf(React.PropTypes.number):주어진 종류로 구성된 배열

objectOf(React.PropTypes.number):주어진 종류의 값을 가진 객체

shape({name:React.PropTypes.striong, age:React.PropTypes.number}):주어진 스키마를 가진 객체

any:아무 종류

 

사용방법 : PropTypes.bool  또는 PropTypes.any.isRequired 같은 방식으로 사용

 

    constructor(props){
        super(props);
        this.state={
          number:0
        }

constructor 설정시 부모 컴포넌트에서 수정할수 없음.

'프로그래밍언어 > React' 카테고리의 다른 글

React Create-react-app V2 css , scss 변경사항 적용  (0) 2019.07.23
React Event 이벤트 종류  (0) 2019.07.20
React 주석  (0) 2019.07.20
React css사용방법  (0) 2019.07.20
React if문  (0) 2019.07.20
import React , {Component} from 'react';
import './App.css'

class App extends Component{
  render(){

    const style = {
      backgroundColor : 'gray',
      border:'1px solid black',
      height:Math.random(Math.random() * 500 ) + 50,
      width:Math.random(Math.random() * 500) + 50,
      WebkitTransition:'all',
      MozTransition:'all',
      msTransition:'all'
    };


    return(
      <div className="my-div"> 
      {/*요소 밖에서는 이렇게 주석 */}
        <h1>리액트 테스트</h1>
        <div style={style}
        // self-cloed 태그에서만 작동하는 주석
        />
        //이렇게는 주석이 되지않음.
        /*이것도 안됨*/
      </div>
    )
  }
}

export default App;

/> 안에 들어가야하며 새줄에 // 방식으로 주석을 사용할수있고. 그렇지 않을경우는

{/* 이런식으로 사용한다 */ }

화면에 보이는 모습

'프로그래밍언어 > React' 카테고리의 다른 글

React Event 이벤트 종류  (0) 2019.07.20
React Component 불러오기 (props)  (0) 2019.07.20
React css사용방법  (0) 2019.07.20
React if문  (0) 2019.07.20
React App.js  (0) 2019.07.20
import React , {Component} from 'react';


class App extends Component{
  render(){

    const style = {
      backgroundColor : 'gray',
      border:'1px solid black',
      height:Math.random(Math.random() * 500 ) + 50,
      width:Math.random(Math.random() * 500) + 50,
      WebkitTransition:'all',
      MozTransition:'all',
      msTransition:'all'
    };


    return(
      <div>
        <h1>리액트 테스트</h1>
        <div style={style}></div>
      </div>
    )
  }
}

export default App;

보이는 화면

 

 

Import 방식

App.css

.my-div{
  background-color: aqua;
  font-size: 15px;
}

 

 

App.js

import React , {Component} from 'react';
import './App.css'

class App extends Component{
  render(){

    const style = {
      backgroundColor : 'gray',
      border:'1px solid black',
      height:Math.random(Math.random() * 500 ) + 50,
      width:Math.random(Math.random() * 500) + 50,
      WebkitTransition:'all',
      MozTransition:'all',
      msTransition:'all'
    };


    return(
      <div className="my-div"> 
        <h1>리액트 테스트</h1>
        <div style={style}></div>
      </div>
    )
  }
}

export default App;

className 으로 div 를 설정한이후 App.css 를 import 한이후 사용한다.

 

설정시 보이는 화면

'프로그래밍언어 > React' 카테고리의 다른 글

React Component 불러오기 (props)  (0) 2019.07.20
React 주석  (0) 2019.07.20
React if문  (0) 2019.07.20
React App.js  (0) 2019.07.20
Create-react-app V2 변경 적용사항.  (0) 2019.07.13

ES6 의 const 와 let

 

var 방식

function myFunction(){
	var a = "hello";
    if(true){
    	var a = "bye";
        console.log(a);  // bye
       }
   console.log(a); //bye
 }
 
 

 

let 방식

function myFunction(){
	let a = 1;
    if(true){
    	let a = 2;
        console.log(a); // 2
    }
    console.log(a); //1
 }

 

const 는 재설정 불가.

 

 


If 문 대신 조건부 연산자.

 

import React , {Component} from 'react';


class App extends Component{
  render(){
    const text ='자바스크립트 테스트입니다.'
    const condition = true;


    return(
      <div>
        <h1>리액트 테스트</h1>
        <h2>{text}</h2> 
        {
          condition ? '참':'거짓'
        }
        <h5>참일때만 출력</h5>
        {
          condition ? '보여주세요':null
        }
        <h5>&& 연산자</h5>
        {
          condition  && '보여주세요'
        }
      </div>
    )
  }
}

export default App;

 

 

 

보이는 화면

 

'프로그래밍언어 > React' 카테고리의 다른 글

React 주석  (0) 2019.07.20
React css사용방법  (0) 2019.07.20
React App.js  (0) 2019.07.20
Create-react-app V2 변경 적용사항.  (0) 2019.07.13
React 초기 셋팅  (0) 2019.06.27
import React from 'react';
import logo from './logo.svg';
import './App.css';

function App() {
  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p>
          Edit <code>src/App.js</code> and save to reload.
        </p>
        <a
          className="App-link"
          href="https://reactjs.org"
          target="_blank"
          rel="noopener noreferrer"
        >
          Learn React
        </a>
      </header>
    </div>
  );
}

export default App;

import React from 'react';  (ES6 방식)

 

npm 을 통해 설치하게되면 node_modules 에 설치가된다. 

그것을 불러와 사용하기 위하여 import 할때 사용한다.

 

 

자바스크립트로 해석하면 

var React = require('react');

 

ES6 class 문법

class Dog{
	constructor(name) {
    	this.name = name;
       }
    say(){
    	console.log(this.name + ': 멍멍');
       }
  }
  
  const dong = new Dog('휜둥이');
  dog.say();
  
  //휜둥이 : 멍멍

 

 

샘플로 설치된 리액트를 실행한 화면

 

'프로그래밍언어 > React' 카테고리의 다른 글

React 주석  (0) 2019.07.20
React css사용방법  (0) 2019.07.20
React if문  (0) 2019.07.20
Create-react-app V2 변경 적용사항.  (0) 2019.07.13
React 초기 셋팅  (0) 2019.06.27

 

index.js [serviceWorker]

import * as serviceWorker from './serviceWorker';

serviceWorker.register ();

 

 

webpack.config.js

            {
              test: sassRegex,
              exclude: sassModuleRegex,
              use: getStyleLoaders(
                {
                  importLoaders: 2,
                  sourceMap: isEnvProduction && shouldUseSourceMap,
                },
                'sass-loader'
              ),
              sideEffects: true,
            },

해당부분 아래와 같이 변경.

            {
              test: sassRegex,
              exclude: sassModuleRegex,
              use: getStyleLoaders({
                importLoaders: 2,
                sourceMap: isEnvProduction && shouldUseSourceMap
              }).concat({
                loader: require.resolve('sass-loader'),
                options: {
                  includePaths: [paths.appSrc + '/styles'],
                  sourceMap: isEnvProduction && shouldUseSourceMap
                }
              }),
              // Don't consider CSS imports dead code even if the
              // containing package claims to have no side effects.
              // Remove this when webpack adds a warning or an error for this.
              // See https://github.com/webpack/webpack/issues/6571
              sideEffects: true
            },

 

'프로그래밍언어 > React' 카테고리의 다른 글

React 주석  (0) 2019.07.20
React css사용방법  (0) 2019.07.20
React if문  (0) 2019.07.20
React App.js  (0) 2019.07.20
React 초기 셋팅  (0) 2019.06.27

node 설치 https://nodejs.org/ko/

 

Node.js

Node.js® is a JavaScript runtime built on Chrome's V8 JavaScript engine.

nodejs.org

yarn 다운로드 https://yarnpkg.com/en/docs/install#windows-stable

 

Yarn

Fast, reliable, and secure dependency management.

yarnpkg.com

yarn 설치 https://chocolatey.org/install

 

Installation

That's it! All you need is choco.exe (that you get from the installation scripts) and you are good to go! No Visual Studio required. Chocolatey installs in seconds. You are just a few steps from running choco right now! With PowerShell, there is an additio

chocolatey.org

 

Vscode 설치 https://code.visualstudio.com/

 

Visual Studio Code - Code Editing. Redefined

Visual Studio Code is a code editor redefined and optimized for building and debugging modern web and cloud applications.  Visual Studio Code is free and available on your favorite platform - Linux, macOS, and Windows.

code.visualstudio.com

VS Code 확장프로그램

ESLint (자바스크립트 문법체크)

Realative Path (상대경로 파일 경로 지정)

Guides (들여쓰기 가이드라인)

Reactjs code snippets (리액트관련 스니펫 모음) 제작사 : Charalampos Karypidis 

 

 

create-react-app 으로 TEST 

 

case1 yarn 설치
yarn global add create-react-app

case2 npm 설치  
npm install -g create-react-app

 

react 테스트

$ create-react-app hello-react
$ cd hello-react
$ yarn start

 

다음과 같은 화면이 나오면 초기 셋팅 완료.

'프로그래밍언어 > React' 카테고리의 다른 글

React 주석  (0) 2019.07.20
React css사용방법  (0) 2019.07.20
React if문  (0) 2019.07.20
React App.js  (0) 2019.07.20
Create-react-app V2 변경 적용사항.  (0) 2019.07.13

 

#새로운 저장소 초기화 bash 상에서 루트로 진입한이후

git init

 

#초기 설정 

git config --global user.name 계정명

git config --global user.email email계정

 

#깃 클론

git clone https://깃주소명

 

#깃 파일추가

git add 파일명

git add .  : 전체파일을 추가

 

#깃 commit 

git commit -m "커밋시 메모"

 

#push 업로드

git push

 

#git 상태확인

git status


var Users=[{name:'소녀시대',age:20},{name:'걸스데이',age:22},{name:'티아라',age:23},{name:'애프터스쿨',age:25}];


console.log('배열 요소의 수 : %d',Users.length);

console.log('원본 Users');

console.dir(Users);


var Users2 = Users.slice(1,3);


console.log('slice() 로 잘라낸 후 Users2');

console.dir(Users2);


var Users3 = Users2.slice(1);


console.log('slice() 로 잘라낸후 Users3');

console.dir(Users3);


출력 결과:


배열 요소의 수 : 4
원본 Users
[ { name: '소녀시대', age: 20 },
{ name: '걸스데이', age: 22 },
{ name: '티아라', age: 23 },
{ name: '애프터스쿨', age: 25 } ]
slice() 로 잘라낸 후 Users2
[ { name: '걸스데이', age: 22 }, { name: '티아라', age: 23 } ]
slice() 로 잘라낸후 Users3
[ { name: '티아라', age: 23 } ]




1




var Users=[{name:'소녀시대',age:20},{name:'걸스데이',age:22},{name:'티아라',age:23}];

console.log('delete 키워드로 배열 요소 삭제 전 배열 요소의 수 : %d',Users.length);



delete Users[1];



console.log('delete 키워드로 배열 요소 삭제 후');

console.dir(Users);


Users.splice(1,0,{name:'애프터스쿨',age:25});

console.log('splice()로 요소 인덱스 1에 추가한후 ')

console.dir(Users)


Users.splice(2,1);

console.log('splice()로 인덱스 2의 요소를 1개 삭제후')

console.dir(Users)


실행후 : 

delete 키워드로 배열 요소 삭제 전 배열 요소의 수 : 3
delete 키워드로 배열 요소 삭제 후
[ { name: '소녀시대', age: 20 },
<1 empty item>,
{ name: '티아라', age: 23 } ]
splice()로 요소 인덱스 1에 추가한후
[ { name: '소녀시대', age: 20 },
{ name: '애프터스쿨', age: 25 },
<1 empty item>,
{ name: '티아라', age: 23 } ]
splice()로 인덱스 2의 요소를 1개 삭제후
[ { name: '소녀시대', age: 20 },
{ name: '애프터스쿨', age: 25 },
{ name: '티아라', age: 23 } ]


1



#오라클 DB 계정 생성 및 사용자 확인

오라클의 관리자 계정은 DBA 권한을 가지고 있어야 하며, 오라클 설치 시 기본적으로 Scott(사용자)가 자동 생성됨




서버에서 ORACLE 접속시

 

su - oracle

sqlplus '/as sysdba'



현재 생성된 계정 확인

SELECT * From DBA_USERS;

SELECT * FROM ALL_USERS;


사용자에게 부여된 시스템 권한 확인

SELECT * FROM DBA_SYS_PRIVX

WHERE GRANTEE = '사용자명';


사용자에게 부여된 롤 확인

SELECT * FROM DBA_ROLE_PRIVS

WHERE GRANTEE = '사용자명' ;


사용자에게 부여된 롤에 부여된 시스템 권한 확인

SELECT * FROM DBA_SYS_PRIVS

WHERE GRANTEE = '롤명' ;


타 사용자에게 부여한 객체(테이블 등) 권한 확인

SELECT * FROM DBA_TAB_PRIVS

WHERE OWNER = '테이블소유자명' ;
또는
SELECT * FROM DBA_TAB_PRIVS
WHERE GRANTEE = '권한부여자명' ;


사용자가 소유한 모든 테이블 확인

SELECT 테이블명 FROM USER_TABLES;


계정 생성

CREATE USER 계정명 IDENTIFIED BY 비밀번호;


계정 비밀번호 변경

ALTER USER 계정명 IDENTIFIED BY 변경할비밀번호;

  • 변경할 비밀번호는 문자로 시작해야합니다.


계정 권한 할당

GRANT CREATE 권한명 TO 계정;

  • 시스템 권한

  • 시스템 권한 종류

     내용

     CREATE USER

     데이터 베이스 유저 생성 권한

     SELECT ANY TABLE

     모든 유저의 테이블 조회 권한

     CREATE ANY TABLE

     모든 유저의 테이블 생성 권한

     CREATE SESSION

     데이터베이스 접속 권한

     CREATE TABLE

     테이블 생성 권한

     CREATE VIEW

     뷰 생성 권한

     CREATE PROCED USER

     프로시저 생성 권한

     CREATE SEQUENCE

     시퀀스 생성 권한

     SYSDBA

     데이터베이스를 관리하는 최고 권한

     SYSOPER

     데이터베이스를 관리는 권한

REVOKE 권한 제거
REVOKE 권한명 (시스템 명령 또는 SQL 명령) ON 테이블명 FROM 계정;


계정 삭제

DROP USER 계정명 CASCADE;




참고 링크


+ Recent posts