Local 디렉토리에 있는 파일을 다운로드하는 예제 소스


** 컨트롤러

@RequestMapping(value="/demo/download.do")

public void download(

 HttpServletRequest request

, HttpServletResponse response) throws Exception {

// 다운로드 파일 정보 조회

String downloadFilePath = "/tmp/original.jpg";

InputStream inputStream = getFileInputStream(downloadFilePath);

// HTTP 다운로드 프로토콜 정의

ServletContext context = request.getSession().getServletContext();

int contentLengt = inputStream.available();

setHttpDowndloadProtocol(context, response , downloadFilePath, contentLengt);

// 다운로드 파일 쓰기

OutputStream outStream = response.getOutputStream();

writeToResponse(inputStream, outStream);


inputStream.close();

outStream.close();

}



- 다운로드 파일 조회

private InputStream getFileInputStream(String downloadFilePath) throws FileNotFoundException {

File downloadFile = new File(downloadFilePath);

return new FileInputStream(downloadFile);

}


- HTTP 다운로드 프로토콜 정의

private void setHttpDowndloadProtocol(

 ServletContext context

, HttpServletResponse response

, String downloadFilePath

, int contentLength) {

String mimeType = getMimeType(context, downloadFilePath);

response.setContentType(mimeType);

response.setContentLength(contentLength);


String contentDisposition = String.format("attachment; filename=\"%s\"", "download.jpg");

response.setHeader("Content-Disposition", contentDisposition);

}


private String getMimeType(

  ServletContext context

, String downloadFilePath) {

String mimeType = context.getMimeType(downloadFilePath);

if (mimeType == null) {

  mimeType = "application/octet-stream";

}

return mimeType;

}


- 다운로드 파일 쓰기

private void writeToResponse(

  InputStream inputStream

, OutputStream outStream) throws IOException {

byte[] buffer = new byte[1024];

int bytesRead = -1;


while ((bytesRead = inputStream.read(buffer)) != -1) {

  outStream.write(buffer, 0, bytesRead);

}

}


Posted by 짱가쟁이
2014. 12. 22. 13:31




Spring MVC

스프링에서 지원하는 서블릿 기반의 MVC 프레임워크


DispatcherServlet(Front Controller)

프레젠테이션 계층의 제일 앞단에서 서버로 들어오는 모든 요청을 먼저 받아서 처리함. 클라이언트가 보낸 요청을 받아서 공통적인 작업을 먼저 수행한 후에 적절한 세부 컨트롤러로 작업을 위임해주고, 클라이언트에게 보낼 뷰를 선택해서 최종 결과를 생성하여 응답을 전송함


HandlerMapping

클라이언트의 요청 URL과 매핑되는 컨트롤러를 결정함

Controller

URL과 매핑되는 세부 컨트롤러로 요청을 처리한 뒤, 결과를 DispatcherServelet에게 전달


ModelAndView

컨트롤러가 처리한 결과 정보 및 뷰를 선택한 정보를 담음


ViewResolver

컨트롤러의 처리 결과를 생성할 뷰를 결정

View

컨트롤러의 처리 결과 화면을 생성. JSP 또는 Velocity 템플릿 파일 등을 뷰로 사용



Posted by 짱가쟁이



Servlet

웹 페이지를 동적으로 생성하는 서버측 프로그램을 말하며, 흔히 서블릿이라 불린다.


서버측 프로그램

서버에서 실행되는 작은 프로그램.

Ex> JSP -> 컴파일 -> 서블릿 변환 -> 서버에서 구동


Container

서블릿의 Lifecycle을 관장하는 소프트웨어(모듈)을 "컨테이너"라 불린다.


Lifecycle

컨테이너는 클라이언트의 요청을 받으면 URL에 매핑하는 서블릿을 생성하고 생성된 서블릿은 정의된 비즈니스를 수행하고 소멸한다.


Role of Container

Communication 지원

서블릿과 웹서버의 통신을 담당. 컨테이너가 없다고 가정하면, 웹서버의 요청을 대기하는 리스너를 만들어 해당 요청(URL)과 서블릿을 매핑해야 하는 과정을 거쳐야 함. 컨테이너는 이런 복잡한 통신 기능을 API로 제공함.

- Lifecycle 관리

클라이언트의 요청(URL)이 들어오면 해당 URL과 매핑되는 서블릿의 인스턴스를 생성하고, 초기화 메소드를 호출. 서블릿의 수명이 다하면 적절하게 가비지 컬렉션을 수행한다. 즉 서블릿의 탄생과 죽음을 관리한다.


- Multi-Thread 지원

컨테이너는 클라이언트의 요청이 들어오면 서블릿을 처리하기 위한 새로운 쓰레드를 생성하고, 작업이 끝난 쓰레드는 반환하여 다중 요청에 대한 안정적인 동시성을 지원함


- 선언적 보안관리(??)


- JSP 지원





Posted by 짱가쟁이


$( "#startDt, #endDt" ).datepicker({

                 dateFormat: 'yy-mm-dd'

               , changeMonth: true

               , changeYear: true

               , nextText: '다음 '

               , prevText: '이전 '

               , showButtonPanel: true

               , beforeShow: function (input) {

                     setTimeout(function() {

                            var nextYearBtn = $("<button>이후 </button>");

                                 nextYearBtn.unbind("click").bind("click", function() {

                             $.datepicker._adjustDate($(input), +1, 'Y');

                                 });

                                 var preYearBtn = $("<button>이전 </button>");

                                 preYearBtn.unbind("click").bind("click", function() {

                             $.datepicker._adjustDate($(input), -1, 'Y');

                                 });

                                

                        $(".ui-datepicker-buttonpane")

                           .html('')

                           .append(nextYearBtn)

                           .append(preYearBtn);

                       }, 1);

               }

                    , onChangeMonthYear:function(y, m, i){                               

                           setTimeout(function() {

                                 var nextYearBtn = $("<button>이후 </button>");

                                 nextYearBtn.unbind("click").bind("click", function() {

                             $.datepicker._adjustDate($(i.input), +1, 'Y');

                                 });

                                

                                 var preYearBtn = $("<button>이전 </button>");

                                 preYearBtn.unbind("click").bind("click", function() {

                             $.datepicker._adjustDate($(i.input), -1, 'Y');

                                 });

                                

                        $(".ui-datepicker-buttonpane")

                           .html('')

                           .append(nextYearBtn)

                           .append(preYearBtn);

                       }, 1);

                 }

             });//.val(getFormatDate(new Date())) defaultDate : $(this).val()


Posted by 짱가쟁이

window.open('','_self').close();

Posted by 짱가쟁이

<script type="text/javascript" src="/js/jquery.js"></script>
<script type="text/javascript" src="/js/jQuery.dPassword.js"></script>
<script type="text/javascript">
  $(document).ready( function() {
    $('input:password').dPassword();
  });
</script>


<script type="text/javascript" src="/js/jquery.js"></script>
<script type="text/javascript" src="/js/jQuery.dPassword.js"></script>
<script type="text/javascript">
  $(document).ready( function() {
    $('input:password').dPassword({
      duration: 2000,
      prefix: 'my_'
    });
  });
</script>






Posted by 짱가쟁이

몇년만에 웹을 만지는 느낌은.. 너 누구니??

우선 서비스 서버 작업 후 API 테스트 페이지가 필요하더라.. 콘솔에서 테스트를 하면 편하고 좋기는 하지만.. 가끔 외부에서 모바일 기기로 테스트 하려니.. 좀 난감한 경우가 생기더라.. 어쩔수 없이 웹으로 작업하던중.. 예전에 들었던 jquery라는 넘을 사용하고 싶다라는 욕구 때문에 .. 쩌ㅃ~

우선 결론은 사용해보니.. "편하다"

Example.
Script
   function comboChange() {
        var options = {
                   success     : showInitResponse,
                   url              : "/path/test.action",
                   contentType : "application/x-www-form-urlencoded;charset=UTF-8",
                   type           : "post", /* get, post */
                   dataType    : "html" /* xml, html, script, json */
               };
         $('#INIT').ajaxSubmit(options);
    }

    // post-submit callback
    function showInitResponse(responseText, statusText)  {
           //submit후 작업부분
         document.getElementById('result').innerHTML = responseText;
    }

result 에 삽입하고 싶은 페이지 url을 설정하고 ajaxSubmit() 을 사용하면 땡.

Html
<s:form name="INIT" action="INIT" theme="simple" method="post">
        <s:select id="apiId" name="apiId" list="#{'INBO01':'INBO01', 'INTC02':'INTC02'}" onchange="javascript:comboChange();"></s:select>           
</s:form>

<div id="result"/>

콤보박스가 API명을 선택하면 해당 API 테스트 페이지를 삽입한다. 뭐.. 테스트 페이지는 Reflect를 사용해서 한방에 끝내기는 했지만... Reflect 단점상.. 가독성이 떨어진다. ㅡㅡ;;

우선.. 하도 많은 사이트를 참조해서 출처를 올리려니.. 기억이 가물가물..

Posted by 짱가쟁이
서버에 접근하기 힘들고.. 로그는 봐야 할때.. Tomcat web root 폴더에 log 파일을 생성하게 만들고..

본인은 D:\www\log 경로에 로그파일을 생성했다.


C:\Program Files\Apache Software Foundation\Tomcat 6.0\conf\web.xml 파일을 조금 수정하면 땡.

<init-param>
            <param-name>listings</param-name>
            <param-value>true</param-value>
</init-param>

fasle 를 true로 변경하면.. 디렉토리 구조로 로그파일에 접근이 가능하다. 뭐.. 다른 보안상의 문제점이 있기는 하것지만.. 로그를 외부에서 꼭 봐야 한다면.. 요넘도 나쁘지는 않을 듯..


Posted by 짱가쟁이
우선 이클립스에서 Dynamic web project 로 프로젝트를 생성하고 Server를 tomcat 6.0 으로 개발을 진행하던중..

꼭 프로젝트 경로에 있는 넘만 실행시킬 필요가 있을까?? 실 운영환경이랑 비슷하게 개발할 수 없을까 하는 생각에 이것저것 찾아보게됨..


자.. 그러면 실제로 변경해야 할 부분은 Servers/server.xml 이넘을 수정하면 된다.

<Host appBase="D:/www" autoDeploy="true" name="localhost" unpackWARs="true" xmlNamespaceAware="false" xmlValidation="false">

<Context docBase="프로젝트명(폴더명)" path="" reloadable="false"  /></Host>

위 빨강이를 보면 D 드라이브에 www 폴더를 생성하고 그넘으로 경로를 잡아준다.

뭐.. 위에 넘만 설정하고. "D:/www/프로젝트명" 경로에 실제 프로젝트에서 구동시킬 설정파일과 class 파일들을 복사만 하면 땡임.




위 설정된 넘으로 테스트 하던 중.. 웹 서비스가 두번 로딩되는 문제가 발생 됨.

뭐.. 서비스 하는데는 문제가 되지는 않지만.. 찝찝함을 견딜 수가 없다는 ....

여기저기 검색을 하다보니.. 스프링에 쿼즈로 작업한 넘을 톰켓에 올려서 구동하는 사람이 같은 문제로 고생한 글을 찾을 수 있었다. 뭐 그냥반 글을 보면 위 Host 쪽에서 설정한 넘으로 한번 로딩하고.. Context 에서 한번 더 로딩하기 때문에 문제가 발생한다고 한다.  뭐 해결책은 Context를 삭제하면 한번만 로딩된다. 쩌ㅃ~



Posted by 짱가쟁이
JSON (JavaScript Object Notation)
- 가벼운 데이터 변환 포멧

Sample data
{"result":"success", "value":"0", "list":[...]}


Simple Code
import org.codehaus.jettison.json.JSONObject;
import org.apache.cxf.helpers.IOUtils;

JSONObject json = new JSONObject(IOUtils.toString(in));
System.out.println(json.getString("result"));
System.out.println(json.getString("value"));

List Code
JSONObject jsonObject = new JSONObject(IOUtils.toString(in));
JSONArray jsonArray = jsonObject .getJSONArray("list");

for(int i = 0 ; i < jsonArray .length() ; i++){
    JSONObject listJson= jsonArray .getJSONObject(i);
    System.out.println(listJson.getString("result"));
    System.out.println(listJson.getString("value"));
}



Posted by 짱가쟁이
이전버튼 1 2 이전버튼