[JSTL이란]

JSTL 은 JSP(Java Server Pages) Standard Tag Library의 약자로써, jsp 어플리케이션의 핵심기능을 캡슐화한 유용한 태그 모음.

 

tutorial 사이트 :

https://www.tutorialspoint.com/jsp/jsp_standard_tag_library.htm

 

<JSTL 사용을 위한 taglib 선언>

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

사용하고자 하는 태그라이브러리(taglib)의 prefix 를 각각 선언

 

 

<JSTL tag 별 용도 및 설명>

1.c tag : 코어

c:if : 조건문 

c:choose c:when c:otherwise : switch case default 조건문

c:forEach : 반복문

c:set : 변수 할당

c:out : 출력

2.fn tag : 길이반환 등의 함수

fn:length : 길이 반환

fn:substring : 문자열 자르기

3.fmt tag : format 변환용으로 사용

아래 url 참고

https://www.javatpoint.com/jstl-formatting-tags

 

 

<사용 예>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<c:if test="${ not empty dataList}">
     <c:forEach var="list" items="${dataList}" varStatus="status">
        <tr class="dataTr tmpTr" style='cursor:pointer;' onclick="goInfo('${list.seq}')">
            <td>${list.start_page_limit + status.count}</td>
            <td>${list.seq}</td>
            <td>
            <c:choose>
               <c:when test="${fn:length(list.memo)>20}">
                  <c:out value="${fn:substring(list.memo, 0, 19)}"/>...
               </c:when>
               <c:otherwise>
                  <c:out value="${list.memo}"/>
               </c:otherwise>
            </c:choose>
            </td>
            <td>
            <c:set var="nm" value="${fn:split(list.user_name, '^')}" />
            <c:forEach var="obj" items="${nm}" varStatus="idx">
              ${obj}<c:if test="${!idx.last}">,<br></c:if>
            </c:forEach> 
            </td>
        </tr>
    </forEach>
</c:if>
cs

1 line : 서버로부터 받아온 dataList 가 비어있지 않다면 2~23 라인 실행

2 line : 반복문

3 line : 서버에서 받아온 dataList 를 list 변수에 담아 for 문 내에서 사용. varStatus 는 index 와 관련되어 사용이 가능한 속성

4 line : varStatus.count로 순번 출력(1부터 출력) (참고: varStatus.index는 0부터 출력)

7 ~ 14 line : if else 구문

8 line : list에서 가져온 memo 의 길이가 20 보다 큰 경우

9 line : 0~19번째 문자까지 출력 후 ... 붙이기 (말줄임)

17 line : nm 변수에 list 에서 가져온 user_name 을 ^ 문자 기준으로 split 하여 저장

18 line : nm 변수를 obj 변수에 담아 for 문 내에서 사용

19 line : 마지막이 아닌 경우 (!varStatus.last) ,<br> 을 붙임 (반대로 다시말해 마지막인 경우 ,<br> 을 붙이지 않음) 

 

 

< foreach 의 varStatus >

<c:forEach var='list' items='${dataList}' varStatus='status'>

   ${status.current} // 현재아이템

   ${status.index}   // 0부터 시작하는 인덱스

   ${status.count}   // 1부터 시작하는 카운트

   ${status.first}   // 현재 인덱스가 첫번째 인덱스인지 판별

   ${status.last}    // 현재 인덱스가 마지막 인덱스인지 판별

   ${status.begin}   // 반복문 시작 값

   ${status.end}     // 반복문 끝 값

   ${status.step}    // 반복문 증가 값

</c:forEach>

 

참고 : https://www.javatips.net/blog/jstl-last-using-varstatus

 

 

< 주의사항 > 

페이지 로드 순서(웹언어들의 동작 및 실행 순서(Load Sequence On Web))에 주의하자..

JAVA > JSTL > HTML > JavaScript(jQuery)

 

 

해당 부분은 따로 정리해서 포스팅하겠다.

 

반응형

POI (Excel) + Spring + JSP

 

POI lib 을 사용한 excel 파일 생성 및 다운로드

 

 

1. dependency 추가(HSSF 예제)

1
2
3
4
5
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi</artifactId>
    <version>3.15</version>
</dependency>
cs

* HSSF이외에 XSSF, SXSSF 라이브러리 존재. 

HSSF : excel 의 .xls 파일 포맷을 위한 POI

XSSF : .xls 및 .xlsx 파일 포맷을 위한 POI

SXSSF : 이미지 및 대용량 엑셀 데이터를 위한 POI

SXSSF 의 경우 HSSF, XSSF에 비해 성능이 떨어지는 거라는 글을 봤음, 대용량 처리가 아닌 이상 XSSF 혹은 HSSF 사용

 

2. 엑셀 파일 생성(HSSF 사용 예제)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
@Override
    public HSSFWorkbook listExcelDownload(VO param) throws Exception {
        
        
        HSSFWorkbook workbook = new HSSFWorkbook();
        
        HSSFSheet sheet = workbook.createSheet("엑셀시트명");
        
        HSSFRow row = null;
        
        HSSFCell cell = null;
        
        param.setPager(false);
        param.setNullText(NULL_TEXT);
        param.setSeparator(DELI_EXCEL);
        List<VO> list = Dao.selectList(param);
        
        row = sheet.createRow(0);
        String[] headerKey = {"칼럼1""칼럼2""칼럼3""칼럼4"};
        
        for(int i=0; i<headerKey.length; i++) {
            cell = row.createCell(i);
            cell.setCellValue(headerKey[i]);
        }
        
        for(int i=0; i<list.size(); i++) {
            row = sheet.createRow(i + 1);
            StbcsTaskHstVO vo = list.get(i);
            
            cell = row.createCell(0);
            cell.setCellValue(vo.getEx1());
            
            cell = row.createCell(1);
            cell.setCellValue(vo.getEx2());
            
            cell = row.createCell(2);
            cell.setCellValue(vo.getEx3());
            
            cell = row.createCell(3);
            cell.setCellValue(vo.getEx4());
 
        }
        
        return workbook;
    }
    
cs

* HSSF lib 사용시

HSSFWorkbook 생성 > HSSFWorkbook에 HSSFSheet 생성 > HSSFSheet에 HSSFRow 생성 > HSSFRow에 HSSFCell 생성

* XSSF lib 사용시

흐름은 위와 동일, HSSF을 XSSF로만 바꿔주면 됨(ex: HSSFWorkbook >> XSSFWorkbook).

 

 

3. Controller (엑셀 다운로드)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@RequestMapping(value="/exceldownload.do")
    public void excelDownload( HttpServletRequest request ,HttpServletResponse response ,HttpSession session, VO param) throws Exception {
        
        OutputStream out = null;
        
        try {
            HSSFWorkbook workbook = Service.listExcelDownload(param);
            
            response.reset();
            response.setHeader("Content-Disposition""attachment;filename=stbcs_history.xls");
            response.setContentType("application/vnd.ms-excel");
            out = new BufferedOutputStream(response.getOutputStream());
            
            workbook.write(out);
            out.flush();
            
        } catch (Exception e) {
            logger.error("exception during downloading excel file : {}", e);
        } finally {
            if(out != nullout.close();
        }    
    }
cs

 

4. jsp

1
2
3
4
5
6
7
8
9
/* 엑셀다운로드 */
function downloadExcel(){
 
    var f = document.frmSearch;
    f.action = "/exceldownload.do";
    f.submit();
    
    return;
}
cs

 

 

 

 

반응형

CSS 적용 우선 순위

1. 사용자 스타일 시트 우선

!important 선언을 한 사용자 스타일  > !important 선언을 한 작성자 스타일 >
작성자 스타일 > 사용자 스타일 > User Agent 선언 (브라우저 자체의 선언)

 

2. 계산결과가 높을 수록 우선 적용된다.

a = 선택자중 ID의 수를 세어 100자리에 놓는다,

b = 선택자중 가상 클래스와 클래스의 수를 세어 10자리에 놓는다.

c = 선택자중 엘리먼트의 수를 세어 1의 자리에 놓는다.

  a b c 계산결과
*{} 0 0 0 0
li{} 0 0 1 1
ul li{} 0 0 2 2
li.num{} 0 1 1 11
li.num.last{} 0 2 1 21
p#wrap{} 1 0 1 101

 

3. 가장 마지막에 지정된 스타일이 우선 적용된다.

<style type="text/css">

  p.test{color:black;}

</style>

<p class="test" style="color:red;">TEST</p>

 

위 경우 동일한 p 태그의 test 클래스에 red 색상 css 가 선언되어있다.

p 태그가 마지막에 지정된 스타일이므로 TEST 문구는 red 속성이 적용된다.

 

 

*생활코딩 사이트 내용 정리.

https://opentutorials.org/module/484/4149

 

반응형

'front > html, css' 카테고리의 다른 글

[CSS] padding 순서  (2) 2019.07.04

td{padding : 1px 2px 3px 4px;}

 

: 상 우 하 좌

시계방향순서

반응형

'front > html, css' 카테고리의 다른 글

[CSS] 적용 우선 순위  (0) 2019.07.10

SELECT 한 결과를 INSERT/UPDATE 하기

 

별도의 sql id 로 select, insert 쿼리를 각각 분리하여 선언하고

select 한 값을 서버에서 다시 insert sql 의 매개변수로 던져주어 DB에 insert 할 경우

WAS서버와 DB 서버간 DB connection 이 두 번 발생 하므로, 

다음과 같은 방법을 이용하자.

 

1. mysql 의 select insert 문법 사용

ex1)

1
2
INSERT INTO sampleTable (col1, col2, col3)
SELECT #{val1}, #{val2}, #{val3}
cs

ex2)

1
2
INSERT INTO sampleTable(col1, col2, col3)    
     SELECT #{val1}, #{val2}, MAX(col3) FROM sampleTable WHERE pkKey = #{pkKey}
cs

 

2. mybatis 의 selectKey 사용

1
2
3
4
5
6
7
8
9
<insert id="sampleSelectInsert" parameterType="java.util.HashMap">
<selectKey keyProperty="selectRs" resultType="integer" order="before">
  SELECT MAX(val)
    FROM sampleTable
   WHERE key = #{value}
</selectKey>
INSERT INTO targetTable (col1, col2, col3)    
                SELECT #{val1}, #{val2}, #{selectRs}
</insert>
cs

* order 옵션을 before 로 사용시 메인 쿼리 (위 예제에서 insert sql) 실행 전에 selectKey sql 실행.

  위의 경우 insert sql 실행 전에 select sql가 실행되어야 selectRs 라는 값을 가져올 수 있으므로 order 를 before로 지정

* order 옵션을 after 로 사용시 메인 쿼리 실행 후에 selectKey sql 이 실행되므로, insert 이후의 seq(시퀀스) max 값을

  return해야 할 때 유용하게 사용 가능

 

※ update 에서 selectkey 를 사용할 경우 mybatis 버전이 낮을 때 에러가 발생하는 경우가 있는 것 같다.

   select + update 를 사용해야 하는 경우 서브쿼리를 사용하자.

 

반응형

현상]
drm:vmw_host_log [vmwgfx]] *ERROR* Failed to send host log message
우분투 실행시 위와 같은 에러메시지 출력 
해결]
환경설정 > 디스플레이 > Graphics Controller 를 VBoxVGA로 변경

참고:
https://unix.stackexchange.com/questions/502540/why-does-drmvmw-host-log-vmwgfx-error-failed-to-send-host-log-message-sh

반응형

1. 변화하는 기능을 별도의 interface로 분리(캡슐화)

2. 각각의 기능(interfaceImple)들이 인터페이스를 구현(implements)

3. 기능을 사용하는 객체(class) 내에서 기능(interface)을 멤버변수로 포함

4. 기능을 사용하는 객체(class) 내에서 기능(interfaceImple)을 주입받는 setter를 선언하여 각각의 객체(class)가 다른 기능(interfaceImple) 을 사용할 수 있게 설계

 

* 무조건적인 상속은 소스의 중복을 야기, 소스 수정시 구현체들의 소스 수정을 야기

 

[ex]

[Shout interface]

소리지르기 비명지르기 기능이 있는 Shout 인터페이스 작성.

1
2
3
4
5
6
7
package design_pattern.strategy;
 
public interface Shout {
    public void yell();
    public void scream();
}
 
cs

 

[Human class]

Shout 인터페이스를 구현한 Human 클래스

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package design_pattern.strategy;
 
public class Human implements Shout{
    
    @Override
    public void yell() {
        System.out.println("으악");
    }
 
    @Override
    public void scream() {
        System.out.println("꺄");
    }
    
}
 
cs

 

[Dog class]

Shout 인터페이스를 구현한 Dog 클래스

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package design_pattern.strategy;
 
public class Dog implements Shout{
 
    @Override
    public void yell() {
        System.out.println("왈");
    }
 
    @Override
    public void scream() {
        System.out.println("왈");
    }
    
}
 
cs

 

[Throat class]

소리지르기, 비명지르기 기능을 갖고 있는 Shout 인터페이스를 멤버변수로 두고 있는 Throat 클래스

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package design_pattern.strategy;
 
public class Throat {
    
    Shout s;
    
    public void setThroat(Shout s) {
        this.s = s;
    }
    
    public void func1() {
        s.yell();
    }
    
    public void func2() {
        s.scream();
    }
    
}
 
cs

 

[Main class(client)]

기능을 사용하는 클라이언트

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package design_pattern.strategy;
 
public class Main {
    public static void main(String args[]) {
        
        Throat throat = new Throat();
        
        throat.setThroat(new Human());
        throat.func1();
        throat.func2();
        
        System.out.println("------------------");
        
        throat.setThroat(new Dog());
        throat.func1();
        throat.func2();
        
    }
}
 
cs

 

[결과]

클라이언트 단에서 setter를 사용하여 클래스(기능)를 변경하여 사용 가능하다.

 

정리가 잘 되어있는 글

참고 도서

 

 

반응형

Head First : Design Patterns

 

자바스럽게 개발하려면 디자인 패턴에 대한 공부는 필수.

아직 1장 스트래터지 패턴 밖에 읽어 보지 못했지만, 이해하기 쉽게그래도 어렵다 정말 잘 쓴 책 같다.

공부하며 각각의 패턴들을 블로그에 따로 정리해보려고 한다.

 

실무에서 다양한 상황에 맞게 각각의 패턴들을 적용하여 개발하려면 내공이 더 쌓여야 가능하겠지만,

일단 각종 API, 라이브러리 및 고수 선배님들의 소스를 파악하는데 큰 도움이 될 듯 하다.

 

2019-06-03 시작.

반응형

'etc. > books' 카테고리의 다른 글

[Book] HTTP 완벽 가이드  (0) 2020.03.17
[Book] 객체지향의 사실과 오해  (0) 2020.02.23
[Book] 소프트웨어 장인  (0) 2020.01.16
[Book] Clean Code (클린 코드)  (0) 2019.12.28
[Book] 프로그래머의 길, 멘토에게 묻다  (0) 2019.11.22

[클라이언트 ip 가져오기]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public static String getIp(HttpServletRequest request){
    String result = null;
    
    result = request.getHeader("X-Forwarded-For");
    
    if (result == null || result.length() == 0 || "unknown".equalsIgnoreCase(result)) {
        result = request.getHeader("Proxy-Client-IP");
    }
    if (result == null || result.length() == 0 || "unknown".equalsIgnoreCase(result)) {
        result = request.getHeader("WL-Proxy-Client-IP");
    }
    if (result == null || result.length() == 0 || "unknown".equalsIgnoreCase(result)) {
        result = request.getHeader("HTTP_CLIENT_IP");
    }
    if (result == null || result.length() == 0 || "unknown".equalsIgnoreCase(result)) {
        result = request.getHeader("HTTP_X_FORWARDED_FOR");
    }
    if (result == null || result.length() == 0 || "unknown".equalsIgnoreCase(result)) {
        result = request.getRemoteAddr();
    }
    
    return result==null?"":result; 
}
 
cs

 

[서버 ip 가져오기]

1
2
3
4
5
6
7
8
9
 public static String getIp(){
    String result = null;
    try {
        result = InetAddress.getLocalHost().getHostAddress();
    } catch (UnknownHostException e) {
        result = "";
    }
   return result; 
}
cs

 

찾다보니 아래와 같은 글도 찾게 되었다.

https://pkgonan.github.io/2018/06/InetAddress-getLocalHost

 

반응형

n개의 row 로 결과가 출력되는 쿼리를 한 줄의 row에 표현하고 싶은 경우, GROUP_CONCAT을 사용한다.

* SELECT GROUP_CONCAT('칼럼명' SEPARATOR '구분문자')

   FROM 테이블명

 

예를 들어,

쿼리 :

1
2
SELECT user_id AS result 
  FROM user_info;
cs

결과 :

result
user1
user2
user3

 

n개의 로우가 출력되는 쿼리에 GROUP_CONCAT 사용시,

쿼리:

1
2
SELECT GROUP_CONCAT(user_id SEPARATOR '^') AS result 
  FROM user_info;
cs

결과 :

result
user1^user2^user3

위처럼 하나의 row에 구분자를 기준으로 모든 row가 붙어서 출력된다.

* GROUP_CONCAT('데이터' ORDER BY '정렬기준' desc SEPARATOR '구분자') 와 같이 order by 사용도 가능.

 

* 응용

1
2
3
4
5
6
7
SELECT COUNT(*)
  FROM sample_table
 WHERE json_data REGEXP (
                         SELECT GROUP_CONCAT(user_id SEPARATOR '|') AS result 
                           FROM user_info
 );
 
cs

적절한 예인지 모르겠으나, 위와 같이 복수개의 문자열에 대한 LIKE 조건을 건 것 처럼 사용 할 수도 있지 않을까..

* jstl 을 사용한 클라이언트단에서의 출력

 

1
2
3
4
5
6
<td>
    <c:set var="user_id" value="${fn:split(list.user_id, '^')}" />
    <c:forEach var="obj" items="${user_id}" varStatus="idx">
    ${obj}<c:if test="${!idx.last}"><br></c:if>
    </c:forEach>
</td>
cs

 

※ ORACLE

LISTAGG(column, 'separator') WITHIN GROUP(ORDER BY column)

1
2
SELECT LISTAGG(user_id, ',') WITHIN GROUP(ORDER BY user_id) AS result
FROM user_info
cs

 

반응형

+ Recent posts