웹프로그램을 만들다보면 그리드 시스템이 필요할떄가 있습니다. 

테이블태그를 이용한 코드 작성도 나쁘진 않지만 JQGRID를 사용해보고 개발의 편리성에 GRID라이브러리를 사용하게 되었습니다. 

JQGRID를 사용해 보았으니 최신버전은 유료라이센스로 바뀌었고 4.0대 버전을 무료로 사용할수 있었습니다. 

대체할 라이브러리를 검색을 하다 발견한 JSGRID를 사용을 해보게 되었습니다. 

JQGRID라이브러리의 예제 소스는 아래에서 다운받거나 구경할수 있습니다.

http://js-grid.com/demos/

 

Demos

 

js-grid.com

저는 JSGRID 라이브러리를 스프링에 적용하는 것을 정리합니다. 

라이브러리 로드 파일에 라이브러리경로를 넣어줍니다. 

    <link rel="stylesheet" type="text/css" href="../css/jsgrid.css" />
    <link rel="stylesheet" type="text/css" href="../css/theme.css" />
    
    <script src="../src/jsgrid.core.js"></script>    
    <script src="../src/jsgrid.load-indicator.js"></script>
    <script src="../src/jsgrid.load-strategies.js"></script>
    <script src="../src/jsgrid.sort-strategies.js"></script>
    <script src="../src/jsgrid.validation.js"></script>
    <script src="../src/jsgrid.field.js"></script>
    <script src="../src/fields/jsgrid.field.text.js"></script>
    <script src="../src/fields/jsgrid.field.number.js"></script>
    <script src="../src/fields/jsgrid.field.select.js"></script>
    <script src="../src/fields/jsgrid.field.checkbox.js"></script>
    <script src="../src/fields/jsgrid.field.control.js"></script>

각자의 경로에 맞추어 넣어주면 됩니다. 

jsgrid를 선언하는 부분은 이런식으로 나와 있습니다. 

 $("#jsGrid").jsGrid({
                height: "70%",
                width: "100%",
                filtering: true,
                editing: true,
                inserting: true,
                sorting: true,
                paging: true,
                autoload: true,
                pageSize: 15,
                pageButtonCount: 5,
                deleteConfirm: "Do you really want to delete the client?",
                controller: db,
                fields: [
                    { name: "Name", type: "text", width: 150, validate: "required" },
                    { name: "Age", type: "number", width: 50, validate: { validator: "range", param: [18,80] } },
                    { name: "Address", type: "text", width: 200, validate: { validator: "rangeLength", param: [10, 250] } },
                    { name: "Country", type: "select", items: db.countries, valueField: "Id", textField: "Name",
                        validate: { message: "Country should be specified", validator: function(value) { return value > 0; } } },
                    { name: "Married", type: "checkbox", title: "Is Married", sorting: false },
                    { type: "control" }
                ]
            });

나누어 보겠습니다. 

위부분을 인수로 받아 생성하는 코드로 변경을 합니다.

//그리드 생성.
function initGrid(grid_id,in_fields,in_paging,in_pageSize,in_pageButtonCount,in_filtering,in_inserting,in_editing,in_sorting,in_autoload
		,now_pager,now_table_custom,now_db
		,onrowClass,inonItemInserting,inonItemUpdating)
{
	jsGrid.locale("ko");
	grid_id.jsGrid({
		
		noDataContent: "데이터가 없습니다.",
		deleteConfirm: "삭제합니다 정말입니까?",
		pagerFormat: " {prev} {pages} {next}",
		pagePrevText: "&laquo;",
		pageNextText: "&raquo;",
		pageFirstText: "처음",
		pageLastText: "마지막",
		loadMessage: "잠시 기다려주십시오 .",
		invalidMessage: "입력 된 데이터가 잘못되었습니다.",
		
        height: "auto",
        width: "100%",
        filtering: in_filtering,
        editing: in_editing,
        inserting: in_inserting,
        sorting: in_sorting,
        paging: in_paging,
        pageLoading: true,
        autoload: in_autoload,
        pageSize: in_pageSize,
        pageButtonCount: in_pageButtonCount,
        controller: now_db,
        fields: in_fields,
        rowClass: onrowClass,
        onItemInserting: inonItemInserting,
        onItemUpdating: inonItemUpdating,
        onItemInserted:function(){grid_id.jsGrid("loadData");},
    });
	now_table_custom.on("click", function() {
        var $cb = $(this);
        grid_id.jsGrid("option", $cb.attr("id"), $cb.is(":checked"));
    });
    now_pager.on("change", function() {
        var page = parseInt($(this).val(), 10);
        grid_id.jsGrid("option", "pageSize", page); 
        grid_id.jsGrid("refresh");
    });
}

jsgrid로  한페이지에 다수의 그리드를 생성 관리할수 있게 되었습니다. 

<div id="jsGrid"></div> //기본 예제 그리드 id

입력되는 값들을 기본 디폴드 값으로 분리한 선언부를 만들어 놓습니다. 

//조각 조각 입력해서 그리드 생성하기..
var sms_js_size = [];
sms_js_size["width"]="100%";
sms_js_size["height"]="auto";
var sms_basic_setting= [];
sms_basic_setting["autoload"]=true; //화면 로딩시 데이터를 불러옴.
sms_basic_setting["confirmDeleting"]=true; //삭제시 정말 지울건지 물어봄. 
sms_basic_setting["pagerContainer"] = null; //페이지 이동 위치 .. 
sms_basic_setting["pageIndex"] = 1; //시작페이지 위치.. 기본 1페이지..
sms_basic_setting["pageSize"] = 15; //화면에 나타날 기본 줄수... 15개를 기본으로한다. 
sms_basic_setting["loadIndication"] = true; // 제어기 조작 실행 중로드 표시를 표시할지 여부를 지정하는 부울 값.
sms_basic_setting["loadIndicationDelay"]= 500; //로드 표시를 표시하기 전의 지연을 ms 단위로 지정하는 정수 값
sms_basic_setting["loadShading"] = true; //표시를로드하는 동안 격자 내용 위에 오버레이 (셰이더)를 표시할지 여부를 지정하는 부울 값?
sms_basic_setting["updateOnResize"] = true;//윈도우 크기 변경 이벤트에서 격자를 새로 고칠 지 여부를 지정하는 부울 값
var sms_in_ting = [];
sms_in_ting["heading"]= true; //격자 머리글 표시 여부를 지정합니다.
sms_in_ting["filtering"]= true; // 필터 행 표시 여부를 지정
sms_in_ting["inserting"]= true; // 행 삽입 여부를 지정합니다.
sms_in_ting["editing"]= true; //편집이 허용되는지 여부를 지정합니다.
sms_in_ting["selecting"]= true; //마우스를 올리면 표 행을 강조 표시할지 여부를 지정합니다.
sms_in_ting["sorting"]= true; // 정렬 허용 여부를 지정합니다.
sms_in_ting["paging"]= true; // 페이지별로 데이터를 표시할지 여부
sms_in_ting["pageLoading"]= true; //부울 값은 페이지별로 데이터를로드할지 여부를 지정
var sms_in_row_function = [];
sms_in_row_function["rowClass"]=function (item, itemIndex)  {};
sms_in_row_function["rowClick"]=function ( args ) {};
sms_in_row_function["rowDoubleClick"]=function ( args ) {};
sms_in_row_function["invalidNotify"]=function ( args ) {};
var sms_in_callback = [];
sms_in_callback["onDataLoading"]=function ( args ) {};
sms_in_callback["onDataLoaded"]=function ( args ) {};
sms_in_callback["onError"]=function ( args ) {};
sms_in_callback["onInit"]=function ( args ) {};
sms_in_callback["onItemInserting"]=function ( args ) {};
sms_in_callback["onItemInserted"]=function ( args ) {};
sms_in_callback["onItemUpdating"]=function ( args ) {};
sms_in_callback["onItemUpdated"]=function ( args ) {};
sms_in_callback["onItemDeleting"]=function ( args ) {};
sms_in_callback["onItemDeleted"]=function ( args ) {};
sms_in_callback["onItemInvalid"]=function ( args ) {};
sms_in_callback["onOptionChanging"]=function ( args ) {};
sms_in_callback["onOptionChanged"]=function ( args ) {};
sms_in_callback["onPageChanged"]=function ( args ) {};
sms_in_callback["onRefreshing"]=function ( args ) {};
sms_in_callback["onRefreshed"]=function ( args ) {};
function get_JsSize()
{
	var return_obj = {};
	//copyArray(return_obj,sms_js_size);
	for (var key in sms_js_size )
	{
		return_obj[key]=sms_js_size[key];
	}
	return return_obj;
}
function get_JsBasic_setting()
{
	var return_obj = {};
	//copyArray(return_obj,sms_basic_setting);
	for (var key in sms_basic_setting )
	{
		return_obj[key]=sms_basic_setting[key];
	}
	return return_obj;
}
function get_JsIn_tinge()
{
	var return_obj = {};
	//copyArray(return_obj,sms_in_ting);
	for (var key in sms_in_ting )
	{
		return_obj[key]=sms_in_ting[key];
	}
	return return_obj;;
}
function get_JsIn_row_function()
{
	var return_obj = {};
	//copyArray(return_obj,sms_in_row_function);
	for (var key in sms_in_row_function )
	{
		return_obj[key]=sms_in_row_function[key];
	}
	return return_obj;;
}
function get_JsIn_callback()
{
	var return_obj = {};
	//copyArray(return_obj,sms_in_callback);
	for (var key in sms_in_callback )
	{
		return_obj[key]=sms_in_callback[key];
	}
	return return_obj;;
}

분리됨 모듈라이브러리파일을 jsgrid가 사용되는 페이지에서 로드하여 줍니다. 

페이지 부분에 들어가는 소스입니다.

<div id="jsGrid"></div>	  //그리드 위치 선언

자바스크립트 부분
$(document).ready(function(){	
     var db = {
    		loadData: function (filter) {
                return  $.ajax({
                    type: "POST",
                    headers : {
    					"Content-Type" : "application/json",
    					"X-HTTP-Method-Override" : "POST",
    					'X-CSRF-TOKEN': $("#csrf_token").val()
    				},
    				async: true,
                    url: getContextPath()+"/grid/select",
                    data: read_common_data("Appointment_Mapper.a2_list_all_select", filter),
                    error: function (request, status, error) {
                    	alert('code:' + request.status + '\n' + 'message:' + request.responseText + '\n' + 'error:' + error);
                    	}
                });
            }        
        };
    window.db = db;
    window.db.comcode = new Object();    
    window.db.comcode["mt_use"] = [         
    								{ Name: "선택", Id: "" },
						            { Name: "Y", Id: "Y" },
						            { Name: "N", Id: "N" }
						           ];

이제 그리드 등 연결해 줍니다.

now_grid=$("#jsGrid");
    now_pager= $("#pager");
    now_table_custom=$(".config-panel input[type=checkbox]");
    now_db = db;
    /* 달력 */ 
    jsGrid.fields.MySelectControlField = MySelectControlField;

필드값을 설정해줍니다.

 var fields =  [
                   { name: "idx", title:"번호", type:"number", width: 60 ,align: "center" , valueType: "number",readOnly: true},
                   { name: "mdate", title:"게시일", type: "text",  width: 100, align: "center" },
                   { name: "title", title:"제목", type: "text",  width: 300, align: "left" ,readOnly: true},
                   { name: "dname", title:"구분", type: "text",  width: 60, align: "left" ,readOnly: true},
                   { title:"답변상태",width: 100 ,align: "center",
                	   itemTemplate: function(_, item) {
                		   var parent = $("<p>");
                		   var $result_bt = $("<button>")
	   					    .addClass( "btn btn-blue btn_icon" )
                         	.on("click", function() {                             	
                             	
                         	});
               		        $result_bt.append( "답변완료" );
               		     	
               		     var $result_bt1=$(" <button>")
	   					    .addClass( "btn btn-lightblue btn_icon" )
                      	.on("click", function() {                             	
                          	    
                      	});
               		     $result_bt1.append( "미답변" );
               			if(item.answer=='Y')
               			{
               				parent.append($result_bt);	
               			}
               			else
               			{
               				parent.append($result_bt1);
               			}
               		
		       		  
		       		  return parent;		     
                	   }},
                	   {title:"답변메일",width: 100 ,align: "center",
                	   itemTemplate: function(_, item) {
                		   var parent = $("<p>");
                		   var $result_bt = $("<button>")
	   					    .addClass( "btn btn-blue btn_icon" )
                         	.on("click", function() {                             	
                         		email_send(item);
                         	});
               		        $result_bt.append( "보내기" );
               		            		        
               		  		if(item.memailsend=='Y')
	             			{
	             				parent.append("답장보냄");	
	             			}
	             			else
	             			{
	             				parent.append("답장안함");
	             			}
               		  		parent.append(item.memail);               		  	
							parent.append($result_bt);
		       		  return parent;		     
                	   }},                 	   
                   { type: "MySelectControlField", selectButton: true, deleteButton:false, modeSwitchButton: false, editButton: false, width: 120 },
                   { title:"공개상태",width: 100 ,align: "center",
                	   itemTemplate: function(_, item) {
                		   var parent = $("<p>");
                		   var $result_bt = $("<button>")
	   					    .addClass( "btn btn-blue btn_icon" )
                         	.on("click", function() {                             	
                             	
                         	});
               		        $result_bt.append( "공개" );
               		     	
               		     var $result_bt1=$(" <button>")
	   					    .addClass( "btn btn-lightblue btn_icon" )
                      	.on("click", function() {                             	
                          	    
                      	});
               		     $result_bt1.append( "미공개" );
               			if(item.always=='Y')
               			{
               				parent.append($result_bt);	
               			}
               			else
               			{
               				parent.append($result_bt1);
               			}
               		
		       		  
		       		  return parent;		     
                	   }},
                   { title:"공개삭제",width: 100 ,align: "center",
                	   itemTemplate: function(_, item) {
                		   var parent = $("<p>");
                		   var $result_bt = $("<button>")
	   					    .addClass( "btn btn-blue btn_icon" )
                         	.on("click", function() {                             	
                             	naver_send_w(item);
                         	});
               		        $result_bt.append( "공개" );
               		     	
               		     var $result_bt1=$(" <button>")
	   					    .addClass( "btn btn-lightblue btn_icon" )
                      	.on("click", function() {                             	
                          	    naver_send_d(item);
                      	});
               		     $result_bt1.append( "삭제" );
               			
		       		  parent.append($result_bt,'&nbsp;',$result_bt1);
		       		  return parent;		     
                	   }} 
               ];

다음은 인서트나 업데이트시 체크되야할부분과 업데이트인서트 기능을 설정해줍니다.

 var onItemInserting = function(args) {
        // cancel insertion of the item with empty 'name' field
    	f_values_chack(args);
    }
    var onItemUpdating = function(args) {
    	// cancel insertion of the item with empty 'name' field
    	f_values_chack(args);
    }
    var in_filtering=true;
    var in_editing=false;
    var insert_row=false;
    initGrid(now_grid,fields,true,15,10,in_filtering,insert_row,in_editing,true,true,now_pager,now_table_custom,now_db,OnrowClass,onItemInserting,onItemUpdating);

여기서 f_values_chack함수를 만들어줍니다. 

var f_values_chack = function(args)
{
	if(args.item.mt_code === "") {
    	jQuery.each( args.grid.fields, function( key, value ) //반복
    	{
    		if(value.name==="mt_code")
    		{
    			showmessage("경고",value.title+"을(를) 입력값이 누락되었습니다. 확인해 주세요.",2000,'error');
    		}
    	});
        args.cancel = true;
        return;
    }
    if(args.item.mt_code_value === "") {
    	jQuery.each( args.grid.fields, function( key, value ) //반복
     	{
     		if(value.name==="mt_code_value")
     		{
     			showmessage("경고",value.title+"을(를) 입력값이 누락되었습니다. 확인해 주세요.",2000,'error');
     		}
     	});     	
       	args.cancel = true;
       	return;
    }
}

실행해보면 나옵니다. 

JSGRID

 

블로그 이미지

은호아빠

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

,

웹페이지에 상담신청이 왔을시 E-MAIL로 받게 했었다. 알람설정을 했지만 스마트폰을 잘보지 않아

문자로 보게 하는게 좋겠다고 하여 카페24에서 서비스 중이 SMS호스팅을 이용하기로 했다.

https://www.cafe24.com/

 

카페24

No.1 글로벌 전자상거래 플랫폼 '카페24'

www.cafe24.com

SMS서비스 및 비용

적당한 상품을 고르고 신청을 합니다. 

상품메뉴

메뉴가 있는데 발신번호 관리에서 번호를 인증해줍니다.

디지털365치과의원 번호로 인증함

디지털365치과의원 대표전화번호로 인증을 받았습니다.

restTemplate 이용해서 보내봅니다. 소스입니다.

	
    	String url = "https://sslsms.cafe24.com/sms_sender.php";
		String secret_key = "시크릿키";
		Util_Message smsp = Util_Message.getInstance(); //메세지 찍어보는거 
		CommonData result = new CommonData();
		smsp.print_String("/sms_send"); //위치sms_send 
		smsp.print_CommonData(dto); //db에서 읽어온 문자 메시지 내용 		
		RestTemplate restTemplate = new RestTemplate(); 
		HttpHeaders headers = new HttpHeaders();
	    headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
	    LinkedMultiValueMap<String, String> map= new LinkedMultiValueMap<String, String>();
	    map.add("user_id", "유저ID");	    
	    map.add("secure", secret_key); //시크릿키
	    map.add("msg", dto.get("content")); //SMS내용
	    map.add("sphone1", "052"); //인증된 발신번호
	    map.add("sphone2", "710");
	    map.add("sphone3", "5020");
	    map.add("rphone", dto.get("to_phone")); //수신 휴대번호
	    map.add("title", "디지털365치과의원"); //타이틀 ..
	    map.add("rdate", ""); //예약일자
	    map.add("rtime", "");  //예약시간
	    map.add("mode", "1");
	    //map.add("testflag", "Y");	 //테스트시..
	    HttpEntity<LinkedMultiValueMap<String, String>> request2 = new HttpEntity<LinkedMultiValueMap<String, String>>(map, headers);
        
	    String response2 = restTemplate.postForObject( url, request2, String.class );
	    smsp.print_String(response2);

테스트를 해보니 문자가 잘 받아집니다. 

문자메세지

블로그 이미지

은호아빠

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

,

이번 디지털365치과의원 홈페이지를 제작하며 모바일 페이지에 대해 정리합니다.


모바일 페이지 구분을 위해 디바이스를 구분해주는 라이브러리가 있었습니다. 
스프링 모바일 디바이스 입니다. 
순서는 메이븐을 추가해주시고요.
<!-- 모바일 페이지 디바이스 구분 -->
<dependency>
    <groupId>org.springframework.mobile</groupId>
    <artifactId>spring-mobile-device</artifactId>
    <version>1.1.5.RELEASE</version>
</dependency>

web.xml에

<!-- 스프링 모바일 -->

<filter>

  <filter-name>deviceResolverRequestFilter</filter-name>

  <filter-class>org.springframework.mobile.device.DeviceResolverRequestFilter</filter-class>

</filter>

<filter-mapping>

  <filter-name>deviceResolverRequestFilter</filter-name>

  <url-pattern>/*</url-pattern>

</filter-mapping>

필터를 추가합니다. 

servlet-context.xml에 이부분을 수정 추가 합니다. 

<!-- 스프링 모바일부분. -->

<annotation-driven>

<argument-resolvers>

<beans:bean class="org.springframework.mobile.device.DeviceWebArgumentResolver" />

<beans:bean class="org.springframework.mobile.device.site.SitePreferenceWebArgumentResolver" />

</argument-resolvers>

</annotation-driven>

구분

<beans:bean class="org.springframework.mobile.device.view.LiteDeviceDelegatingViewResolver">

  <beans:constructor-arg>

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

  </beans:constructor-arg>

  <beans:property name="mobilePrefix" value="mobile/" />

  <beans:property name="tabletPrefix" value="mobile/" />

  <beans:property name="enableFallback" value="true"/>

</beans:bean>

구분

<interceptors>

   

<beans:bean class="org.springframework.mobile.device.DeviceResolverHandlerInterceptor"></beans:bean>

<beans:bean class="org.springframework.mobile.device.site.SitePreferenceHandlerInterceptor"></beans:bean>

</interceptors>


이러면 경로가 pc의 경우 views/home.jsp 기존대로 호출되구요. 

모바일이나 태블릿의 경우 view/mobile/home.jsp로 호출됩니다. 중간에 mobile가 붙죠 ^^ 

기존 주소 그대로 호출되고 pc와 모바일이 분리되고 컨트롤러는 같이 쓰고 개발이 편리한것 같습니다. 


블로그 이미지

은호아빠

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

,

스프링부트 2.0 에서  멀티 db를 사용하고 mybaits와 mysql 을 사용해보자.. 

/main/resources/application.properties

파일을 열고 환경 설정을 한다. 

#db순서
spring.first.datasource.type=org.apache.tomcat.jdbc.pool.DataSource 
spring.first.datasource.driverClassName=net.sf.log4jdbc.sql.jdbcapi.DriverSpy
spring.first.datasource.jdbc-url=db주소
spring.first.datasource.username=아디
spring.first.datasource.password=패스워드
spring.first.datasource.connectionProperties=useSSL=false;useUnicode=yes;characterEncoding=UTF-8;serverTimezone=UTC 

#db순서
spring.second.datasource.type=org.apache.tomcat.jdbc.pool.DataSource 
spring.second.datasource.driverClassName=com.mysql.jdbc.Driver
spring.second.datasource.jdbc-url=db주소
spring.second.datasource.username=아디.
spring.second.datasource.password=패스워드.
spring.second.datasource.connectionProperties=useSSL=false;useUnicode=yes;characterEncoding=UTF-8;serverTimezone=UTC 

JSP 페이지 사용을 위해서

#JSP를 사용하겠다.
spring.mvc.view.prefix=/WEB-INF/views/
spring.mvc.view.suffix=.jsp

문자를 UTF-8사용 설정

spring.http.encoding.charset=UTF-8 

첫번째 DB파일 설정

import javax.sql.DataSource;

import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class FirstDataSourceConfig {
@Bean 
@ConfigurationProperties(prefix = "spring.first.datasource") 
public DataSource firstDataSource() 
{
return DataSourceBuilder.create().build(); 

@Bean public SqlSessionFactory firstSqlSessionFactory(DataSource firstDataSource, ApplicationContext applicationContext) throws Exception 
{
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean(); 
sqlSessionFactoryBean.setDataSource(firstDataSource); 
sqlSessionFactoryBean.setMapperLocations(applicationContext.getResources("classpath:mapper/first/*.xml")); 
return sqlSessionFactoryBean.getObject(); 
}
@Bean public 
SqlSessionTemplate firstSqlSessionTemplate(SqlSessionFactory firstSqlSessionFactory) throws Exception 
{
return new SqlSessionTemplate(firstSqlSessionFactory); 
}

}

 

2번째 DB파일 설정

import javax.sql.DataSource;

import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class SecondDataSourceConfig {
@Bean 
@ConfigurationProperties(prefix = "spring.second.datasource") 
public DataSource secondDataSource() 
{
return DataSourceBuilder.create().build(); 

@Bean public SqlSessionFactory secondSqlSessionFactory(DataSource secondDataSource, ApplicationContext applicationContext) throws Exception 
{
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean(); 
sqlSessionFactoryBean.setDataSource(secondDataSource); 
sqlSessionFactoryBean.setMapperLocations(applicationContext.getResources("classpath:mapper/second/*.xml")); 
return sqlSessionFactoryBean.getObject(); 
}
@Bean public 
SqlSessionTemplate secondSqlSessionTemplate(SqlSessionFactory secondSqlSessionFactory) throws Exception 
{
return new SqlSessionTemplate(secondSqlSessionFactory); 
}

}

SQL파일은 여기에 위치한다. 

JSP파일은 여기에 위치한다. 

JSP경로

서비스를 만들고

DAO역시 만들어준다.

컨트롤러 뷰 화면 입니다. 

정리완료... 

블로그 이미지

은호아빠

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

,

GOOGLE Chrome

SPRING FRAMEWORK 2018. 9. 18. 12:30

웹페이지 인쇄시 인쇄 되는 페이지를 미리보면서 수정할수 있다면 좋을텐데...

보니 크롬에서 지원한다.. @@ 

MORE TOOLS 에서 RENDERING 를 추가 한다. 

EMULATE 를 PRINT 로 설정한다. 

블로그 이미지

은호아빠

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

,

안드로이드 앱에서  스프링 시큐리티(SPRING SECURITY)로 파일 올리기


스프링 세팅을 해주어야 합니다. 

rest로 이미지를 받을때 스프링 시큐리티에서 접근을 허가 안합니다. 웹브라우저로 했을땐 잘되었는데요.

이문제를 모르고 안드로이드 앱이 문제인줄 알았습니다.


rest는 패턴을 지정해주지 않아도 기본적으로 보안 체크를 합니다. 그래서 security-context.xml 파일에 

이값을 추가합니다. 


<http security="none" pattern="/android/**"/>



저는 ANDROID로 파일을 받을 예정이라 ANDROID하위는 모두 패스 하도록 설정했습니다.


소스는 간단합니다. 

@REQUESTMAPPING(VALUE = "POSTFORMDATA", METHOD=REQUESTMETHOD.POST, 

PRODUCES = "APPLICATION/JSON;CHARSET=UTF-8")

PUBLIC @RESPONSEBODY STRING HANDLEFORMUPLOAD(MULTIPARTFILE FILE,HTTPSERVLETREQUEST REQUEST) THROWS IOEXCEPTION, EXCEPTION {

여기에 DB에 저장하든 파일로 저장하든 로직 이 구현되면 됩니다.

}


안드로이드 소스를 살펴보겠습니다.


private class uploadImageTask extends AsyncTask<Void, Void, String> {


private String url_address;

private MultiValueMap<String, Object> formData;

public uploadImageTask(String url, String values) {
deviceInfo();
this.url_address = url;
FileSystemResource file = new FileSystemResource( values );
formData = new LinkedMultiValueMap<String, Object>();
try {
formData.add("description", "meseoul");
formData.add("file", file);
formData.add("user_name", Global.User_name.getBytes("UTF-8"));
formData.add("s00741", "s00741");
formData.add("good", "good");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
@Override
protected String doInBackground(Void... params) {
String result = "";
Util.Log( "url:> " + url_address );
HttpHeaders requestHeaders = new HttpHeaders();
requestHeaders.setContentType( MediaType.MULTIPART_FORM_DATA);
HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<MultiValueMap<String, Object>>(
formData, requestHeaders );
RestTemplate restTemplate = new RestTemplate( true );
restTemplate.getMessageConverters()
.add(0, new StringHttpMessageConverter( Charset.forName("UTF-8")));
ResponseEntity<String> response = restTemplate.exchange( url_address, HttpMethod.POST, requestEntity,
String.class );
result= response.getBody().toString();
return result;
}
@Override
protected void onPostExecute(String result) {
if(result.equals("YES"))
{
Toast.makeText(mContext, "서버에 저장되었습니다."+Global.User_name, Toast.LENGTH_LONG).show();
}
else
{
Toast.makeText(mContext, "저장을 실패했습니다."+Global.User_name, Toast.LENGTH_LONG).show();
}

}

}


uploadImageTask a = new uploadImageTask( Global.UrlAddress + "/android/postformdata", saveFilePath );
a.execute();


안드로이드 스프링을 사용하였는데요. 

세팅법은 최신버전을 찾아서 하시면 됩니다. 

BUILD.GRADLE 파일에

dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
//noinspection GradleCompatible
implementation 'com.android.support:appcompat-v7:26.1.0'
implementation 'com.android.support.constraint:constraint-layout:1.0.2'
testImplementation 'junit:junit:4.12'
compile 'org.springframework.android:spring-android-rest-template:1.0.1.RELEASE'
compile 'org.codehaus.jackson:jackson-mapper-asl:1.9.11'
compile 'com.fasterxml.jackson.core:jackson-databind:2.3.2'
androidTestImplementation 'com.android.support.test:runner:1.0.1'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
implementation files('libs/jsoup-1.11.2.jar')
implementation files('libs/json-simple-1.1.1.jar')
implementation files('libs/sdk-v1.0.0.jar')

}


안드로이드 UTF-8 전송시 한글 깨지는데 저는 저렇게 해줬습니다. 

formData.add("user_name", Global.User_name.getBytes("UTF-8"));


블로그 이미지

은호아빠

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

,

SPRING FRAMEWORK 시작하기 스프링 시작하기 1

스프링을 시작해보자. ~!!

일단 개발환경 설정

이클립스에서 STS플러그인을 다운받아 설치하여 시작하여도 되지만. SRPING.IO.에 접속하여 STS 툴을 다운받아 설치하는 과정을 보자

http://spring.io/tools/sts/all

최신버전을 다운로드 받아 설치 하자.

설치후 실행을 하고 작업폴더를 설정한다.

그리고 신규 프로젝트를 누르고 

SPRING LEGACY PROJECT 를 선택한다.

그리고 아래쪽 SPRING MVC PROJECT를 선택하고 프로젝트네임설정하고 

FINISH를 누른다.



블로그 이미지

은호아빠

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

,