스프링  컨트롤러에서 자바 스크립트 추가 하기

PrintWriter 이걸 사용하면 되는데 요즘 UTF-8로 설정을 많이 해서 프로젝트 따라 자동으로 되는지 알았는데 설정을

해줘야 한다. 

		response.setCharacterEncoding("UTF-8");
		response.setContentType("text/html; charset=UTF-8");
		PrintWriter out = null;
		try {
			out = response.getWriter();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

UTF-8로 해서 생성을 한다. 

스크립트를 작성하면 페이지이동하면서 실행이 된다.

            out.println("<script type='text/javascript'>");
			  out.println("alert('메인 홈으로 이동합니다.');"); 
			  out.println("window.location.href='"+request.getContextPath()+"/index';");
			  out.println("</script>");
			  out.flush();
			  return return_url_str;

 

블로그 이미지

은호아빠

여행, 맛집, 일상, 프로그래밍, 개발자, 윈도우, 웹, jsp, spring, db, mysql, oracle, c#

,

스프링 게시판 만들기 2

저장을 해야 해요. 스크립트를 만들어요. 

function  save_note()
{
	if(check_save())
	{
		return true;
	}
	$("#a_save_btn").prop("disabled", true);
	var url;
	var sql_state_value;
	if($("#i_idx").val()=='')
	{
		url = '/board/save';
		sql_state_value = 'insert';
	}
	else
	{
		url = '/board/save';
		sql_state_value = 'update';
	}	
	
	var postData = {};
    postData["sql_state"] = sql_state_value;
    postData["idx"] = $("#i_idx").val()
    postData["title"] = $("#title").val()
	postData["mdate"] = $("#mdate").val()
	postData["mt_content"] = $('#summernote').summernote('code')
	postData["uuid"] =  $("#i_uuid").val()
	postData["division"] = $("#division").val()
	postData["mt_input_id"] =  $('#login_idx').val()
	postData["mt_update_id"] =  $('#login_idx').val()
	
	if($('#always').is(':checked'))
	{
		postData['always']='Y';
	}
	else
	{
		postData['always']='N';
	}
	var data = JSON.stringify(postData);
	getPostData(url,data,callback_save,false);
}

체크내용스크립트는 별 내용이 없어요. 

function check_save()
{		
	console.log($('#summernote').summernote('code'));
	if($('#summernote').summernote('code')=='<p><br></p>')
	{
		showmessage("알림","내용을 확인해 주세요.",2000,'');
		$("#title").focus();
		return true;
	}
	if($('#summernote').summernote('code')=='')
	{
		showmessage("알림","내용을 확인해 주세요.",2000,'');
		$("#title").focus();
		return true;
	}
	if($("#mdate").val()=='')
	{
		showmessage("알림","작성일 확인해 주세요.",2000,'');
		$("#mdate").focus();
		return true;
	}
	if($("#title").val()=='')
	{
		showmessage("알림","제목을 확인해 주세요.",2000,'');
		$("#title").focus();
		return true;
	}
	if($("#division").val()=='')
	{
		showmessage("알림","커뮤니티 종류 확인해 주세요.",2000,'');
		$("#division").focus();
		return true;
	}
	return false;
}

 

응답후에요. 

var callback_save = function (result)
{
	$('#a_save_btn').removeAttr("disabled");
	if(result['result']=='INSERT_OK')
	{
		showmessage("알림","새글이 등록되었습니다.",5000,'');
		$("#i_idx").val(result['idx']);
		self.location = "/board/board?idx="+$("#i_idx").val();
	}
	else if(result['result']=='UPDATE_OK')
	{	
		showmessage("알림","수정이 되었습니다.",5000,'');
		self.location = "/board/board?idx="+$("#i_idx").val();
	}
	else
	{
		showmessage("알림",result['message'],20000,'');
	}
	
}

/board/save 컨트롤러를 만들어 볼께요. 

@RequestMapping(value = "/save", method = RequestMethod.POST)
	@ResponseBody
	public Map<String, String> regedit(@RequestBody CommonData dto) throws Exception{
		Map<String, String> paramMap = new HashMap<>();
		smsp.print_CommonData(dto);
		String sql_state = dto.get("sql_state");
		String idx = dto.get("idx");
		String uuid = dto.get("uuid");
		if(sql_state.equals("insert"))
		{
			//새글
			service.insert(dto, "Board_Mapper.new_save");
			paramMap.put("result", "INSERT_OK");
			idx = service.selectstr(dto, "Board_Mapper.new_save_idx");
			paramMap.put("idx", idx);
		}
		else if(sql_state.equals("update"))
		{
			//내용수정
			service.update(dto, "Board_Mapper.update");
			paramMap.put("result", "UPDATE_OK");
		}		
		return paramMap;
	}

컨트롤러 부분이었어요.  이제 쿼리부분이에요.

Board_Mapper.xml 파일을 만들어 쿼리는 이렇게 작성했어요. 

<insert id="new_save">		
		insert into tb_board(
					mdate
				  , title
				  , muuid
				  , content
				  , always
				  , division
				  , mt_input_wdate
				  , mt_input_id
				  , mt_update_wdate
				  , mt_update_id
				  )
		   values(  #{mdate}
				  , #{title}
				  , #{uuid}
				  , #{mt_content}
				  , #{always}
				  , #{division}
				  , now()
				  , #{mt_input_id}
				  , now()
				  , #{mt_update_id}
		          )
	</insert>
	<!-- 내용수정 -->
	<update id="update" >
  		update tb_board 
  		   set title = #{title}
  		     , content = #{mt_content} 
  		     , always = #{always}
  		     , mt_update_wdate =  now()
  		     , mt_update_id = #{mt_update_id}
  		 where idx = #{idx}
  	</update>
  	<!-- 새글번호 -->
  	<select id="new_save_idx" resultType="String"> 
		SELECT idx 
		 from tb_board
		where muuid = #{uuid}
	</select>

그리고 글을 저장하고 나면 수정폼이 아닌 일반 페이지에서 보여지면 좋겠어요. 

그래서 일반 페이지도 작성해요. 

<div class="card-body register-card-body">
			      <p class="login-box-msg">글내용</p>
				      <table class="table table-write" id="add_mt">
						<colgroup>			
						<col style="width:120px" />
						<col style="width:*" />						
						</colgroup>
						<tr>						
							<th>작성일</th>
							<td>
								${mdate}
							</td>
						</tr>
						<tr>						
							<th>제목</th>
							<td>${title}</td>
						</tr>
						<tr>
							<th>내용</th>
							<td>
								<div id="summernote">${content}</div>
							</td>
						</tr>
					</table>			      
				<!-- 게시판 구분 -->
			      <input type="hidden" id="division" name="division" value="test1" />
			    <!-- 글번호 --> 
			      <input type="hidden" class="form-control" id="i_idx" value="${idx}">
			    <!-- UUID 부여 -->
			      <input type="hidden" class="form-control" id="i_uuid" value="${uuid}">
			      
			    </div>

일반페이지는 board.jsp로 했어요. 적은 내용이 보여요. 

그리고 글을 적었으면 목록을 봐야겠죠?

목록이에요.

    <div class="card-body register-card-body">
			      <p class="login-box-msg">목록</p>
				      <div style="text-align: right;">
						<c:if test="${issave == 'yes'}">
						<button title="수정" type="button" id="a_edit_btn" class="btn btn-outline-primary" onclick="edit_note();">새글</button>
						</c:if>
  					  </div>
			      	
		      	  <table class="table table-bordered" id="board_list">
		      	  </table>
				<!-- 게시판 구분 -->
			      <input type="hidden" id="division" name="division" value="test1" />
			    </div>
			    <div class="footer_area">
					<div class="text-center">
						<ul class="pagination pagination-sm m-0 float-right" id="item_list_page">
						</ul>
					</div>
				</div>
			      
			    
			    <div style="text-align: right;">
					<c:if test="${issave == 'yes'}">
					<button title="수정" type="button" id="a_edit_btn" class="btn btn-outline-primary" onclick="edit_note();">새글</button>
					</c:if>
				</div>

 페이지를 로드한다음 jquery로 글을 읽어올꺼에요. 

var item_count;
var pageMaker;
$(document).ready(function(){
	item_count=0;
	list_page(1);
});
function list_page(in_data)
{
	var url;
	var sql_state_value = 'select';
	url = "/board/list_get";
	
	var postData = {};
    postData["sql_state"] = sql_state_value;
    if(!ISNULL(pageMaker))
    {
    	postData["page"] = in_data
		postData["perPageNum"] = pageMaker.cri.perPageNum
    }
	postData["title"] = $("#i_title").val()
	postData["division"] = $("#division").val()
	
    var data = JSON.stringify(postData);
    
	getPostData(url,data,callback_list);		
}

이렇게 호출을 해요. 

pageMaker가 선언이 안되어 있으면 페이지 정보는 없이 데이터를 요청해요. 

@RequestMapping(value = "/list_get", method = RequestMethod.POST, consumes="application/json")
	  public @ResponseBody CommonData list_get(@RequestBody CommonData dto) throws Exception {		  
		  CommonData R_data = new CommonData();
		  Iterator keyData = dto.keySet().iterator();
	      while (keyData.hasNext()) {
	          String key = ((String)keyData.next());
	          String value = dto.get(key);
	      }     
	      SearchCriteria cri = new SearchCriteria();     
	      if(dto.get("page")!=null)
	      {
	      	 cri.setPage(Integer.valueOf(dto.get("page"))); 
	      	 dto.put("perPageNum", Integer.valueOf(dto.get("perPageNum")));
	      }
	      else
	      {
	      	 cri.setPage(1);
	      	 dto.put("perPageNum", cri.getPerPageNum());
	      }
	      dto.put("pageStart", cri.getPageStart());     
	      PageMaker pageMaker = new PageMaker();
	      pageMaker.setCri(cri);
	      pageMaker.setTotalCount(service.listSearchCount(dto,"Board_Mapper.Board_select_cnt"));
	      List<Map<String, Object>> list = service.select(dto, "Board_Mapper.Board_select");
	      R_data.put("list", list);
	      R_data.put("pageMaker", pageMaker);
	      R_data.put("result", "SELECT_OK");
	      return R_data;
	  }

데이터를 요청 받았어요. 

그럼 받은 데이터를 화면에 표시해줘요. 

var callback_list = function (result_data)
{
	if(result_data['result']=='SELECT_OK')
	{
		var result = result_data.list;
	   	pageMaker = result_data.pageMaker;
	   	$("#board_list").empty();
	   	var i = $('#board_list').length + 2; //두칸뒤로.
	   	$("#board_list").append('<colgroup>'
   				+'						<col style="width:60px" />'
   				+'						<col style="width:200px" />'
   				+'						<col style="width:*" />'
   				+'						<col style="width:120px" />'
   				+'						</colgroup>					'
   				+'						<tr>'
   				+'							<th>번호</th>'
   				+'							<th>날짜</th>'
   				+'							<th>제목</th>'
   				+'							<th>작성자</th>'
   				+'						</tr>'
   				);
	   	var item_count=1 + (pageMaker.cri.page-1)*pageMaker.cri.perPageNum;
   		var no_num=0; 
   		jQuery.each( result, function( index, value ) {
   			$("#board_list").append('<tr>'
					  +'<td>'+value.idx+'</td>'
					  +'<td class="left">'
					  +value.mdate
					  +'</td>'
					  +'<td class="left">'
					  +'<a class="" href="/board/board?idx='+value.idx+'">'
					  +value.title
					  +'</a>'
					  +'<input type="hidden" class="form-control" id="b_idx'+index+'"' 
					  +' value="'+value.idx+'">'
					  +'</td>'
					  +'<td>'
					  +value.uname
					  +'</td>'
					  +'</tr>'
					  );	
   			item_count++;
			});
   		$("#item_list_page").empty();
   		if(pageMaker.prev)
   		{
   			$("#item_list_page").append('<li  class="page-link"><a href="#" onclick="list_page('+(pageMaker.startPage - 1)+')">&laquo;</a></li>');
   		}
   		for(var f_i=pageMaker.startPage;f_i<=pageMaker.endPage;f_i++)
   		{	
   			
   			if(pageMaker.cri.page == f_i)
   			{	
   				$("#item_list_page").append('<li class="page-link"><a href="#" onclick="list_page('+(f_i)+') ">'+f_i+'</a></li>');
   			}
   			else
   			{
   				$("#item_list_page").append('<li class="page-link"><a href="#" onclick="list_page('+(f_i)+') ">'+f_i+'</a></li>');
   			}
   			
   		}
   		if(pageMaker.next && pageMaker.endPage > 0)
   		{
   			$("#item_list_page").append('<li class="page-link"><a href="#" onclick="list_page('+(pageMaker.endPage + 1)+')">&raquo;</a></li>');
   		}
	}		
}

이렇게 하면 화면에 이렇게 표시되요. 

게시판 목록

오늘은 여기까지 정리 할께요. 

필요한 파일은 여기에 첨부할께요. 

남은 항목은 첨부파일, 게시글 이미지 따로 저장, 댓글 기능등이 남았네요.

오늘은 여기까지 정리할게요. 

jsp파일들이에요. 

board.jsp
0.00MB
list.jsp
0.01MB
write_e.jsp
0.01MB

컨트롤러 파일이에요. 

Board_Controller.java
0.01MB

다음은 맵퍼 파일이에요. 

Board_Mapper.xml
0.00MB

아 그리고 service와 dao를 수정했어요. 몽땅 올릴테니 파일을 변경해주세요. 

commonDAO.java
0.00MB
first_commonDAOImpl.java
0.00MB
second_commonDAOImpl.java
0.00MB

먼저 DAO파일이였구요 다음은 SERVICE파일이에요. 

common_Service.java
0.00MB
Common_ServiceImpl.java
0.01MB
First_ServiceImpl.java
0.00MB
Second_ServiceImpl.java
0.00MB

이상입니다. 

블로그 이미지

은호아빠

여행, 맛집, 일상, 프로그래밍, 개발자, 윈도우, 웹, jsp, spring, db, mysql, oracle, c#

,

summernote img 태그 이미지 첨부 스프링

https://summernote.org/ 에가면 사용법등 잘설명되어 있어요.

저는 스프링에서 summernote를 사용하는 방법에대해서 정리할거에요.

일단 summernote를 다운로드 받으세요. 사이트에 가면 잘나와 있어요. 

	<link href="${pageContext.request.contextPath}/resources/editor/summernote.css" rel="stylesheet">
	<script src="${pageContext.request.contextPath}/resources/editor/summernote.js"></script>
	<!-- include summernote-ko-KR -->
	<script src="${pageContext.request.contextPath}/resources/editor/lang/summernote-ko-KR.js"></script>
    

받으셨으면 페이지에 첨부를 해요. 

페이지를 시작하는 부분에 $(document).ready(function() {});

아래코드를 첨부해요.

$('#summernote').summernote({
	    lang: 'ko-KR', // default: 'en-US'
	   	height: 500,                 // set editor height
		minHeight: 500,             // set minimum height of editor
		maxHeight: 500,             // set maximum height of editor
		focus: true,                  // set focus to editable area after initializing summe
		callbacks: {
          onImageUpload: function(files, editor, welEditable) {
            for (var i = files.length - 1; i >= 0; i--) {
              sendFile(files[i], this);
            }
          },
          onChange: function(contents, $editable) {
              console.log('onChange:', contents, $editable);
             
              new_img_list=$(".note-editable .sn_insert_img");
              if(old_img_list!='' &&new_img_list!='')
              {
              	note_image_sync(old_img_list,new_img_list);
              }
              old_img_list= $(".note-editable .sn_insert_img");
              
            },
          onBlur: function() {
              console.log('Editable area loses focus');
            },
          onFocus: function() {
              console.log('Editable area is focused');
            }
        }
	  });
	$("#summernote").summernote({
	    onMediaDelete : function($target, editor, $editable) {
	         alert($target.context.dataset.filename);         
	         $target.remove();
	    }
	}); 

섬머노트 페이지에 가면 설명이 잘되어 있어서 설명은 안하겠어요. 여기서 onImageUpload 부분을 구현해줘야 해요. 

sendFile부분을 구현해야해요. 

function sendFile(file, el) {
    var form_data = new FormData();
    form_data.append('file', file);
    $.ajax({
      data: form_data,
      headers : {
			'X-CSRF-TOKEN': $("#csrf_token").val()
		},
      type: "POST",
      url: '/admin/chart/image_upload',
      cache: false,
      contentType: false,
      enctype: 'multipart/form-data',
      processData: false,
      async: false
    }).done(function( msg ) {
        if(msg.result=='IMAGE_OK')
        {
	        var url = msg.url;
	        id = msg.id;        
	        $(el).summernote('editor.insertImage', url,fun_summernote_imgcallback);
	        $('#imageBoard > ul').append('<li><img src="'+url+'" class="summernoteimg_obj" id="'+id+'" width="100%" height="100%"/></li>');
        }
        else
    	{
        	showmessage("알림","이미지 파일이 아닙니다.",2000,'');
    	}
    });
  }

저는 이미지 파일을 db에 보관을 해요. 

image_upload부분은 이렇게 해요. 

@ResponseBody
		@RequestMapping(value ="/image_upload", method=RequestMethod.POST, produces = "application/json;charset=UTF-8")
		public Map<String, String> update_file_upload(MultipartFile file,HttpServletRequest request)throws Exception{
			Map<String, String[]> paramMap=request.getParameterMap();
			Iterator keyData = paramMap.keySet().iterator();
			CommonData dto = new CommonData();
			while (keyData.hasNext()) {
			    String key = ((String)keyData.next());
			    String[] value = paramMap.get(key);
			    dto.put(key, value[0].toString());        
			    smsp.print_String("key : " + key + ", value : " + value[0].toString());
			} 
			MediaUtils MediaUtils = new MediaUtils();
			String formatName = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf(".")+1);
			MediaType mType = MediaUtils.getMediaType(formatName);
			BufferedImage resizeimg;
			if(mType!=null)
			{
				BufferedImage srcImg = ImageIO.read(file.getInputStream()); 
				/*
			    if(srcImg.getWidth()>1920) //사이즈 조절 할때
			    {
			    	smsp.print_String("사이즈 조절 1920");
			    	resizeimg = Scalr.resize(srcImg
			    			, Scalr.Method.QUALITY
			    			, Scalr.Mode.FIT_TO_WIDTH
			    			, 1920
			    			,Scalr.OP_ANTIALIAS);
			    	ByteArrayOutputStream baos_re = new ByteArrayOutputStream();
			 	    boolean foundWriter_re = ImageIO.write(resizeimg, formatName.toLowerCase(), baos_re);
			 	    baos_re.flush();
			 		byte[] imageInByte_re = baos_re.toByteArray();
			 		dto.put("mt_contentlength",baos_re.toByteArray().length);
			 		dto.put("mt_data", imageInByte_re);
			 		baos_re.close();
			    }
			    else //사이즈 조절안할때.
			    */ 
			    {	
			    	smsp.print_String("사이즈 조절안함. 1920");
			    	dto.put("mt_contentlength",file.getBytes().length);
			 	    dto.put("mt_data", file.getBytes());
			    }	   
			    BufferedImage destImg = 
			            Scalr.resize(srcImg, 
			            		Scalr.Method.BALANCED, 
			                180,180
			                ,Scalr.OP_ANTIALIAS);
			    ByteArrayOutputStream baos = new ByteArrayOutputStream();
			    boolean foundWriter = ImageIO.write(destImg, "png", baos);
				baos.flush();
				byte[] imageInByte = baos.toByteArray();
				dto.put("mt_s_data", imageInByte);
				baos.close();
			}
			Map<String, String> result = new HashMap<>();
			result.put("result", "NOT_AN_IMAGE");
			if(mType!=null)
			{
			    dto.put("mt_filename",file.getOriginalFilename());
			    dto.put("mt_type",file.getContentType());
			    HttpSession session = request.getSession();
			    Member vo = (Member) session.getAttribute("login");
			    dto.put("mt_input_id", vo.idx);
			    dto.put("mt_update_id", vo.idx);
			    first_service.insert(dto, "File_UpDown_Mapper.insert_editor_image_upload");
			    int idx= first_service.listSearchCount(dto, "File_UpDown_Mapper.select_editor_image_upload");
				result.put("result", "IMAGE_OK");
			    String url = "/editor/get_editor_image/?idx="+idx;
			    String id = ""+idx;
			    result.put("url", url);
			    result.put("id", id);
			    }
		    return result;
		}

db에 바로 넣고 있어요. 

db의 테이블은 이렇게 생겼어요. 

CREATE TABLE `editor_image_table` (
  `idx` int(11) NOT NULL AUTO_INCREMENT COMMENT '게시물 고유키값',
  `mt_uuid` varchar(40) DEFAULT NULL,
  `mt_contentlength` int(11) DEFAULT NULL COMMENT '파일사이즈.',
  `mt_filename` varchar(100) DEFAULT NULL COMMENT '이름',
  `mt_type` varchar(100) DEFAULT NULL COMMENT '파일타입',
  `mt_data` longblob DEFAULT NULL COMMENT '파일내용',
  `mt_s_data` longblob DEFAULT NULL COMMENT '축소파일내용',
  `mt_input_wdate` datetime DEFAULT NULL COMMENT '입력일',
  `mt_input_id` bigint(20) DEFAULT NULL COMMENT '입력ID',
  `mt_update_wdate` datetime DEFAULT NULL COMMENT '최종수정일',
  `mt_update_id` bigint(20) DEFAULT NULL COMMENT '최종수정ID',
  PRIMARY KEY (`idx`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8 COMMENT='파일정보';

쿼리부분입니다. 

<!-- 이미지파일 업로드 -->
	<insert id="insert_editor_image_upload">	
		INSERT INTO editor_image_table (
						   mt_filename						
						 , mt_type
						 , mt_data
						 <if test="mt_s_data != null">
						 , mt_s_data
						 </if>
						 <if test="uid != null">
						 , mt_uuid
						 </if>
						 , mt_contentlength
						 , mt_input_wdate
						 , mt_input_id
						 , mt_update_wdate
						 , mt_update_id
						 ) 
				     VALUES (
				           #{mt_filename}				         	
				         , #{mt_type}
				         , #{mt_data}
				         <if test="mt_s_data != null">
				         , #{mt_s_data}
				         </if>
				         <if test="uid != null">
						 , #{uid}
						 </if>
				         , #{mt_contentlength}
				         , now()		          
				         , #{mt_input_id}
				         , now()
				         , #{mt_update_id}	         
				         )
	</insert>

이상입니다.

블로그 이미지

은호아빠

여행, 맛집, 일상, 프로그래밍, 개발자, 윈도우, 웹, jsp, spring, db, mysql, oracle, c#

,

SPRING MVC 세팅 설정 시작하기!

SPRING BOOT도 좋지만 저는 SPRING MVC로 프로젝트를 진행을 하는 편이에요.

환경설정 등을 기존에 해놓은 것을 그대로 사용할 수 있어 그런데요.

일단 STS를 실행하고 새로운 작업공간을 설정해요. 

새로운작업공간

전 DENTALAPP이라는 폴더를 작업공간으로 설정했어요. 

스프링 레거시 프로젝트

오른쪽 마우스를 누르고 New -> Spring Legacy Project를 선택해요.

패키지

그럼 새로운 작업 패키지명을 적는데요 저는 com에 제 이름의 약어인 sms와 2019를 붙이고 home이라고 적었어요. 

앱이름

프로젝트 이름을 dentalapp이라고 하였고요.  템플릿은 Spring MVC Project를 선택하였어요. 

컨트롤러

홈컨트롤러 파일과 홈 JSP파일이 생기는데요. 

JSP파일

JSP파일은 페이지를 UTP-8로 사용하겠다는 내용을 추가해줘요. 안 그러면 한글이 깨져서 나와요. 

그럼 프로젝트를 실행해볼까요?

저는 톰캣 8로 설정하고 돌렸어요. 

결과물

결과가 잘 나오고 있네요. 한글도 안 깨지고요. 

앞으로 쭉 프로젝트를 진행 볼게요. 모바일 웹앱을 만들 생각이고요. 안드로이드랑 아이폰으로 패키징을 할 계획이에요. 

여기까지 정리할게요. 

블로그 이미지

은호아빠

여행, 맛집, 일상, 프로그래밍, 개발자, 윈도우, 웹, jsp, spring, db, mysql, oracle, c#

,

Spring java excel download 스프링 엑셀 다운 poi

SRPING MVC 이미지

안녕하세요. 웹 개발일을 하다 보면 엑셀 파일을 요청받을 일들이 있어요. 

SPRING에서는 아파치 소프트웨어 재단에서 만든 POI를 사용할 수 있어요. 

마이크로소프트 오피스 파일들을 읽고 쓰는 기능을 제공하는데요. 워드, 엑셀, 파워포인트 파일을 지원하고 있어요. 최근 OFFICE OPEN XML FILE FORMATS(*. DOCX,*. XLSX,*. PPTX)등 지원 파일을 늘려가고 있다고 해요. 

처음 메이븐 설정을 해요. 

		<!-- 엑셀파일 -->
		<dependency>
		    <groupId>org.apache.poi</groupId>
		    <artifactId>poi</artifactId>
		    <version>3.13</version>
		</dependency>
		<dependency>
		    <groupId>org.apache.poi</groupId>
		    <artifactId>poi-ooxml</artifactId>
		    <version>3.13</version>
		</dependency>
		<dependency>
		    <groupId>org.apache.commons</groupId>
		    <artifactId>commons-collections4</artifactId>
		    <version>4.0</version>
		</dependency>

SERVLET-CONTEXT.XML 파일 내용을 찾아보면 InternalResourceViewResolver가 선언되어 있을거에요. 

<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>

JSP페이지로 이름을 매핑해주는것인데 대부분 설정이 되어 있을 거예요.

저희가 받아야 할 건 JSP페이지가 아니에요. 

XmlViewResolver를 설정해줘야 해요. 조금 귀찮긴 한데 한번 만들어 놓으면 다른 프로젝트에도 복사해서 사용하면 돼요.

<beans:bean id="viewResolver1" class="org.springframework.web.servlet.view.XmlViewResolver">
        <beans:property name="order" value="1"/>
        <beans:property name="location" value="/WEB-INF/views.xml"/>
    </beans:bean>

views.xml파일위치

views.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"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
   	<bean id="mr001_exceldownload_View" class="com.sms2019.excel.mr001_exceldownload_View" />
</beans>

views.xml
0.00MB

그리고 소스파일에 views.properties 추가를 해요. 

views.properties

mr001_exceldownload_View.(class)=com.sms2019.excel.mr001_exceldownload_View

views.properties
0.00MB

컨트롤러 부분에 요청받는 부분을 만들어요. 

@RequestMapping(value = "/g402_excel_download", method = RequestMethod.GET)
  public ModelAndView g402_excel_download(HttpServletRequest request, Model model) throws Exception {
	  	Util_list_convert smsp=Util_list_convert.getInstance();
	  	smsp.print_String("/gp/g402_excel_download");
		Map<String, String[]> paramMap=request.getParameterMap();
		paramMap.forEach(
				(key, value) ->  smsp.print_String(key + " : " + value[0])
				);
		Iterator keyData = paramMap.keySet().iterator();
		CommonData dto = new CommonData();	
		paramMap.forEach(
				(key, value) -> {dto.put(key, value[0]);
				smsp.print_String(key + " : " + value[0]);
				model.addAttribute(key,value[0].toString());
				});
	    CommonData data_box = new CommonData();
	    List Title_list = new ArrayList();    
	    Title_list.add("번호");
	    Title_list.add("품목명");
	    Title_list.add("규격");
	    Title_list.add("파트");
	    Title_list.add("수량");
	    Title_list.add("팀");

	    List Title_list_coll = new ArrayList();
	    Title_list_coll.add("rownum");
	    Title_list_coll.add("item_name");
	    Title_list_coll.add("item_standard");
	    Title_list_coll.add("part_division_text");
	    Title_list_coll.add("quantity");
	    Title_list_coll.add("team_code_text");
	    
	    dto.put("exceldown","exceldown");
	    List<Map<String, Object>> list = z_service.select(dto,"Gp2018_Mapper.g402_list_select");
	    ModelAndView mav = new ModelAndView("mr001_exceldownload_View");
	    mav.addObject("Title_list", Title_list);
	    mav.addObject("Title_list_coll", Title_list_coll);
	    mav.addObject("list", list);
	    mav.addObject("Filename", "주문목록");
	    return mav;
  }

엑셀 파일 데이터를 만들어요 db에서 읽어와도 좋고요 엑셀 윗부분을 요청 시 받아와도 되고요 전 컨트롤러를 각각 만들어서 써요. 그래서 타이틀이랑 항목 칼럼 이름 그리고 데이터 그리고 파일 이름 넣어요. 

그럼 MadelAndView에 적힌 부분으로 호출이 되는데요.

package com.danawa.excel;

import java.net.URLEncoder;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

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

import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFFont;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Font;
import org.springframework.stereotype.Controller;
import org.springframework.web.servlet.view.document.AbstractExcelView;

import com.danawa.domain.CommonData;
import com.danawa.util.Util_list_convert;

@Controller
public class mr001_exceldownload_View extends AbstractExcelView {
 
    @Override
    protected void buildExcelDocument(Map<String, Object> model,
            HSSFWorkbook workbook, HttpServletRequest request, HttpServletResponse response)
            throws Exception {
    	Util_list_convert smsp=Util_list_convert.getInstance();
	  	smsp.print_String("Common_exceldownload");
    	String Filename = (String)model.get("Filename");
		String fileName = Filename+".xls";
		fileName = URLEncoder.encode(fileName,"UTF-8");
        response.setContentType("application/ms-excel; charset=UTF-8");
        response.setCharacterEncoding("UTF-8");
        response.setHeader("Content-Disposition","attachment; filename="+fileName);
        // get data model which is passed by the Spring container
        List<String> Title_list = (List<String>) model.get("Title_list");
        List<String> Title_list_coll = (List<String>) model.get("Title_list_coll");
    	List<CommonData> list = (List<CommonData>) model.get("list");
        // create a new Excel sheet
        HSSFSheet sheet = workbook.createSheet("sheet1");
        sheet.setDefaultColumnWidth(30);
         
        // create style for header cells
        CellStyle style = workbook.createCellStyle();
        CellStyle centerstyle = workbook.createCellStyle();
        CellStyle centerbluestyle = workbook.createCellStyle();
       
        Font font = workbook.createFont();
        font.setFontName("Arial");        
        font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
        font.setColor(HSSFColor.WHITE.index);
       // style.setFillForegroundColor(HSSFColor.BLACK.index);
       // style.setFillPattern(CellStyle.SOLID_FOREGROUND);
        style.setBorderBottom (HSSFCellStyle.BORDER_THIN);
        style.setBottomBorderColor (HSSFColor.BLACK.index);
        style.setBorderLeft (HSSFCellStyle.BORDER_THIN);
        style.setLeftBorderColor (HSSFColor.BLACK.index);
        style.setBorderRight (HSSFCellStyle.BORDER_THIN);
        style.setRightBorderColor (HSSFColor.BLACK.index);
        style.setBorderTop (HSSFCellStyle.BORDER_THIN);
        style.setTopBorderColor (HSSFColor.BLACK.index);
        //style.setFont(font);        
        //centerstyle.setFillForegroundColor(HSSFColor.WHITE.index);
        //centerstyle.setFillPattern(CellStyle.SOLID_FOREGROUND);
        centerstyle.setAlignment(CellStyle.ALIGN_CENTER);
        centerstyle.setBorderBottom(HSSFCellStyle.BORDER_THIN);
        centerstyle.setBottomBorderColor(HSSFColor.BLACK.index);
        centerstyle.setBorderLeft(HSSFCellStyle.BORDER_THIN);
        centerstyle.setLeftBorderColor(HSSFColor.BLACK.index);
        centerstyle.setBorderRight(HSSFCellStyle.BORDER_THIN);
        centerstyle.setRightBorderColor(HSSFColor.BLACK.index);
        centerstyle.setBorderTop(HSSFCellStyle.BORDER_THIN);
        centerstyle.setTopBorderColor(HSSFColor.BLACK.index);
        centerbluestyle.setFillForegroundColor(HSSFColor.BLACK.index);
        centerbluestyle.setFillPattern(CellStyle.SOLID_FOREGROUND);
        centerbluestyle.setAlignment(CellStyle.ALIGN_CENTER);
        centerbluestyle.setFillBackgroundColor(HSSFColor.BLACK.index);
        centerbluestyle.setBorderBottom(HSSFCellStyle.BORDER_THIN);
        centerbluestyle.setBottomBorderColor(HSSFColor.BLACK.index);
        centerbluestyle.setBorderLeft(HSSFCellStyle.BORDER_THIN);
        centerbluestyle.setLeftBorderColor(HSSFColor.BLACK.index);
        centerbluestyle.setBorderRight(HSSFCellStyle.BORDER_THIN);
        centerbluestyle.setRightBorderColor(HSSFColor.BLACK.index);
        centerbluestyle.setBorderTop(HSSFCellStyle.BORDER_THIN);
        centerbluestyle.setTopBorderColor(HSSFColor.BLACK.index);
        centerbluestyle.setFont(font);    
         
        // create header row
        HSSFRow header = sheet.createRow(0);
        
        int cellCount;
        cellCount=0;
        int columns_length=0;
        //제목 값 세팅 한다. 
        for(String item : Title_list){
        	header.createCell(cellCount).setCellValue(item);
            header.getCell(cellCount).setCellStyle(centerbluestyle);
            cellCount++;
            columns_length++;
    	}
        
        // create data rows
        int rowCount = 1;   
        String sitem_name = null;
        String item_standard = null;
        String sitem_name_replace=null;
        Iterator list_object = list.iterator();	    
        while (list_object.hasNext()) {
        	CommonData e_object = (CommonData) list_object.next();
            HSSFRow aRow = sheet.createRow(rowCount++);
            cellCount=0; 
            
            for(String item : Title_list_coll){
                String value = e_object.get(item);
                smsp.print_String("item : " + value);
                aRow.createCell(cellCount).setCellValue(value);
	            aRow.getCell(cellCount).setCellStyle(centerstyle);            
	            cellCount++;
            }
    	}
        for(int ni=1;ni<=sheet.getLastRowNum();ni++)
        { 
        	sheet.getRow(ni).setHeightInPoints((float)20);
        	 
        }
       
        autoSizeColumns(sheet,sheet.getRow(0).getLastCellNum());
    }
    private void autoSizeColumns(HSSFSheet sheetData, int maxColNum) {
   	 try {
   		 // Autosize columns
   		 int width = 0;
   		 for (int col = 0; col < maxColNum; col++) {
   			 sheetData.autoSizeColumn(col);
   			 int cwidth = sheetData.getColumnWidth(col);
   			 cwidth += 500;
   			 sheetData.setColumnWidth(col, cwidth);
   			 width += cwidth;
   		 }

   		 // calculate zoom factor
   		 int nominator = 45000 * 100 / width;
   		 if (nominator < 100)
   			 sheetData.setZoom(nominator, 100);

   	 } catch (Exception he) {
   		 // No UI, no autosize :(
   	 }
    }
 
}

이렇게 엑셀 내용을 채워 엑셀 파일이 만들어져요.

String Filename = (String)model.get("Filename");
		String fileName = Filename+".xls";
		fileName = URLEncoder.encode(fileName,"UTF-8");
        response.setContentType("application/ms-excel; charset=UTF-8");
        response.setCharacterEncoding("UTF-8");
        response.setHeader("Content-Disposition","attachment; filename="+fileName);

파일 이름을 설정하고 utf8로 다운로드돼요.

List<String> Title_list = (List<String>) model.get("Title_list");
        List<String> Title_list_coll = (List<String>) model.get("Title_list_coll");
    	List<CommonData> list = (List<CommonData>) model.get("list");

엑셀 파일의 항목 타이틀과 각 항목의 column의 이름 그리고 데이터 받아와요. 

HSSFSheet sheet = workbook.createSheet("sheet1"); 
        sheet.setDefaultColumnWidth(30);

sheet를 만들어요. 만들 때 이름을 정해줄 수 있어요. 전 sheet1이라고 했어요. 

// create style for header cells
        CellStyle style = workbook.createCellStyle();
        CellStyle centerstyle = workbook.createCellStyle();
        CellStyle centerbluestyle = workbook.createCellStyle();
       

cell 스타일을 미리 만들었어요.  단순해요. style는 흰색의 배경에 검은색의 테두리 선을 가진 것이고요. centerstyle는 중앙 정렬한 흰색 배경에 검은색 테두리 구요. centerbluestyle는 중앙 정렬에 파란 배경을 과 검은색 테두리를 가진 스타일이에요. 

style.setBorderBottom (HSSFCellStyle.BORDER_THIN);
        style.setBottomBorderColor (HSSFColor.BLACK.index);
        style.setBorderLeft (HSSFCellStyle.BORDER_THIN);
        style.setLeftBorderColor (HSSFColor.BLACK.index);
        style.setBorderRight (HSSFCellStyle.BORDER_THIN);
        style.setRightBorderColor (HSSFColor.BLACK.index);
        style.setBorderTop (HSSFCellStyle.BORDER_THIN);
        style.setTopBorderColor (HSSFColor.BLACK.index);        
        centerstyle.setAlignment(CellStyle.ALIGN_CENTER);
        centerstyle.setBorderBottom(HSSFCellStyle.BORDER_THIN);
        centerstyle.setBottomBorderColor(HSSFColor.BLACK.index);
        centerstyle.setBorderLeft(HSSFCellStyle.BORDER_THIN);
        centerstyle.setLeftBorderColor(HSSFColor.BLACK.index);
        centerstyle.setBorderRight(HSSFCellStyle.BORDER_THIN);
        centerstyle.setRightBorderColor(HSSFColor.BLACK.index);
        centerstyle.setBorderTop(HSSFCellStyle.BORDER_THIN);
        centerstyle.setTopBorderColor(HSSFColor.BLACK.index);
        centerbluestyle.setFillForegroundColor(HSSFColor.BLACK.index);
        centerbluestyle.setFillPattern(CellStyle.SOLID_FOREGROUND);
        centerbluestyle.setAlignment(CellStyle.ALIGN_CENTER);
        centerbluestyle.setFillBackgroundColor(HSSFColor.BLACK.index);
        centerbluestyle.setBorderBottom(HSSFCellStyle.BORDER_THIN);
        centerbluestyle.setBottomBorderColor(HSSFColor.BLACK.index);
        centerbluestyle.setBorderLeft(HSSFCellStyle.BORDER_THIN);
        centerbluestyle.setLeftBorderColor(HSSFColor.BLACK.index);
        centerbluestyle.setBorderRight(HSSFCellStyle.BORDER_THIN);
        centerbluestyle.setRightBorderColor(HSSFColor.BLACK.index);
        centerbluestyle.setBorderTop(HSSFCellStyle.BORDER_THIN);
        centerbluestyle.setTopBorderColor(HSSFColor.BLACK.index);
        centerbluestyle.setFont(font);    

직관적으로 만들어놓아서 대충 알아보실 거 같아요. 소스량을 줄이려면 함수를 만들면 되겠죠? 그건 직접 해보세요 ^^

 Font font = workbook.createFont();
        font.setFontName("Arial");        
        font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
        font.setColor(HSSFColor.WHITE.index);

폰트를 따로 선언해서 사용해야 할 일이 있을 경우엔 폰트도 추가해주세요 전 타이틀 부분은 폰트를 다르게 했어요 흰색으로요. ^^

HSSFRow header = sheet.createRow(0);

첫 번째 로우를 만들고요 

 int cellCount;
        cellCount=0;
        int columns_length=0;
        //제목 값 세팅 한다. 
        for(String item : Title_list){
        	header.createCell(cellCount).setCellValue(item);
            header.getCell(cellCount).setCellStyle(centerbluestyle);
            cellCount++;
            columns_length++;
    	}

첫번째 행에 항목 타이틀 값들을 넣어줘요... 

 // create data rows
        int rowCount = 1;   
        String sitem_name = null;
        String item_standard = null;
        String sitem_name_replace=null;
        Iterator list_object = list.iterator();	    
        while (list_object.hasNext()) {
        	CommonData e_object = (CommonData) list_object.next();
            HSSFRow aRow = sheet.createRow(rowCount++);
            cellCount=0; 
            
            for(String item : Title_list_coll){
                String value = e_object.get(item);
                smsp.print_String("item : " + value);
                aRow.createCell(cellCount).setCellValue(value);
	            aRow.getCell(cellCount).setCellStyle(centerstyle);            
	            cellCount++;
            }
    	}

컨트롤러에서 넘겼던 칼럼 항목 이름을 순으로 위치로 해서 셀에 넣어요. 

이상으로 엑셀 파일 다운로드 관련해서 정리해보았습니다. 

블로그 이미지

은호아빠

여행, 맛집, 일상, 프로그래밍, 개발자, 윈도우, 웹, jsp, spring, db, mysql, oracle, c#

,

홈페이지를 구축하다보면 기존 도메인과 개발도메인 로컬 도메인등 여러 주소를 사용할 경우가 있습니다.

저의 경우 홈페이지 구매후 신규 개발을 들어 갔는데 이름역시 디지털아트에서 디지털365치과의원으로 변경되어 

홈페이지를 신규개발한후 365에 맞는 도메인 https://digital365365.com/ 를 구매하여 설정하였고

기존에 운영중인던 도메인 dadentalclinic.com 도메인과 디지털365치과.com 등을 추가로 설정하였습니다.

그런데 블로그나 사이트 등록시 https://digital365365.com/ 로 하면 좋았을텐데 여러가지 도메인들을 사용하게 되었습니다.

그래서 도메인을 임의로 통합시키는 작업을 해주었습니다. 

<beans:bean id="metaInterceptor" class="com.sms2019.interceptor.MetaInterceptor"></beans:bean>

인터셉터 를 하나 만들어 줍니다. 

인터셉터 내용은 아래와 같습니다.

String m_url = request.getRequestURL().toString();
		smsp.print_String("m_url :" + m_url);
		if(m_url.contains("검사주소 넣기"))
		{
			smsp.print_String("바른주소");
		}
		else if(m_url.contains("http://localhost"))
		{
			smsp.print_String("로콜주소");
		}
		else
		{
			smsp.print_String("그외 주소다.");
			String new_addr = "https://digital365365.com"+originalURL;
			response.sendRedirect(new_addr);
		}

이상입니다. 

블로그 이미지

은호아빠

여행, 맛집, 일상, 프로그래밍, 개발자, 윈도우, 웹, jsp, spring, db, mysql, oracle, c#

,