반응형

jQuery를 통해 radio, checkBox의 선택된 값을 가져오거나 강제로 선택되게 하는 방법을 알아보겠습니다.

 

radio 제어

예제로 이러한 smartPhone.html 있다고 가정하고 진행하겠습니다.

<div class="smartPhoneForm">
	<div>스마트폰</div>
	<div>
		통신사 :
		<input type="radio" name="telecom" value="skt"> SKT
		<input type="radio" name="telecom" value="kt"> KT
		<input type="radio" name="telecom" value="lgt"> LGT
	</div>
	<div>
		브랜드 :
		<input type="radio" name="brand" value="samsung"> 삼성
		<input type="radio" name="brand" value="apple"> Apple
		<input type="radio" name="brand" value="lg"> LG
	</div>
</div>

 

선택된 값 가져오기

$("input[name='radio의 name값']:checked").val();
//ex)$("input[name='telecom']:checked").val();

선택된 radio값을 가져옵니다.

 

 

 

값 강제로 선택시키기

$("input[name='radio의 name'][value='선택할 값']").prop("checked", true);
//$("input[name='telecom'][value='skt']").prop("checked", true);

 

 

 


checkbox 제어

checkbox 이벤트를 위한 checkbox.html 예제입니다.

<div class="favoriteBrand">
	<div>좋아하는 브랜드를 선택하세요</div>
	<div>
		<span><input type="checkBox" name="brand" value="acne"> 아크네 스튜디오</span>
		<span><input type="checkBox" name="brand" value="burbbery"> 버버리</span>
		<span><input type="checkBox" name="brand" value="louis_vuitton"> 루이비통</span>
	</div>
	<div>
		<span><input type="checkBox" name="brand" value="gucci"> 구찌</span>
		<span><input type="checkBox" name="brand" value="givenchy"> 지방시</span>
		<span><input type="checkBox" name="brand" value="off_white"> 오프화이트</span>
	</div>
</div>

 

 

체크박스 선택된 개수 가져오기

$("input[name='checkBox의 name값']:checked").length
//$("input[name='brand']:checked").length

선택된 개수

 

체크박스 선택된 값 가져오기

var len = $("input[name='brand']:checked").length;
if(len > 1){ //개수를 체크하고 2개부터는 each함수를 통해 각각 가져온다.
    $("input[name='brand']:checked").each(function(e){
        console.log($(this).val())
    })
}

선택된 데이터 가져오기

 

배열을 만들어 담아도 된다.

var len = $("input[name='brand']:checked").length;
var checkArr = [];
if(len > 1){ //개수를 체크하고 2개부터는 each함수를 통해 각각 가져온다.
    $("input[name='brand']:checked").each(function(e){
        var value = $(this).val();
        checkArr.push(value);        
    })
}

console.log(checkArr);

 

체크박스 강제로 선택시키기

$("input[name='checkBox의 name'][value='선택시킬 value값']").prop("checked", true);
//$("input[name='brand'][value='burbbery']").prop("checked", true);

선택시키기

 

특정 checkbox의 모든값 선택하기

$("input[name='brand']").each(function(e){
    $(this).prop("checked", true);
});
//brand로 설정된 모든 checkbox선택

각각 값에 접근하여 true처리하여 선택한다.

 

모두 선택

 

특정 checkbox의 모든값 해제하기

$("input[name='brand']").each(function(e){
    $(this).prop("checked", false); //false는 해제된다.
})

각각 값에 접근하여 false처리하여 해제한다.

 

반응형
반응형

jQuery 플러그인 중 form태그 내부의 데이터를 편하게 비동기 처리해주는 기능이 있습니다.

바로 jQueryajaxSubmit(); 인데요.

submit이지만 비동기로 처리할 수 있고 동작 이전의 함수처리, 이후의 함수처리도 정의할 수 있는 장점이 있습니다.

사용법은 아래와 같습니다.

 

사용방식

var options = { 
        target:        '#output2',   // target element(s) to be updated with server response 
        beforeSubmit:  showRequest,  // pre-submit callback 
        success:       showResponse  // post-submit callback 

        // other available options: 
        //url:       url         // override for form's 'action' attribute 
        //type:      type        // 'get' or 'post', override for form's 'method' attribute 
        //dataType:  null        // 'xml', 'script', or 'json' (expected server response type) 
        //clearForm: true        // clear all form fields after successful submit 
        //resetForm: true        // reset the form after successful submit 

        // $.ajax options can be used here too, for example: 
        //timeout:   3000 
    }; 

$(formTag).ajaxSubmit(options);

formTag에 ajaxForm() 메소드를 연결하여 사용합니다.

저런 옵션들이 있구나 정도로 보시면 될 것 같고, 좀 더 자세한 사용법을 보겠습니다.

 

 

ajax동작 처리에 따른 결과값 받는 예제(주의점)

 

form.html

<form id="myForm" action="insertBoard.do" method="post"> 
    title: <input type="text" name="title" /> 
    Content: <textarea name="Content"></textarea> 
    <input type="submit" value="Save" /> 
</form>

form.js

<script>
var option = {
    dataType : 'json', //JSON형태로 전달도 가능합니다.
    url: "insertBoard.do",
    success: function(res){
        alert(res.msg); //res Object안에 msg에는 결과 메시지가 담겨있습니다.
    },
    error: function(res){
        alert("에러가 발생했습니다.")
    }
}

$('#myForm').submit(function() { //submit이 발생하면
    $(this).ajaxSubmit(option); //옵션값대로 ajax비동기 동작을 시키고
    return false; //기본 동작인 submit의 동작을 막아 페이지 reload를 막는다.
});
</script> 

 

여기서 주의하실점은 submit기능 동작 정의 후 마지막에 있는 return false;입니다.

이부분을 처리하지 않으면 아무리 success, error옵션을 처리하여도 페이지가 submit이 먹히기 때문에 페이지 리로드 현상이 발생하고 결과값에 따른 동작(alert() 메시지 출력)을 정상적으로 처리 할 수 없습니다.

 

위 예제에서 사용한 option에서 사용한 기능 외에 다른 기능은  공식 API 문서를 통해 더 많은 정보를 볼 수 있습니다.

아래에 공식 API 정보가 있는 URL을 링크해두었으니 참고하시면 더 좋을 것 같습니다.

http://jquery.malsup.com/form/#getting-started

반응형
반응형

https://myhappyman.tistory.com/86

 

Spring - 파일 다운로드 예제 - IE, Chrome (스프링 파일 다운로드 구성)

스프링 프로젝트에서 파일 업로드와 다운로드를 하는 방법을 알아보겠습니다. 이번 포스팅에선 다운로드 예제를 작성했습니다. 추가 메이븐 다운로드 없이 스프링 설정만 하시면 됩니다. 파일 다운로드 web.xml

myhappyman.tistory.com

이전 포스팅 스프링에서 파일 다운로드 받기에 이어 업로드 예제를 진행해보겠습니다.

 

다운로드는 위 URL의 포스팅을 참고해주세요.

 

 

 

파일 다운로드

servlet-context.xml

<!--  spring-upload -->
<beans:bean id="multipartResolver" class="org.springframework.web.multipart.support.StandardServletMultipartResolver" />
<!--  spring-upload -->

multipartResolverbean등록하여 추가합니다.

 

web.xml

파일 전송시 서블릿에서 10메가로 파일제한 처리하였습니다.

<!-- Processes application requests -->
<servlet>
	<servlet-name>appServlet</servlet-name>
	<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
	<init-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>/WEB-INF/spring/servlet-context.xml</param-value>
	</init-param>
	<load-on-startup>1</load-on-startup>
	<!-- fileupload multipart-config maxSize set -->
	<multipart-config>
        <max-file-size>104857600</max-file-size> <!-- 10MB limit -->
        <max-request-size>104857600</max-request-size>
        <file-size-threshold>0</file-size-threshold>
    </multipart-config>
    <!-- fileupload multipart-config -->
</servlet>

 

commonController.java

upload요청이 올 경우 처리할 컨트롤러를 추가합니다.

(common/upload매핑)

import java.io.File;
import java.io.IOException;
import java.util.HashMap;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;

@Controller
@RequestMapping("/common")
public class CommonController{
	
	private static final String FILE_SERVER_PATH = "C:/test";

	@RequestMapping("/upload")
	public String upload(@RequestParam("uploadFile") MultipartFile file, ModelAndView mv, Model model) throws IllegalStateException, IOException {
		if(!file.getOriginalFilename().isEmpty()) {
			file.transferTo(new File(FILE_SERVER_PATH, file.getOriginalFilename()));
			model.addAttribute("msg", "File uploaded successfully.");
		}else {
			model.addAttribute("msg", "Please select a valid mediaFile..");
		}
		
		return "board/board";
	}
}

uploadFile로 요청이 파라미터 값을 확인하고 지정한 경로로 저장합니다.

(C:/test)

 

board.jsp

<%@page import="java.net.URLEncoder"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
    
<!DOCTYPE html>
<html>
  <head>
	<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
	<meta name="description" content="">
	<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
    <title>파일 다운로드</title>
  </head>
  <body>
  	<div class="content">
		<br/><br/>
		<h3>파일 업로드</h3>
		<form action="/common/upload.do" method="post" enctype="multipart/form-data">
		  <table>
		    <tr>
		      <td>Select File</td>
		      <td><input type="file" name="uploadFile" /></td>
		      <td>
		        <button type="submit">Upload</button>
		      </td>
		    </tr>
		  </table>
		</form>
	</div>
  </body>
</html>

ui를 작성합니다.

 

파일을 선택하고 submit버튼을 누르면 action 값에 의해 만들어 놓은 컨트롤러로 전달이 됩니다.

 

 


동작 결과

Upload버튼 클릭 후 정상적으로 서버에 저장되는 모습

 

c:/test에 저장된 모습

반응형
반응형

우분투 톰캣 설치하기

먼저 설치할 톰캣을 다운로드 합니다.

 

https://tomcat.apache.org/download-80.cgi

불러오는 중입니다...

 

8.5 tar.gz으로 다운로드합니다.

 

저는 톰캣 8.5로 진행하겠습니다.

 

8.5 tar버전을 다운로드 후 putty를 통해 우분투 서버에 SSH접속을 합니다.

 

1. 톰캣을 설치할 디렉토리를 만듭니다. (원하는 디렉토리에 설치하시면 됩니다.)

$ sudo mkdir 원하는 디렉토리

ex) $ sudo mkdir /home/psw/tomcat

 

2. ftp를 활용하여 tar파일을 옮겨줍니다. 서버에 존재한다면 mv명령어를 사용해 생성한 디렉토리로 옮겨줍니다.

저는 파일질라를 사용했습니다.

파일질라를 활용한 tar파일 이동

 

3. tar 압축파일을 풀어줍니다.

$ sudo tar xvf apache-tomcat-8.5.51.tar.gz

4번부터는 선택사항입니다. 풀린 디렉토리의 webapps에 war파일을 넣고 bin파일에서 서비스를 기동하시고 사용하셔도 됩니다.

 

4. 풀린 디렉토리명을 편한 방식으로 변경합니다.

$ sudo mv apache-tomcat-8.5.51 tomcat-8.5

저는 tomcat-8.5로 변경했습니다.

 

5. conf/server.xml을 열어 어플리케이션(war파일)이 바라볼 위치를 지정하기 위해 xml파일을 열어줍니다.

$ sudo vi conf/server.xml

 

6. server.xml 하단부 Host부분에 Context를 추가한 후, 저장하고 vi를 종료합니다.

<Context path="" docBase="어플리케이션 위치/어플리케이션 이름" reloadable="false" ></Context>

 

저는 아래와 같이 설정하였습니다.

/home/psw/tomcat/app의 디렉토리를 바라보는 톰캣으로 설정하였습니다.

 

7. 구동시킬 war파일을 server.xml에서 추가한 위치에 옮겨주시고 war의 압축을 풀어줍니다.

저는 war를 미리 풀어놓고 zip또는 tar로 만들어서 압축을 해제하고 있습니다.

풀린 tar(war파일)의 디렉토리 명을 app로 바꿉니다.

 

8. 톰캣을 시작합니다. (.bat파일은 윈도우에서 사용합니다.)

$ sudo ./bin/startup.sh

.sh파일로 시작과 종료를 제어합니다.

shutdonw.sh 는 톰캣을 종료할 때, 사용합니다.

 

9. 톰캣 프로세스가 정상적으로 동작 중인지 확인합니다.

$ ps aux | grep tomcat

 

 

톰캣 서비스 등록하기

톰캣을 종료 시작할때 매번 /tomcat/bin으로 가서 명령을 날리는게 번거롭거나 서버가 재시작되어도 자동으로 톰캣이 올라오도록 하려면 톰캣을 서비스로 등록하시면 됩니다.

 

1. 서비스등록을 위해 파일을 생성합니다. (tomcat으로 서비스를 등록하겠습니다.)

$ sudo vi /etc/init.d/tomcat

 

2. vi창이 열리면 아래의 쉘명령문을 입력합니다.

#!/bin/bash

### BEGIN INIT INFO
# Provides:    tomcat
# Required-Start:  $remote_fs $syslog
# Required-Stop:   $remote_fs $syslog
# Default-Start:   2 3 4 5
# Default-Stop:    0 1 6
# Short-Description: auto start Tomcat server
# Description: start web server
### END INIT INFO

export CATALINA_HOME=/home/psw/tomcat/tomcat-8.5
case $1 in
    start)
        echo "start tomcat: "
	sh $CATALINA_HOME/bin/startup.sh
        ;;
    stop)
        echo "shutdown tomcat: "
        sh $CATALINA_HOME/bin/shutdown.sh
        ;;
    restart)
        echo "restart tomcat: "
        sh $CATALINA_HOME/bin/shutdown.sh;
        sh $CATALINA_HOME/bin/startup.sh
        ;;
    *)
        echo "usage: service tomcat {start|stop|restart}"
        exit 1
esac
exit 0

여기서 주의하실 곳은 CATALINA_HOME 변수값을 톰캣 위치를 정확하게 지정해셔야 합니다.

 

톰캣 서비스 쉘 스크립트

저는 아까 톰캣을 생성한 위치로 지정했습니다.

 

3. 생성한 tomcat파일 권한을 변경합니다.

$ sudo chmod 755 /etc/init.d/tomcat

 

4. 서비스를 업데이트 합니다.

$ sudo update-rc.d tomcat defaults

 

5. 톰캣 서비스를 확인합니다.

$ sudo service tomcat status

 

6. 이제 서비스가 먹히는지 확인해보겠습니다.

$ service tomcat start -- 톰캣이 종료된 상태라면 start로 동작시킵니다.

$ service tomcat stop -- 톰캣이 시작된 상태라면 stop으로 종료시킵니다.

$ service tomcat restart -- 톰캣을 재시작하려면 restart 시킵니다.

 

이 후에는 우분투서버가 재부팅되어도 서비스가 동작중 인것을 볼 수 있습니다.

반응형
반응형

https://opentutorials.org/module/516/5558

 

리눅스에 Java 다운로드해서 설치하기 - Java

환경 본 수업은 리눅스 배포판 중의 하나인 Ubuntu를 기준으로 진행한다. 자바를 다운로드 해서 설치하기 1. 운영체제의 종류를 파악한다.  file /sbin/init 2. 자바가 이미 설치 되어 있는지 확인한다. java -version 위의 명령의 실행 결과 자바의 버전이 출력된다면 그냥 이것을 사용할지 새로운 버전을 설치할지 선택한다. 아마 오래된 운영체제가 아니라면 본 수업을 진행하기 위해서 새로운 자바를 설치할 필요는 없을 것이다. 3. 기존

opentutorials.org

생활코딩님의 강좌를 참고해서 작성하였습니다.

 


JDK 1.8 tar 다운로드

우분투에 자바 1.8 jdk를 압축파일을 다운받아서 설치해보겠습니다.

 

SSH접속하여 설치한다고 생각하고 먼저 1.8 jdk부터 다운받도록 합니다.

tar 압축파일로 설치를 할 예정이므로 tar로 다운로드합니다.

 

 

https://www.oracle.com/java/technologies/javase/javase-jdk8-downloads.html

자신의 OS에 알맞는 버전으로 다운로드합니다.

 

64비트 리눅스버전으로 다운로드했습니다.

 

이제 Ubuntu서버에 붙어서 확인하도록 하겠습니다. 저는 putty를 활용했습니다.

 


우분투 접근하여 설정하기

서버에 접근하시면 기본적으로 자바가 설치되어 있을겁니다. openjdk~~

 

1. 자바가 설치되어있다면 설정된 버전이 나올 겁니다.

$ java -version

 

2. 이미 설치되어 있던 자바(openJdk)를 삭제하도록 합니다. (1.8로 설치예정)

$ sudo apt-get purge openjdk-\*

 

3. 삭제가 완료되면 이제 압축을 풀 디렉토리를 생성합니다.(mkdir - 디렉토리 생성)

$ sudo mkdir -p /usr/local/java

 

4. 생성한 디렉토리로 먼저 오라클에서 다운받은 자바 tar압축 파일을 옮겨줍니다.

> 저는 파일질라를 이용해서 옮겼습니다. 다른 디렉토리에 있다면 mv명령어를 통해 옮겨주도록 합니다.

파일질라로 압축파일 이동

 

5. 압축을 풀어줍니다. (tar xvf)

$ sudo tar xvf /usr/local/java/jdk-8u241-linux-x64.tar.gz

압축이 풀린 모습

 

6. 환경설정을 진행합니다. (/etc/profile)

$ sudo vi /etc/profile

 

7. 열린 vi창 맨 밑에 자바 환경변수를 등록하고 저장합니다.

export JAVA_HOME=$(readlink -f /usr/local/java | sed "s:bin/java::")

 

vi가 처음이신분들은 처음에 i를 입력하면 편집모드로 변경됩니다.

화살표 아래를 눌러서 맨 밑으로 오시고 위 export ~를 입력하신다음 esc 키를 입력 후

:wq! 를 입력하여 저장 종료를 합니다.

 

8. 자바 명령어를 등록합니다.

$ sudo update-alternatives --install "/usr/bin/java" "java" "/usr/local/java/jdk1.8.0_241/bin/java" 1;
$ sudo update-alternatives --install "/usr/bin/javac" "javac" "/usr/local/java/jdk1.8.0_241/bin/javac" 1;
$ sudo update-alternatives --install "/usr/bin/javaws" "javaws" "/usr/local/java/jdk1.8.0_241/bin/javaws" 1;

$ sudo update-alternatives --set java /usr/local/java/jdk1.8.0_241/bin/java;
$ sudo update-alternatives --set javac /usr/local/java/jdk1.8.0_241/bin/javac;
$ sudo update-alternatives --set javaws /usr/local/java/jdk1.8.0_241/bin/javaws;

 

9. 이제 자바 버전을 확인해봅니다.

$ java -version

1.8.0_241로 변경 설정된 모습

 

여기서 정상적으로 안보이는 경우 SSH접속을 다시 해보시고 명령어를 입력해보시고 그래도 동일하다면 위에서부터 중간에 경로가 틀린게 없는지 확인해주세요.

반응형
반응형

스프링 프로젝트에서 파일 업로드와 다운로드를 하는 방법을 알아보겠습니다.

 

이번 포스팅에선 다운로드 예제를 작성했습니다.

 

추가 메이븐 다운로드 없이 스프링 설정만 하시면 됩니다.

 

 

 

파일 다운로드

web.xml

<!-- Filter -->
<filter>
	<filter-name>encodingFilter</filter-name>
	<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
	<init-param>
		<param-name>encoding</param-name>
		<param-value>utf-8</param-value>
	</init-param>
</filter>
<filter-mapping>
	<filter-name>encodingFilter</filter-name>
	<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- Filter -->


<!-- Processes application requests -->
<servlet>
	<servlet-name>appServlet</servlet-name>
	<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
	<init-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>/WEB-INF/spring/servlet-context.xml</param-value>
	</init-param>
	<load-on-startup>1</load-on-startup>
</servlet>

먼저 web.xml에서 필터 설정과 DispatcherServlet상태를 확인하겠습니다.

필터를 통해 utf-8 인코딩 처리를 하였고 servlet-context.xml의 위치는 /WEB-INF/spring/servlet-context.xml 로 지정하였습니다.

 

servel-context.xml

<!-- spring-donwload bean -->
<beans:bean class="org.springframework.web.servlet.view.BeanNameViewResolver">
    <beans:property name="order" value="0" />
</beans:bean>
<beans:bean id="downloadView" class="com.psw.myapp.utils.DownloadView" />
<!-- /spring-donwload bean -->

<!-- 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="1" />
</beans:bean>

InternalResourceViewResolverorder순서를 1로 변경하였습니다.

DonwloadView 자바파일에서 다운로드 처리를 진행할 것이며 bean등록 처리를 해기 위해 BeanNameViewResolver를 사용했습니다.

serlet-context.xml 위치

 

 

CommonController.java

import java.io.File;
import java.io.IOException;
import java.util.HashMap;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;

@Controller
@RequestMapping("/common")
public class CommonController{
	
	private static final String FILE_SERVER_PATH = "C:/test";

	@RequestMapping("/download")
	public ModelAndView download(@RequestParam HashMap<Object, Object> params, ModelAndView mv) {
		String fileName = (String) params.get("fileName");
		String fullPath = FILE_SERVER_PATH + "/" + fileName;
		File file = new File(fullPath);
		
		mv.setViewName("downloadView");
		mv.addObject("downloadFile", file);
		return mv;
	}
}

모든 파일은 C:/test에 있다고 가정하였습니다.

파일은 전달받은 fileName 파라미터값을 통해 파일을 세팅합니다.

downloadFile에 다운로드할 파일을 처리하고 bean등록을한 downloadView로 넘길것입니다.

 

 

DownloadView.java

import java.io.File;
import java.io.FileInputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.Map;

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

import org.springframework.util.FileCopyUtils;
import org.springframework.web.servlet.view.AbstractView;

public class DownloadView extends AbstractView {

	@Override
	protected void renderMergedOutputModel(Map<String, Object> model, HttpServletRequest request, HttpServletResponse response)
			throws Exception {

		File file = (File)model.get("downloadFile");
        if(file != null) {
            String fileName = null;
            String userAgent = request.getHeader("User-Agent");
            
            if(userAgent.indexOf("MSIE") > -1 || userAgent.indexOf("Trident") > -1){
                fileName = URLEncoder.encode(file.getName(), "utf-8").replaceAll("\\+", "%20");;
            }else if(userAgent.indexOf("Chrome") > -1) {
            	StringBuffer sb = new StringBuffer();
            	for(int i=0; i<file.getName().length(); i++) {
            		char c = file.getName().charAt(i);
            		if(c > '~') {
            			sb.append(URLEncoder.encode(""+c, "UTF-8"));
            		}else {
            			sb.append(c);
            		}
            	}
            	fileName = sb.toString();
            }else {
            	fileName = new String(file.getName().getBytes("utf-8"));
            }
            response.setContentType(getContentType());
            response.setContentLength((int)file.length());
            response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\";");
            response.setHeader("Content-Transfer-Encoding", "binary");
            
            OutputStream out = response.getOutputStream();
            FileInputStream fis = null;
            try {
                fis = new FileInputStream(file);
                FileCopyUtils.copy(fis, out);
            } catch(Exception e){
                e.printStackTrace();
            }finally{
                if(fis != null){
                    try{
                        fis.close();
                    }catch(Exception e){
                    	e.printStackTrace();
                    }
                }
                
                if(out != null) {
                	out.flush();
                }
            }
            
        }
	}
}

donwloadView는 AbstractView를 상속받아 사용합니다.

AbstractViewView구현을 위한 추상클래스로 컨트롤러가 반환한 모델과 병합되는 뷰입니다.

 

앞서 CommonController.java에서 세팅한 file인 downloadFile을 받아서 ie인지 체크 후 헤더 세팅과 OutputStream을 통해 파일을 출력합니다.

 

또한, 주의사항으로 브라우저마다의 인코딩이 달라서 User-Agent를 통해 접속한 브라우저를 체크하고 출력해줄 파일명을 만들때 인코딩 방식을 다르게 해야합니다. IE의 경우엔 11버전부턴 식별문자가 Trident로 변경되어 MSIE와 같이 조건문에 추가하였습니다.

 

controller와 downloadView 위치

 

이제 다운로드가 정상적으로 되는지 테스트 해보겠습니다.

전 board.jsp라는곳에서 처리할 예정이므로 컨트롤러와 jsp를 추가로 만들겠습니다.

 

 

BoardController.java

import java.util.HashMap;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

@Controller
@RequestMapping("/board")
public class BoardController {
	
	@RequestMapping("/board.do")
	public ModelAndView board(@RequestParam HashMap<Object, Object> params, ModelAndView mv) {
		mv.setViewName("board/board");
		return mv;
	}
}

board/board.do url로 요청이 들어오면 board/board.jsp를 호출하도록 컨트롤러 설정을 했습니다.

 

 

board.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
    
<!DOCTYPE html>
<html>
  <head>
	<meta charset="UTF-8">
	<meta name="description" content="">
	<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
    <title>파일 다운로드</title>
  </head>
  <body>
  	<div class="content">
		<br/><br/>
		<h3>파일 다운로드</h3>
		<a href="/common/download.do?fileName=이미지예제.jpg">download</a>
	</div>
  </body>
  
</html>

board.jsp

이제 마지막으로 WEB-INF/views/board 디렉토리와 board.jsp파일을 만들고 board.jsp를 작성했습니다.

 

board.jsp

a태그를 클릭하시면 CommonContorller에 요청을 했다가 DownloadView를 통해 다운로드가 되는 것을 볼 수 있습니다.

 

 

 

c:/test/이미지예제.jpg

 

다운로드된 jpg

 

 

 

IE 인코딩 에러

 

예제를 그대로 진행하면 한글명때문에 익스에서 하시는분들은 에러가 발생할 수 있습니다.

IE 예외처리 인코딩을 위해 jsp부분을 수정해주시면 됩니다.

 

 

board.jsp

<%@page import="java.net.URLEncoder"%>

...

<a href="/common/download.do?fileName=<%=URLEncoder.encode("이미지예제.jpg")%>">download</a>

URLEncoder를 추가 import해주시고 파라미터부분을 인코딩하여 넘기시면 IE에서도 되는 걸 확인 할 수 있습니다.

 

IE에서 정상 다운로드 처리

 

 

 

파일 업로드는 아래 URL에서 진행됩니다.

https://myhappyman.tistory.com/89

 

Spring - 파일 업로드 예제

https://myhappyman.tistory.com/86 Spring - 파일 다운로드 예제 - IE, Chrome (스프링 파일 다운로드 구성) 스프링 프로젝트에서 파일 업로드와 다운로드를 하는 방법을 알아보겠습니다. 이번 포스팅에선 다운로..

myhappyman.tistory.com

 

반응형
반응형

JAVA8을 공부하면서 참 편하면서 활용도가 높다고 생각된 것 중 가장 크게 와닿은 함수적 인터페이스에 대해 알아보겠습니다.

 

public interface Function<T, R> { … }

Function 인터페이스는 파라미터 타입이 2개하나는 인자로, 하나는 리턴값으로 사용합니다. 또한, apply() 추상 메소드를 상속 받아 사용하고 기본 메소드로 andThen(), compose() 메소드를 사용합니다.

 

처음으로 사용 예시를 봤던 방식이 널 체크하는 예제였습니다.

보면서 가독성 면이나 사용법을 보면서 "와 편하다..."라고 생각이 되었습니다.

매번 com.~.~.utils에 있는 수많은 문자열 처리 함수들이 한줄 한줄로 처리 할 수 있고, 구분도 명확하게 느껴졌습니다.

 

바로 소스를 보겠습니다.

 

 

 


NVL 널체크

import java.util.function.Function;

public class FunctionC {
	
	final static Function<Object, String> NVL = str -> str != null && !((String) str).trim().equals("") ? str.toString() : "";
	
	public static void main(String[] args) {
		System.out.println("일반 함수 >" + NVL(null)); //일반 문자열 함수
		System.out.println("함수형 인터페이스" + NVL.apply(null)); //함수형 인터페이스
		
		System.out.println("일반 함수 >" + NVL("TEST"));
		System.out.println("함수형 인터페이스" + NVL.apply("TEST"));
		
		System.out.println("일반 함수 >" + NVL(""));
		System.out.println("함수형 인터페이스" + NVL.apply(""));
	}
	
	public static String NVL(String str) {
		String res = "";
		if(str != null && !str.trim().equals("")) {
			res = str;
		}
		return res;
	}
}

일반 함수와 함수형 인터페이스의 사용 비교

일반 함수 NVL과 함수형 인터페이스 NVL을 통해 비교를 해봤습니다.

그렇게 어렵지 않은 문자열이 null인지 공백값인지 확인 후 return값을 출력하는 예제입니다.

 

둘다 동일하게 동작하는 것을 볼 수 있습니다.

 

사용법에 차이가 있다면 함수형 인터페이스 Functionapply() 추상메소드를 상속받습니다.

차이점으로 코딩 줄 수의 차이는 조금 애매한 것 같습니다. 똑같이 선언하고 return에서 삼항연산자 처리를 하면 동일하기 때문입니다.

 

다른 예제를 보겠습니다.

 

 

 


문자열 숫자를 정수형으로 반환

import java.util.function.Function;

public class FunctionC {
	
	final static Function<String, Integer> toInt = str -> str.length() == 0 ? 0 : Integer.parseInt(str);
	
	public static void main(String[] args) {
		System.out.println(toInt.apply("555"));
	}
}

변환

 

문자열 숫자 데이터를 정수형으로 반환하는 예제입니다.

 

문제없이 동작하는것을 볼 수 있습니다. 하지만 문자열에는 null데이터가 존재합니다.

그럼 함수형 인터페이스에 null체크 로직을 삼항연산자 앞부분에 추가할까요? 그렇게 해도 상관은 없지만 함수형 인터페이스는 연결해서 사용이 가능합니다.

 

바로 아래처럼 말이죠.

 

 


Function.andThen()

import java.util.function.Function;

public class FunctionC {
	
	final static Function<Object, String> NVL = str -> str != null && !((String) str).trim().equals("") ? str.toString() : "";
	final static Function<String, Integer> toInt = str -> str.length() == 0 ? 0 : Integer.parseInt(str);
	
	public static void main(String[] args) {
		System.out.println(toInt.apply("555"));
		System.out.println(NVL.andThen(toInt).apply(null));
	}
}

null 데이터는 0이 나옴

null을 넣었지만 널포인트 에러가 아닌 0이 나온 것을 볼 수 있습니다.

바로 전 예제에서 만든 NVL 함수형 인터페이스를 통해 먼저 널체크를 하고 andThen() 메소드를 통해 문자열을 숫자로 변환하는 함수형 인터페이스를 연결해줍니다.

 

하지만 사용하면서 주의할 점이 있습니다.

당연한거지만 연결하는 순서도 차례대로 진행해야 합니다. 널체크를 먼저 하고 사용하고자 하는 함수형 인터페이스를 사용해야 합니다.

 

 

 

 

andThen()메소드의 잘 못된 연결방식? compose() !

import java.util.function.Function;

public class FunctionC {
	
	final static Function<Object, String> NVL = str -> str != null && !((String) str).trim().equals("") ? str.toString() : "";
	
	final static Function<Object, String> UPPERCASE = str -> ((String) str).toUpperCase();
	
	public static void main(String[] args) {
		System.out.println("andThen >" + NVL.andThen(UPPERCASE).apply("hello world!!!")); //잘 못된 문법 NULL을 먼저 체크해야 합니다.
		
		System.out.println();
		System.out.println();
		System.out.println();
		
		System.out.println("잘 못 된 문법 >" + UPPERCASE.andThen(NVL).apply(null)); //잘 못된 문법 NULL을 먼저 체크해야 합니다.
	}
}

연결 순서를 잘 못 연결하면 원하는 결과를 얻지 못한다.

 

또 다른 예제입니다. 이번엔 널체크와 문자열을 대문자로 변경하는 toUpperCase() 메소드를 연결하였습니다.

널체크를 먼저한 경우엔 문제가 없지만 아래처럼 강제로 null데이터를 꺼꾸로 입력한 경우엔 null데이터를 가지고 대문자로 변환을 하다보니 null 예외처리가 발생하는 것을 볼 수 있습니다.

 

하지만, 동작 순서를 반대로 하고 싶은 경우도 있을 것 같습니다.

처음에 시작할때 기본 메소드로 andThen()compose()가 존재한다고 했는데 여기서 compose() 메소드를 사용하면 정상적으로 동작이 됩니다.

 

 

 

 

compose()

System.out.println("잘 못 된 문법 >" + UPPERCASE.compose(NVL).apply("hello world~~~")); //잘 못된 문법 NULL을 먼저 체크해야 합니다.

compose()는 동작한다.

 

기본 null에러 발생하던부분의 andThen()compose()로만 변경해주었습니다.

andThen()의 방식이 1 -> 2 라면 compose()는 2 -> 1로 동작합니다.

즉, 내부에 있는 NVL 인터페이스가 먼저 동작하고 UPPERCASE 인터페이스가 동작해서 정상적으로 hello world~~~이 대문자로 변경되었습니다.

 

반응형
반응형

DAO부분에서Mybatis사용시 발생하는 에러로 sqlsession.selectList("NameSpace.select", param)형태의 return List로 받아야 할 값을 Map이나 String, Integer와 같은 형이 맞지 않는 형태로 return할때 발생하는 에러이다.

 

 

 

resultType="hashMap"

mapper의 리턴타입을 hashMap으로 변경한다. 

<mapper namespace="NameSpace">
	<select id="select" parameterType="hashMap" resultType="hashMap">
		...
	</select>
</mapper>

 

 

 

resultMap="resultMap의 ID"

또는 VO형태로 받아야 하는 경우 상단에 resultMap을 정의하고 return 처리한다.

<mapper namespace="NameSpace">
  <resultMap type="com.psw.web.resultVO" id="resultVo">
    <result property="id"             column="id"/>
    <result property="timestamp"      column="timestamp"/>
    <result property="account"        column="account"/>
    <result property="result_date"    column="result_date"/>
    <result property="filename"       column="filename"/>
  </resultMap>

  <select id="selectTable" parameterType="java.util.Map" resultMap="resultVo">
      ...
  </select>
</mapper>
반응형