- ajax로 보낼 경우

@RequestParam(value="arr[]" String[] arr)


- get 또는 post로 보낼 경우

@RequestParam(value="arr" String[] arr)

1. 테이블 목록조회

SELECT *

FROM all_all_tables;


SELECT *

FROM dba_tables;


SELECT *

FROM ALL_OBJECTS

WHERE OBJECT_TYPE = 'TABLE'


-- 접속한 계정의 테이블 목록보기

SELECT *

FROM tabs;


SELECT *

FROM USER_OBJECTS 

WHERE OBJECT_TYPE = 'TABLE';


SELECT *

FROM USER_TABLES;


-- 테이블 코멘트 보기

SELECT *

FROM ALL_TAB_COMMENTS

WHERE TABLE_NAME = '테이블명'


SELECT *

FROM USER_TAB_COMMENTS;



2. 컬럼 목록조회

SELECT *

FROM COLS;

WHERE TABLE_NAME = '테이블명';


SELECT *

FROM ALL_TAB_COLUMNS

WHERE TABLE_NAME = '테이블명';


SELECT *

FROM USER_TAB_COLUMNS;


-- 컬럼 코멘트 보기

SELECT *

FROM USER_COL_COMMENTS;


블로그에 컴퓨터 구매 후기는 처음 써 보네요~ㅋ


집에 불이 나서 컴퓨터를 사야할 상황이 되어서 삼성이나 LG 또는 Lenovo를 알아 보고 있는데

업무상 방문한 업체 담당자가 한성 컴퓨터를 강력히 추천하더라구요..


첨이라 신뢰나 이런 걸 물어 봤는데 성능이나 A/S에 별 문제 없다고 하여 인터넷 검색 시작~


한성컴퓨터 사이트 들어가서 제품을 보는데 

대기업의 컴퓨터랑 비교 시 가격대비 성능은 짱~~~ 이더라구요~ㅋ


그리하여 고르고 골라 

XH58 BossMonster Hero Ti8400 구매 확정하고

11번가에서 6월 2일에 구매 하여 6월 7일에 배송완료~


상세 스팩은 아래와 같다고 합니다~


오픈한 첫 인상은 깔끔하다 였습니다.

전 원래 깔끔한걸 좋아라 해서~


이후 전원을 넣고 오픈하였을 때 딱 들어오는 키보드 백라이트가~ 

똭~~~~~ 이쁘더라구요~^ ^


난 왜 이런게 좋을 까요~~^ ^ㅋ

근데 여기서 살짝 문제가 생겼습니다.


백라이트 끄고 조절하는 Fn 키가 먹질 않는 문제가 발생~~

다른 Fn키는 다 되는데 백라이트와 Fn+ESC와 백라이트 조절이 되질 않는~~ㅜㅜ

그래서 현재 한성컴퓨터 홈페이지에 문의해 놓은 상태~


다른건 정말 맘에 쏙~~~

성능도 괘안코 외관도 괘안코~


그리고 양옆에 USB 포트가 3개 Mini DP 1개 HDMI 포트 1개,  멀티카드 리더기가 있네요~

또 USB Type C도 있군요~ㅋ



뭐~ 부족하진 않네요~^ ^


그리고 아래 부분으로는 받침이 약간 높이가 있고 구멍이 송송송~ 많이 나 있어서 발열에도 문제 없을 듯 하구요~ 


이렇게 생겼습니다~

아직 전원만 꼽고 베터리는 껴 놓지 않은 상황입니당~~


전체적으로는 매우 만족합니다.


지금 한 2일 써본 상황인데 부족하거나 불만인 부분은 없습니다.^ ^

넘 짧게 써봤나요???ㅋㅋ

나중에 A/S나 이런건 더 지켜 봐야 겠지만....


현재는 아주 추천합니다~~^ ^

'기타' 카테고리의 다른 글

아이콘 생성 홈페이지  (0) 2013.06.03

Data를 저장 시 저장되는 모든 정보를 이력으로 남겨 놓기 위하여 작성했습니다.


말들이 하도 많아서...ㅜㅜ



import java.lang.reflect.Method;

import java.util.Enumeration;


import javax.annotation.Resource;

import javax.servlet.http.HttpServletRequest;


import org.apache.commons.lang3.ArrayUtils;

import org.apache.commons.lang3.StringUtils;

import org.aspectj.lang.ProceedingJoinPoint;

import org.aspectj.lang.annotation.Around;

import org.aspectj.lang.annotation.Aspect;

import org.aspectj.lang.reflect.MethodSignature;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.springframework.security.core.context.SecurityContextHolder;

import org.springframework.security.core.userdetails.UserDetails;

import org.springframework.stereotype.Component;

import org.springframework.util.ObjectUtils;

import org.springframework.web.context.request.RequestContextHolder;

import org.springframework.web.context.request.ServletRequestAttributes;


import com.duegosystem.esh.common.utils.RequestUtils;

import com.duegosystem.esh.config.aspect.operate.annotation.OperateLog;

import com.duegosystem.esh.config.aspect.operate.service.UserOpertHistService;

import com.duegosystem.esh.config.aspect.operate.vo.OperateHistVo;

import com.duegosystem.esh.config.security.vo.UserVo;


/**

 * @author Duego-Choi

 *

 */

@Aspect

@Component

public class OperateAdviceLogging {


private static final Logger logger = LoggerFactory.getLogger(OperateAdviceLogging.class);


@Resource(name = "userOpertHistService")

private UserOpertHistService userOpertHistService;


/**

* 등록 수정 삭제 시에만 적용합니다.

*

* @param joinPoint

* @return

* @throws Throwable

*/

@Around("execution(* com.duegosystem..*Controller.insert*(..)) || "

+ "execution(* com.duegosystem..*Controller.update*(..)) || "

+ "execution(* com.duegosystem..*Controller.delete*(..))")

public Object aroundAdvice(ProceedingJoinPoint joinPoint) throws Throwable {


logger.debug("Operate History Logging save processing.......................................");


Object principal = (Object) SecurityContextHolder.getContext().getAuthentication().getPrincipal();


HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes())

.getRequest();


String httpMethod = request.getMethod();

MethodSignature signature = (MethodSignature) joinPoint.getSignature();

Method method = signature.getMethod();


logger.debug("httpMethod : " + httpMethod);

logger.debug("Class Method : " + method);


OperateHistVo operateHistVo = null;


/*

* 저장 수정 삭제 일경우만 사용하도록 하기 위해 POST 형식일 때만 적용되어지도록 처리

*/

if ("POST".equals(httpMethod)) {


if ((principal instanceof UserDetails)) {


operateHistVo = new OperateHistVo();


// 사용자 정보

UserVo user = (UserVo) principal;

logger.debug("empno : " + user.getEmpno());

logger.debug("emplNm : " + user.getEmplNm());


operateHistVo.setOpertId(user.getEmpno());

operateHistVo.setOpertNm(user.getEmplNm());


// 작업자 아이피

String ipAddress = RequestUtils.getRemoteIP(request);

logger.debug("ipAddress : " + ipAddress);

operateHistVo.setOpertIp(ipAddress);


// 접근 경로(메뉴 패턴)

String requestUri = request.getRequestURI();

String contextPath = request.getContextPath();

String pattern = requestUri.replaceAll("(^" + contextPath + ")|((\\.[^\\.]*)$)|((/[^/]+){1}/*$)", "")

+ "/";

logger.debug("Url pattern : " + pattern);

operateHistVo.setPattern(pattern);


String operateFile = requestUri.replace(contextPath, "").replace(pattern, "");

String operateType = "insert";

if (operateFile.startsWith("update")) {

operateType = "update";

} else if (operateFile.startsWith("delete")) {

operateType = "delete";

}

logger.debug("Operate Type : " + operateType);

operateHistVo.setOpertTy(operateType);


/*

* OperateLog Annotation을 통해서 등록하고자 하는 파라메터 또는 등록지 말아야 할 파라메터를

* 지정하였을 경우 처리합니다.

*

* 우선 순위는 등록해야할 파라메터가 있는 경우가 우선입니다.

*/

Enumeration<String> params = request.getParameterNames();


if (method.isAnnotationPresent(OperateLog.class)) {

OperateLog operateLog = method.getDeclaredAnnotation(OperateLog.class);


String[] saveParams = operateLog.params();

String[] notSaveParams = operateLog.notSaveParam();


// 저장하고자 하는 파라메타명을 설정하였을 경우

if (!ObjectUtils.isEmpty(saveParams)) {

while (params.hasMoreElements()) {

String paramName = (String) params.nextElement();

if (ArrayUtils.contains(saveParams, paramName)) {

if (!StringUtils.isEmpty(request.getParameter(paramName))) {

operateHistVo.addParam(paramName, request.getParameter(paramName));

}

}

}


// 저장하지 않을 파라메타명을 성정하였을 경우

} else if (!ObjectUtils.isEmpty(notSaveParams)) {

while (params.hasMoreElements()) {

String paramName = (String) params.nextElement();

if (ArrayUtils.contains(notSaveParams, paramName)) {

continue;

} else {

if (!StringUtils.isEmpty(request.getParameter(paramName))) {

operateHistVo.addParam(paramName, request.getParameter(paramName));

}

}

}

} else {

while (params.hasMoreElements()) {

String paramName = (String) params.nextElement();

if (!StringUtils.isEmpty(request.getParameter(paramName))) {

operateHistVo.addParam(paramName, request.getParameter(paramName));

}

}

}


} else {

while (params.hasMoreElements()) {

String paramName = (String) params.nextElement();

if (!StringUtils.isEmpty(request.getParameter(paramName))) {

operateHistVo.addParam(paramName, request.getParameter(paramName));

}

}

}


userOpertHistService.insert(operateHistVo);

}

}


Object obj = joinPoint.proceed();


/*

* Method에 해당하는 처리가 모두 끝난 후 후처리로 성공 상태 값을 Y로 바꿔준다.

*/

if ("POST".equals(httpMethod)) {

if (!ObjectUtils.isEmpty(operateHistVo)) {

try {

userOpertHistService.updateSuccess(operateHistVo.getOpertHistSeq());

} catch (Exception e) {

logger.error("OperateHist Advice Processing Error......!!!", e);

}

}

}


return obj;

}

}


Gradle의 멀티 프로젝트를 이용하여 모듈식 웹 프로젝트를 만들고 싶었다.

 

공통 부분과 그렇지 않은 부분을 업무별로 구성하여 각 프로젝트마다 필요한 업무를 조합하여 제공하고자 하는것이 목표였다.

 

열심히 구글링을 하였으나 멀티 프로젝트를 만드는 것은 많이 있지마 웹을 처리하는 방식은 없었다.

 

그래서 그냥 한번 이것 저것 찾아 보면서 한번 만들어 보기로 했다.

 

1. 전체 프로젝트 구조

 

 

프로젝트의 순서는 다음과 같이 정의 했다.

 

kamsi-system을 기본으로 하여 하위 프로젝트는 다음 순과 같이 정의를 하였다.


kamsi-common > kamsi-planner

 

kamsi-common을 kamsi-planner에서 Import 하여 배포하는 프로젝트라고 정의 했다.

 

 

 

2. Root Project

 

2.1. settings.gradle 생성

 

rootProject.name = 'kamsi-system'


include 'kamsi-common'
include 'kamsi-planner'

 

 

 

2.2. build.gradle

 

allprojects {


apply plugin: 'java'
apply plugin: 'eclipse-wtp'

ext {
     springVersion = '4.3.6.RELEASE'
     springSecurityVersion = '4.2.0.RELEASE'
     tilesVersion = '3.0.7'
     mybatisVersion = '3.4.1'
     mybatisSpringVersion = '1.3.0'
     log4jVersion = '2.8'
     poiVersion = '3.15'
}

 

repositories {
     mavenCentral()
     maven {
          name "OJDBC"
          url "http://repo.spring.io/libs-release"
     }
     maven {
          name "eGovFramework"
          url "http://maven.egovframe.kr:8080/maven/"
     }
 }

 

 dependencies {

  compile "org.springframework:spring-aop:${springVersion}"
  compile "org.springframework:spring-context:${springVersion}"
  compile "org.springframework:spring-web:${springVersion}"
  compile "org.springframework:spring-webmvc:${springVersion}"
  compile "org.springframework:spring-jdbc:${springVersion}"

  compile "org.springframework.security:spring-security-acl:${springSecurityVersion}"
  compile "org.springframework.security:spring-security-aspects:${springSecurityVersion}"
  compile "org.springframework.security:spring-security-config:${springSecurityVersion}"
  compile "org.springframework.security:spring-security-core:${springSecurityVersion}"
  compile "org.springframework.security:spring-security-taglibs:${springSecurityVersion}"
  compile "org.springframework.security:spring-security-web:${springSecurityVersion}"

  compile "org.springframework:spring-websocket:${springVersion}"

  compile "egovframework.rte:egovframework.rte.ptl.mvc:3.5.0"

  compile "org.mybatis:mybatis:${mybatisVersion}"
  compile "org.mybatis:mybatis-spring:${mybatisSpringVersion}"

  compile "org.aspectj:aspectjweaver:1.9.1"

  compile "javax.servlet:javax.servlet-api:3.1.0"
  compile "javax.servlet:jstl:1.2"
  compile "javax.servlet.jsp:jsp-api:2.2"

  compile "javax.validation:validation-api:1.1.0.Final"
  compile "com.fasterxml.jackson.jaxrs:jackson-jaxrs-base:2.5.2"

  compile "org.apache.tiles:tiles-api:${tilesVersion}"
  compile "org.apache.tiles:tiles-jsp:${tilesVersion}"

  compile "commons-io:commons-io:2.5"
  compile "commons-fileupload:commons-fileupload:1.3.2"
  compile "commons-beanutils:commons-beanutils:1.9.2"
  compile "org.apache.commons:commons-dbcp2:2.1"
  compile "org.apache.commons:commons-lang3:3.5"

  compile "org.apache.logging.log4j:log4j-slf4j-impl:${log4jVersion}"
  compile "org.apache.logging.log4j:log4j-core:${log4jVersion}"
  compile "org.apache.logging.log4j:log4j-api:${log4jVersion}"

  compile "org.hibernate:hibernate-validator:5.1.3.Final"

  compile "org.apache.poi:poi-ooxml-schemas:${poiVersion}"
  compile "org.apache.poi:poi:${poiVersion}"
  compile "org.apache.poi:poi-ooxml:${poiVersion}"
  compile "org.apache.poi:poi-scratchpad:${poiVersion}"

  compile "com.oracle:ojdbc6:12.1.0.1-atlassian-hosted"
  compile "org.bgee.log4jdbc-log4j2:log4jdbc-log4j2-jdbc4.1:1.16"

  compileOnly "org.projectlombok:lombok:1.16.20"
  compileOnly 'javax.servlet:javax.servlet-api:3.1.0'

}

}


subprojects {

task initSourceFolders {
     sourceSets*.java.srcDirs*.each {
         if( !it.exists() ) {
             it.mkdirs()
         }
     }

     sourceSets*.resources.srcDirs*.each {
         if( !it.exists() ) {
             it.mkdirs()
         }
     }


// webapp 폴더 생성

   def webappDir = new File("${projectDir}/src/main/webapp/WEB-INF")

   if( !webappDir.exists() ) {

webappDir.mkdirs()

   }

 }

}

 

위의 두가지 settings.gralde와 build.gradle을 생성 또는 수정한 후 Gradle build를 실행한다.

 

실행하고 나면 Eclipse 에 총 3개의 프로젝트가 생성되는것을 확인할 수 있다.

 

allprojects { ... } 생성되는 모든 프로젝트에 적용 되어져 모든 프로젝트에 Dependence에 정의된 라이브러리 들이 추가 된다.


subprojects { ... } 에 있는 내용은 하위 프로젝트에 source 파일이 담길 [ src/main/java, src/test/java] 와 [ src/main/webapp/WEB-INF ]를 생성하도록 설정 한다.

 

 

3. kamsi-common 프로젝트

 

앞서 말한바와 같이 프로젝트의 공통 부분이 들어갈 최상위 프로젝트이다.

 

Java Config 및 Security 또한 기본으로 사용되는 WEB Resource 등을 관리한다고 가정한다.

 

 

 

3.1 build.gradle

 

//apply plugin: 'war'

group = 'com.kamsi'
version = '0.0.1-SNAPSHOT'

 

jar {

metaInf {
    from 'src/main/webapp'
    into 'resources'

}

destinationDir rootProject.buildDir

}

 

위의 붉고 굵은 글씨의 항목이 중요한 부분이다.

 

지금까지 상위항목을 사용하기 위하여 이것저것을 해 보았지만 적용이 되지 않았다.

 

이클립스에서 java build path에 해당 프로젝트를 add 해도 적용이 되어지지 않았다.

 

그래서 구글링한 결과 사용하려면 jar 파일로 저장을 해서 import 시키는 것이 좋을 듯하다는 판단으로 소스를 jar로 묶어서 import 하였으나... 문제는 jsp 등 WEB-INF 하위에 있는 항목들을 불러 오지 못하는.... 그런 경우가 생겨 버렸다.

 

결국 jsp를 사용하고자 하면 jar 파일안에 있는 META-INF/resources 폴더 밑으로 들어가야 한다고 한다.

java 쪽에서 그렇게 정리를 해 놨다고 한다.

 

위의 붉고 굵은 글씨로 된 코드가 바로 그 부분이다.


이후 우리가 작성하던 방식대로 프로그램을 작성하면 된다.


4. kamsi-planner 프로젝트


해당 프로젝트에서는 kamsi-common을 사용하여 공통을 제외한 planner에 대하여만 작성을 하도록 설정한다.


4.1 build.gradle


apply plugin: 'war'


group = 'com.kamsi'

version = '0.0.1-SNAPSHOT'


war {

    baseName = 'duego-esh-web'

    version = '0.0.2-SNAPSHOT'

}


dependencies {

compile files("../build/kamsi-common-0.0.1-SNAPSHOT.jar")

}


jar {

    metaInf {

    from 'src/main/webapp'

    into 'resources'

    }


destinationDir rootProject.buildDir

}


/*********************************************************************

 * 테스트를 위한 jar 생성

 */

[compileJava, compileTestJava]*.options*.encoding = 'UTF-8' // 인코딩 UTF-8로 통일.


task subprojectBuild(type: Test) {

dependsOn ':kamsi-common:jar'

}


assemble.finalizedBy(subprojectBuild)

위의 소스와 같이 build과 정중 assemble task를 실행할 때 kamsi-common 프로젝트를 jar로 묶어주는 도록 처리를 했으며

또한 jar 파일을 묶은 kamsi-common 프로젝트를 dependencies 하도록 설정하였다.




이렇게 다 작성을 하고 kamsi-planner에서 WEB을 구동하였더니.....

Web Resources(css, javascript)를 찾아 오지 못하는 현상이 발생했다.


이러한 경우 jar 파일의 Web Resource 를 읽어 올수 있도록 처리를 해 줬다.


https://bit.ly/2lRwttG <-- 여기서 확인


이상으로 아주 간략하게 설정을 해 본 것이고... 

아주 초보적인 관점에서 처리 한것이라서... 


더 공부를 진행해야 겠다는 생각만이...ㅜㅜ


apache.commons.compress  받는곳 

https://commons.apache.org/proper/commons-compress/download_compress.cgi

 

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream;


public class ZipTest {

 public static void main(String[] args) throws Throwable {
  String path = "C:\\Users\\yuri\\Downloads\\commons-compress-1.16.1-bin\\commons-compress-1.16.1";
  //compress(path);
  decompress(path + "\\테스트.zip", path + "\\test");
 }

 /**
  * <pre>파일 압축하기</pre>
  * 파라메타 path가 폴더 이면 폴더 전체를 압축하고 파일경우는 파일만 압축
  * @param path
  * @throws IOException
  */
 public static void compress(String path) throws IOException {

  File file = new File(path);

  String files[] = null;

  // 파일이 디렉토리 일경우 리스트를 읽어오고
  // 파일이 디렉토리가 아니면 첫번째 배열에 파일이름을 넣는다.
  if (file.isDirectory()) {
   files = file.list();
  } else {
   files = new String[1];
   files[0] = file.getName();
   System.out.println(file.getName().getBytes());
  }

  // buffer size  int size = 1024;
  byte[] buf = new byte[size];

  String outZipNm = path + "\\테스트.zip";
  FileInputStream fis = null;
  ZipArchiveOutputStream zos = null;
  BufferedInputStream bis = null;

  try {

   // Zip 파일생성
   zos = new ZipArchiveOutputStream(new BufferedOutputStream(new FileOutputStream(outZipNm)));

   for (int i = 0; i < files.length; i++) {

    // 해당 폴더안에 다른 폴더가 있다면 지나간다.
    if (new File(path + "/" + files[i]).isDirectory()) {
     continue;
    }

    // encoding 설정
    zos.setEncoding("UTF-8");

    // buffer에 해당파일의 stream을 입력한다.
    fis = new FileInputStream(path + "/" + files[i]);

    bis = new BufferedInputStream(fis, size);

    // zip에 넣을 다음 entry 를 가져온다.
    zos.putArchiveEntry(new ZipArchiveEntry(files[i]));

    // 준비된 버퍼에서 집출력스트림으로 write 한다.
    int len;

    while ((len = bis.read(buf, 0, size)) != -1) {
     zos.write(buf, 0, len);
    }

    bis.close();

    fis.close();

    zos.closeArchiveEntry();

   }

   zos.close();

  } catch (FileNotFoundException e) {
   e.printStackTrace();
  } finally {

   if (zos != null) {
    zos.close();
   }

   if (fis != null) {
    fis.close();
   }

   if (bis != null) {
    bis.close();
   }

  }
 }

 /**
  * <pre>파일압축 해제</pre>
  *
  * @param zipFileName 압축파일명
  * @param directory 압축이 풀릴 파일 경로
  * @throws Throwable
  */
 public static void decompress(String zipFileName, String directory) throws Throwable {

        File zipFile = new File(zipFileName);
        FileInputStream fis = null;
        ZipInputStream zis = null;
        ZipEntry zipentry = null;

        try {

            //파일 스트림
            fis = new FileInputStream(zipFile);

            //Zip 파일 스트림
            zis = new ZipInputStream(fis);

            //entry가 없을때까지 뽑기
            while ((zipentry = zis.getNextEntry()) != null) {

                String filename = zipentry.getName();

                File file = new File(directory, filename);

                //entiry가 폴더면 폴더 생성
                if (zipentry.isDirectory()) {
                    file.mkdirs();
                } else {
                    //파일이면 파일 만들기
                    createFile(file, zis);
                }

            }

        } catch (Throwable e) {
            throw e;
        } finally {

            if (zis != null)
                zis.close();

            if (fis != null)
                fis.close();

        }

    }

 /**
  * <pre>파일 경로에 압축 푼 파일 생성</pre>
  *
  * @param file
  * @param zis
  * @throws Throwable
  */
 private static void createFile(File file, ZipInputStream zis) throws Throwable {

        //디렉토리 확인
        File parentDir = new File(file.getParent());

        //디렉토리가 없으면 생성하자
        if (!parentDir.exists()) {
            parentDir.mkdirs();
        }

        //파일 스트림 선언
        try (FileOutputStream fos = new FileOutputStream(file)) {

            byte[] buffer = new byte[256];
            int size = 0;
            //Zip스트림으로부터 byte뽑아내기
            while ((size = zis.read(buffer)) > 0) {
                //byte로 파일 만들기
                fos.write(buffer, 0, size);
            }

        } catch (Throwable e) {
            throw e;
        }

    }

}

 

참조 :

압축하기 : 출처: http://javacpro.tistory.com/21 [버물리의 IT공부]

압축 풀기 : http://nowonbun.tistory.com/321 [명월 일지]

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

ArrayList 정렬 및 자르기  (0) 2016.03.07
형 변환 모음...  (0) 2015.05.28
인코딩 한방에 테스트 하기  (0) 2015.04.23
String.format()을 이용하여 Date 표현하기  (0) 2013.10.01

Spring Security 설정 파일에서 다음과 같이 설정한다.


@Configuration

@Import({SecurityBeanConfig.class})

@EnableWebSecurity

public class SecurityConfig extends WebSecurityConfigurerAdapter {


  ...


@Autowired

private FilterSecurityInterceptor filterSecurityInterceptor;


  ...


@Override

public void configure(WebSecurity web) throws Exception {

web

.ignoring()

.antMatchers("/resources/**")

.and()

.privilegeEvaluator(webInvocationPrivilegeEvaluator());

}  


   ...


/**

* Cusome Tag를 사용하여 Web 페이지에서 권한을 체크하고 싶을 때 사용함.

*

* <code>

* <sec:authorize url="/admin/stats/index.jsp">

* <a href="<spring:url value="/admin/stats/index.jsp"/>">link</a>

* </sec:authorize>

* </code>

*

* @return

*/

@Bean

public WebInvocationPrivilegeEvaluator webInvocationPrivilegeEvaluator(){

return new DefaultWebInvocationPrivilegeEvaluator(filterSecurityInterceptor);

}

}


사용은 위의  주석과 같이


체크하고자 하는 경로를 넣어 주면 접근이 가능한지 여부를 판단하여 준다.


<sec:authorize url="/admin/stats/index.jsp">

<a href="<spring:url value="/admin/stats/index.jsp"/>">link</a>

</sec:authorize>


PHP 설정에서 register globals가 off 일 경우 처리

 

if (! ini_get('register_globals')) {

 

Static $superGlobals    = array(

'e' => '_ENV'       ,

'g' => '_GET'       ,

'p' => '_POST'      ,

'c' => '_COOKIE'    ,

'r' => '_REQUEST'   ,

's' => '_SERVER'    ,

'f' => '_FILES'

);


foreach( $superGlobals as $key => $val ) {

foreach( ${$superGlobals[$key]} as $valKey => $valVal ) {

${$valKey} = $valVal;

}

}

}


1. Lombok 다운로드


- http://projectlombok.org/download



2. Lombok 설치


- 다운로드 경로로 이동

- java -jar lombok.jar 실행




- 위와 같은 화면이 뜨면 확인 버튼 클릭


- Specify location... 버튼을 클릭하여 Eclipse.exe 파일을 찾아서 선택



- Install / Update 버튼 클릭


- Quit Installer 버튼 클릭




3. 프로젝트에 Lombok Dependency 추가


- Maven dependency


<dependency>

    <groupId>org.projectlombok</groupId>

    <artifactId>lombok</artifactId>

    <version>1.16.20</version>

    <scope>provided</scope>

</dependency>


- Gradle dependency


provided group: 'org.projectlombok', name: 'lombok', version: '1.16.20'


1. Eclipse 플러그인 설정


- Eclipse Marketplace 에서 gradle 검색


- Buildship Gradle Integration 2.0 인스톨




- 설치 완료 후 Ecilpse 재시작




2. Gradle 프로젝트 생성


- File > New > Project 메뉴 선택


- Gradle > Gradle Project 선택





3. Source Folder 및 Web Folder 생성


- Java Resources 에 Source Folder 추가

  

  : src/main/resources





- 하단 src/main 하위폴더로 Web Folder 생성


  : webapp

  : webapp/WEB-INF




전체 폴더 구조






3. Gradle 설정


- build.gradle 파일 오픈


- plugin 설정


apply plugin: 'java'

apply plugin: 'eclipse-wtp'

apply plugin: 'war'



- property 설정


ext {

  springVersion = '4.3.6.RELEASE'

  springSecurityVersion = '4.2.0.RELEASE'

  tilesVersion = '3.0.7'

  mybatisVersion = '3.4.1'

  mybatisSpringVersion = '1.3.0'

  log4jVersion = '2.8'

  poiVersion = '3.15'

}


- repositories 설정

repositories {
  mavenCentral()
  maven {
    name "eGovFramework"
    url "http://www.egovframe.go.kr/maven/"
  }
  maven {
    name "OJDBC"
    url "https://mvnrepository.com/artifact/com.jslsolucoes/ojdbc6/"
  }
}

dependencies 설정


dependencies {

  compile "org.springframework:spring-aop:$rootProject.ext.springVersion"

  compile "org.springframework:spring-context:$rootProject.ext.springVersion"
  ...

}

=IF( ISERROR(VLOOKUP(C2,$A$2:$A$260, 1, FALSE)),FALSE, TRUE)

스프링 동적리스트 바인딩의 경우 최대 256개까지가 기본설정으로 되어 있다.


만약, 256개 이상을 파라미터로 넘기게 된다면 IndexOutOfBoundsException이 발생하게 될 것이다.



@InitBinder

public void initBinder(WebDataBinder binder) {

    binder.setAutoGrowCollectionLimit(1024);

}


위와 같이 Controller에 추가를 하여 해결하면 된다.


다른 방법으로 톰캣의 경우 설정하는 법도 있곤 한데.. 그냥 이걸로...ㅋ

제목을 써 놓고도 제목이 어렵네용..ㅡㅡ;;


여튼 RESTFul 서비스를 하여 JSON 으로 결과 값을 받을 경우


public class ResponseWrapper {

...

private Object data;

...

}


위와 같은 방식으로 Data를 받을 경우 저 Data의 값이 어떠한 타입인지 모르기 때문에 

결과 적으로는 


{

success : true,

data : { userId=kamsi76, password=1234 }

}


이렇게 data가 JSON 형식이 아닌 형식으로 받게 되어 맵핑이 정상적으로 되지 않습니다.


그래서 다음과 같이


public class ResponseWrapper<T> {

...

private T data;

...

}


이렇게 처리 하면 되겠구나 하고 다시 수정을 했으나....


다음과 같은 문제가 발생을 합니다.


RestTemplate restTemplate = getRestTemplate();

ResponseEntity<ResponseWrapper<UserVo>> response = restTemplate.exchange(

url,

method,

null,

ResponseWrapper.class

);


이런식으로 하면 오류가 발생한다는....


그래서 구글링 한 결과


RestTemplate restTemplate = getRestTemplate();

ResponseEntity<ResponseWrapper<UserVo>> response = restTemplate.exchange(

url,

method,

null,

new ParameterizedTypeReference<ResponseWrapper<UserVo>>() {});

);


이렇게 하면 정상 동작을 합니다...


하지만 여기서 더 나아가...


저걸 공통으로 사용하기 위해 Util을 만들어서 사용한다고 할 경우


public <V, T> ResponseEntity<ResponseWrapper<T>> send(String url, V sendObj, Class<T> responseType, HttpMethod method) {

RestTemplate restTemplate = getRestTemplate();

ResponseEntity<ResponseWrapper<T>> response = restTemplate.exchange(

url,

method,

getEntity(sendObj),

new ParameterizedTypeReference<ResponseWrapper<T>>() {});


return response;

}


이렇게 처리하면 될 줄 알았습니다....


그런데... 정상 동작하지 않고 


{

success : true,

data : { userId=kamsi76, password=1234 }

}


결과가 이렇게 나와 버리는 현상이 나오게 되었습니다..


다시 구글링....


그래서 최종 소스는 다음과 같습니다..


public class RESTUtil {


...


public <V, T> ResponseEntity<ResponseWrapper<T>> send(String url, V sendObj, Class<T> responseType, HttpMethod method) {

RestTemplate restTemplate = getRestTemplate();

ResponseEntity<ResponseWrapper<T>> response = restTemplate.exchange(

url,

method,

getEntity(sendObj),

new ParameterizedTypeReference<ResponseWrapper<T>>() {

public Type getType() {

return new CustomParameterizedTypeImpl((ParameterizedType)super.getType(), new Type[] { responseType});

}

}

);


return response;

}


//내부 클래스로 두었슴...

class CustomParameterizedTypeImpl implements ParameterizedType {


    private ParameterizedType delegate;


    private Type[] actualTypeArguments;


    CustomParameterizedTypeImpl(ParameterizedType delegate, Type[] actualTypeArguments) {

            this.delegate = delegate;

            this.actualTypeArguments = actualTypeArguments;

        }


@Override

public Type[] getActualTypeArguments() {

return actualTypeArguments;

}


@Override

public Type getRawType() {

return delegate.getRawType();

}


@Override

public Type getOwnerType() {

return delegate.getOwnerType();

}


}

}


이와 같이 사용하면 정상 동작합니다.


이상입니다.



'JAVA > Webservice(REST)' 카테고리의 다른 글

07. POST 방식 호출  (0) 2015.08.06
06. 서비스 호출  (0) 2015.08.06
05. beans.xml과 web.xml  (0) 2015.08.06
04. 프로젝트의 시작  (0) 2015.08.06
03. Eclipse 환경설정  (0) 2015.08.06

Restfull을 사용 할 때 method 방식에 put 또는 delete 의 경우 jquery에서는 $.ajax를 사용하여만 하는 번거로움이 있습니다.


Method PUT을 사용할 경우


1
2
3
4
5
6
7
8
9
$.ajax({
    url : "/user",
    type : "PUT",
    data : $("#testForm").serialize(),
    dataType : "text",
    success: function(result) {
        console.log( result );
    }
});




Method DELETE를 사용할 경우


1
2
3
4
5
6
7
$.ajax({
    type : "DELETE",
    dataType : "text",
    success: function(result) {
        console.log( result );
    }
});





위의 소스를 $.post나 $.get 처럼 사용하고자 할 때 다음 예제를 이용하면 됩니다.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
jQuery.each([ "put""delete" ], function(i, method) {
    jQuery[method] = function(url, data, callback, type) {
        if (jQuery.isFunction(data)) {
            type = type || callback;
            callback = data;
            data = undefined;
        }
 
        return jQuery.ajax({
            url : url,
            type : method,
            dataType : type,
            data : data,
            success : callback
        });
    };
});



사용 :


Method PUT을 사용할 경우


1
2
3
$.put("/user", $("#testForm").serialize(), (result) => {
    console.log( result );
},"text");



Method DELETE를 사용할 경우


1
2
3
$.delete("/user/kamsi76", (result) => {
    console.log( result );
},"text");


Express.js의 라우팅은 URI(경로), HTTP 요청 Method(GET, POST 등)의 특정 엔드포인트에 대한 클라이언트 요청에 응답하는 방법을 결정하는 것을 말합니다.



라우트 Method 설정


라우터의 기본 구조는 다음과 같습니다.


app.method(path, handler)

    • method - HTTP 요청 Method
    • path - 엔드포인트 경로
    • handler - 클라이언트 접속 시 실행 되는 함수


위의 구조를 보듯이 각 메소드 별로 처리 라우터를 지정할 수 있다.


1. GET 방식 호출


1
2
3
app.get('/', (req, res) => {
  res.send('Hello World!');
});



2. POST 방식 호출


1
2
3
app.post('/', (req, res) => {
  res.send('Got a POST request');
});



3. PUT 방식 호출


1
2
3
app.put('/user', (req, res) => {
  res.send('Got a PUT request at /user');
});



4. DELETE 방식 호출


1
2
3
app.delete('/user', (req, res) => {
  res.send('Got a DELETE request at /user');
});



5. 모든 Method 접근 허용


1
2
3
app.all('/', (req, res) => {
  console.log('All Method request ...');
});




라우트 경로 설정


라우트 경로는 문자열 또는 문자열 패턴 그리고 정규식으로 지정할 수 있습니다.



1. 문자열


기본은 위의 예제와 같이


1
2
3
app.get('/', (req, res) => {
  res.send('Hello World!');
});





이렇게 호출 됩니다.


/about 에 접근하자 할 경우에는 다음과 같이 작성을 하면 됩니다.


1
2
3
app.get('/about', (req, res) => {
  res.send('about');
});




2. 문자열 패턴


다음 예제는 경로가 /abcd 또는 /acd 에 접근이 가능하도록 합니다.


1
2
3
app.get('/ab?cd', (req, res) => {
  res.send('ab?cd');
});



다음 예제는 /abcd 또는 /abbbbbbcd 등의 경로에 접근이 가능하도록 합니다. 


1
2
3
app.get('/ab+cd', (req, res) => {
  res.send('ab+cd');
});



다음 예제는 /abcd 또는 /ab123cd 등과 같이 ab와 cd 사이에 어떠한 문자가 와도 접근이 가능하도록 합니다.


1
2
3
app.get('/ab*cd', (req, res) => {
  res.send('ab*cd');
});



3. 정규식


다음은 예제는 a가 포함된 모든 경로에 접근하도록 합니다.


1
2
3
app.get(/a/, (req, res) => {
  res.send('/a/');
});


다음 예제는 fly로 끝나는 경로에 접근이 가능하도록 합니다.


1
2
3
app.get(/.*fly$/, (req, res) => {
  res.send('/.*fly$/');
});





라우트 핸들러(Callback 함수)


라우팅 핸들러는 하나 이상으로 설정이 가능합니다.


1
2
3
app.get('/example', (req, res) => {
  res.send('Hello from A!');
});



위와 같이 라우터 핸들러를 하나만 가지는걸 기본으로 하지만 다음과 같이 1개 이상의 라우터 핸들러를 처리할 수도 있습니다. 그러기 위해서는 next() 를 반드시 호출해 줘야 합니다. 


1
2
3
4
5
6
app.get('/example'function (req, res, next) {
  console.log('the response will be sent by the next function ...');
  next();
}, function (req, res) {
  res.send('Hello from B!');
});


위와 같이 next를 사용하면 다음 핸들러를 호출할 수 있습니다.


또한 함수들을 만들어서 배열 형태로 라우트 처리를 할 수 있습니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var cb0 = function (req, res, next) {
  console.log('CB0');
  next();
}
 
var cb1 = function (req, res, next) {
  console.log('CB1');
  next();
}
 
var cb2 = function (req, res) {
  res.send('Hello from C!');
}
 
app.get('/example', [cb0, cb1, cb2]);



Console 결과는 다음과 같습니다.


1
2
3
CB0
CB1
Hello from C!






app.route()


라우트 경로에 대한 체인이 가능하도록 작성이 가능합니다.


정의된 체인 라우트 핸들러는 다음과 같이 사용합니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
app.route("/chain")
    .all((req, res, next) => {
        console.log('Time: 'Date.now());
        next();
    })
    .get((req, res) => {
        console.log("GET call~");
        res.send("LIST BOOK~~~~");
    })
    .post((req, res) => {
        console.log("POST call~");
        res.send("INSERT BOOK~~~~");
    })
    .put((req, res) => {
        console.log("PUT call~");
        res.send("UPDATE BOOK~~~~");
    })
    .delete((req, res) => {
        console.log("DELETE call~");
        res.send("DELETE BOOK~~~~");
    });





express.Router


express.Router을 사용하면 모듈식 라우트 핸들러를 작성할 수 있습니다.


express.Router로 작성은 Java 웹프로그램으로 따졌을 때 Controller과 비슷하다(??) 라고 할 수 있을 듯하네요.


위의 chain route를 기준으로 모듈 작성은 다음과 같이 합니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
const express = require("express");
const router = express.Router();
 
router.route("/")
    .all((req, res, next) => {
        console.log('Time: 'Date.now());
        next();
    })
    .get((req, res) => {
        console.log("GET call~");
        res.send("LIST BOOK~~~~");
    })
    .post((req, res) => {
        console.log("POST call~");
        res.send("INSERT BOOK~~~~");
    })
    .put((req, res) => {
        console.log("PUT call~");
        res.send("UPDATE BOOK~~~~");
    })
    .delete((req, res) => {
        console.log("DELETE call~");
        res.send("DELETE BOOK~~~~");
    });
 
module.exports = router;



이렇게 모듈을 생성을 하고 app메서는 다음과 같이 로딩합니다.


1
2
3
4
5
6
7
8
9
10
const express = require("express");
const app = express();
 
const chain = require("./chain");
 
app.use("/chain", chain);
 
app.listen(3000, () => {
    console.log( "Express Server port 3000");
});


그리고 최종적으로 브라우저에서 확인을 해보면 결과를 확인할 수 있습니다.



'JavaScript > NodeJS' 카테고리의 다른 글

[NodeJS] Express.js - Hello World!!!  (0) 2017.12.05
[NodeJS] Express.js 시작  (0) 2017.12.05
[NodeJS] 서버 만들기(HTTP Server) - 2  (0) 2017.11.28
[NodeJS] 서버 만들기(HTTP Server) - 1  (0) 2017.11.27
[NodeJS] File System  (0) 2017.11.16

+ Recent posts