웹소켓 연결 테스트 소스

1. pom.xml 에 웹소캣 관련 라이브러리 추가

<!--  웹소캣 관련 내용 -->
		<!-- Spring WebSocket 의존성 -->
		<dependency>
		    <groupId>org.springframework</groupId>
		    <artifactId>spring-websocket</artifactId>
		    <version>${org.springframework-version}</version>
		</dependency>
		
		<!-- Spring Messaging 의존성 -->
		<dependency>
		    <groupId>org.springframework</groupId>
		    <artifactId>spring-messaging</artifactId>
		    <version>${org.springframework-version}</version>
		</dependency>
		
		<!-- (선택 사항) STOMP 프로토콜 지원을 위한 의존성 -->
		<dependency>
		    <groupId>org.springframework</groupId>
		    <artifactId>spring-messaging</artifactId>
		    <version>${org.springframework-version}</version>
		</dependency>

2. servlet-context.xml 관련내용 추가 

<beans:beans xmlns="http://www.springframework.org/schema/mvc"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:task="http://www.springframework.org/schema/task"
	xmlns:beans="http://www.springframework.org/schema/beans"
	xmlns:websocket="http://www.springframework.org/schema/websocket"
	xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
		http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/websocket http://www.springframework.org/schema/websocket/spring-websocket.xsd"
	>


<context:component-scan base-package="com.soft.websocket" />
	
	<websocket:handlers>
        <websocket:mapping path="/testwebsockethandler01" handler="WebSocketHandler01"/>
    </websocket:handlers>
    
    <!-- WebSocket 핸들러 Bean 등록 -->
    <beans:bean id="WebSocketHandler01" class="com.soft.websocket.Test_webSocketHandler"/>
	<!-- 스케쥴러파일이 존재하는 패키지 설정 -->

xmlns:websocket="http://www.springframework.org/schema/websocket" 웹소캣 관련 추가 잊지 말 것

3. 자바파일 추가하기 

package com.soft.websocket;

import org.springframework.web.socket.handler.TextWebSocketHandler;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class Test_webSocketHandler extends TextWebSocketHandler {

    private final List<WebSocketSession> sessions = new ArrayList<>();
    private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
    private final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    public Test_webSocketHandler() {
        startMessageSender();
    }

    private void startMessageSender() {
        scheduler.scheduleAtFixedRate(() -> {
            String currentTime = LocalDateTime.now().format(formatter);
            String message = "서버 시간: " + currentTime;

            synchronized (sessions) {
                for (WebSocketSession session : sessions) {
                    if (session.isOpen()) {
                        try {
                            session.sendMessage(new TextMessage("서버에서 보내는 10초마다의 메시지: " + message));
                        } catch (Exception e) {
                            System.err.println("메시지 전송 오류: " + e.getMessage());
                        }
                    }
                }
            }
        }, 0, 3, TimeUnit.SECONDS);
    }

    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        synchronized (sessions) {
            sessions.add(session);
        }
        System.out.println("새로운 WebSocket 연결: " + session.getId());
    }

    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        String payload = message.getPayload();
        System.out.println("수신된 메시지: " + payload);
        /*
        synchronized (sessions) {
            for (WebSocketSession webSocketSession : sessions) {
                if (webSocketSession.isOpen()) {
                    webSocketSession.sendMessage(new TextMessage("서버로부터의 응답: " + payload));
                }
            }
        }
        */
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        synchronized (sessions) {
            sessions.remove(session);
        }
        System.out.println("WebSocket 연결 종료: " + session.getId());
    }

    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
        System.err.println("WebSocket 오류: " + exception.getMessage());
    }

    public void destroy() {
        scheduler.shutdown();
        try {
            if (!scheduler.awaitTermination(5, TimeUnit.SECONDS)) {
                scheduler.shutdownNow();
            }
        } catch (InterruptedException e) {
            scheduler.shutdownNow();
        }
    }
}

4. JSP파일에서 자바스크립트로 호출해서 연결 잘되었는지 확인하기 

<script>
	const host = window.location.host;  // 현재 웹 페이지의 호스트 정보 가져오기
	const protocol = window.location.protocol === 'https:' ? 'wss://' : 'ws://'; // 현재 페이지가 HTTPS라면 wss 사용, 아니면 ws 사용
	const socket = new WebSocket(`${protocol}${host}/testwebsockethandler01`);
	//const socket = new WebSocket('ws://localhost:8080/jspculturedepot/testwebsockethandler01');
	const browserInfo = navigator.userAgent;
	socket.onopen = function() {
	    console.log('웹소켓 연결이 열렸습니다.');
	    socket.send('안녕하세요 서버!');
	    socket.send('나의정보 브라우저정보 : '+browserInfo);
	};
	
	socket.onmessage = function(event) {
	    console.log('서버로부터 메시지:', event.data);
	    //alert('서버로부터 받은 메시지: ' + event.data); // 메시지를 alert 창으로 띄우기
	    socket.send('잘받은 브라우저정보 : '+browserInfo);
	};
	
	socket.onclose = function() {
	    console.log('웹소켓 연결이 닫혔습니다.');
	};
	
	socket.onerror = function(error) {
	    console.error('웹소켓 오류:', error);
};
</script>

호출 주소를 보면 알겠지만 XML에 추가한 

<websocket:handlers>
        <websocket:mapping path="/testwebsockethandler01" handler="WebSocketHandler01"/>
    </websocket:handlers>

이 부분이 PATH로 호출합니다.

블로그 이미지

은호아빠

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

,

HWP파일로 데이터를 다운로드 받고 싶어 하는 고객분이 계셔서

인터넷으로 관련 자료를 검색해보니 누군가 오픈소스로 공개해 놓았다. 

hwplib

https://github.com/neolord0/hwplib

 

GitHub - neolord0/hwplib: hwp library for java

hwp library for java. Contribute to neolord0/hwplib development by creating an account on GitHub.

github.com

인데 이것을 활용해서 테스트로만 만들어 본다. 

		<dependency>
		    <groupId>kr.dogfoot</groupId>
		    <artifactId>hwplib</artifactId>
		    <version>1.1.6</version>
		</dependency>

메이븐을 추가한다.

컨트롤러 소스 부분은 아래와 같다. 

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;

import org.springframework.core.io.InputStreamResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import kr.dogfoot.hwplib.object.HWPFile;
import kr.dogfoot.hwplib.object.bodytext.Section;
import kr.dogfoot.hwplib.object.bodytext.paragraph.Paragraph;
import kr.dogfoot.hwplib.tool.blankfilemaker.BlankFileMaker;
import kr.dogfoot.hwplib.writer.HWPWriter;
/**
 * Handles requests for the application home page.
 */
@Controller
@RequestMapping("/hwp")
public class Hwp_Controller {

	 
		@RequestMapping(value = { "/", "/download" }, method = { RequestMethod.GET, RequestMethod.POST})
	    public ResponseEntity<InputStreamResource> downloadHwpFile() {
	        try {
	            //HWPFile hwpFile = new HWPFile();
	            HWPFile hwpFile = BlankFileMaker.make( );


	            Section s = hwpFile.getBodyText( ).getSectionList( ).get( 0 );
				Paragraph firstParagraph = s.getParagraph( 0 );
				firstParagraph.getText( ).addString( "안녕하세요." );

	            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
	            HWPWriter.toStream(hwpFile, byteArrayOutputStream);
	            byte[] hwpBytes = byteArrayOutputStream.toByteArray();

	            ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(hwpBytes);
	            InputStreamResource inputStreamResource = new InputStreamResource(byteArrayInputStream);

	            HttpHeaders headers = new HttpHeaders();
	            headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=hwpFile.hwp");

	            return ResponseEntity.ok()
	                    .headers(headers)
	                    .contentLength(hwpBytes.length)
	                    .contentType(MediaType.APPLICATION_OCTET_STREAM)
	                    .body(inputStreamResource);
	        } catch (Exception e) {
	            e.printStackTrace();
	            return ResponseEntity.status(500).build();
	        }
	    }
	
}

HWP파일이 생성되어 다운로드 되는것을 확인할수 있다.

블로그 이미지

은호아빠

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

,

전자정부프레임워크 멀티 DB 문자 관련 2개 DB사용하기

전자 정부 프레임워크에 DB를 추가해서 특정 게시판에 특정 시설선택으로 글 작성 시 담당자에게 문자 발송요청건이 생겼네요. 

메인 db를 티베로를 사용하고 있는데 문자 발송은 mysql이라 부랴부랴 하게 되었어요. 

일단 전자정부프레임워크 db2개 관련으로 검색을 하였는데요.

https://www.egovframe.go.kr/home/sub.do?menuNo=37#

 

실행환경 - 예제 다운로드 | 표준프레임워크 포털 eGovFrame

처리중입니다. 잠시만 기다려주십시오.

www.egovframe.go.kr

여기를 안내해주고 예제 소스도 보여주었어요. 

db설정을 3개의 파일로 나누어서 설정을 해주는 소스였는데 저는 2곳으로 나누어서 설정을 하였네요. 

context-datasource.xml,context-mybatis.xml,context-transaction.xml중에서
context-datasource.xml,context-transaction.xml 에만 설정을 했어요.
 
기전전자정부프레임워크는 /src/main/resources/egovframework/egovProps/globals.properties 여기에 db정보를 저장해놓고 사용하던데 그렇게 하지 않고 따로 추가했어요. 

context-datasource.xml에 추가한 내용은 

	<!-- SMS DB 설정  -->
	<beans>   	
	<bean id="dataSource2" class="org.apache.commons.dbcp2.BasicDataSource">	
		<property name="driverClassName" value="net.sf.log4jdbc.DriverSpy"></property>
		<property name="url" value="주소"></property>
		<property name="username" value="아디"></property>
		<property name="password" value="비번"></property>
		<property name="initialSize" value="10" />
        <property name="maxTotal" value="100" />
        <property name="maxIdle" value="100" />
        <property name="minIdle" value="10" />
        <property name="maxWaitMillis" value="5000" />
	</bean>
	
	<bean id="sqlSessionFactory2" class="org.mybatis.spring.SqlSessionFactoryBean">		
		<property name="dataSource" ref="dataSource2" />
		<property name="configLocation" value="classpath:/egovframework/mapper/config/mapper-config.xml" />		
		<property name="mapperLocations" value="classpath:/egovframework/mapper/first/**/*Mapper.xml"></property>
		                                                                   				
	</bean>

	<bean id="transactionManager2"
		class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="dataSource2"></property>
	</bean>	
	<bean id="sqlSession2" class="org.mybatis.spring.SqlSessionTemplate"
		destroy-method="clearCache">
		<constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory2"></constructor-arg>
	</bean>
	
	</beans>

간단히 db를 추가해주었구요.. aop관련설정으로 

context-transaction.xml  아래와 같이 수정해 주었어요. 

	<tx:annotation-driven transaction-manager="transactionManager2"/>

이렇게 하고 나니 별문제 없이 프로젝트가 실행이 되었어요.  이제 서비스를 만들어 볼게요. 

일단 commondata클래스를 만들고요.

import java.util.LinkedHashMap;

public class CommonData extends LinkedHashMap {
	public void put(String key, Object value){
		super.put(key, value);
	}

	public String get(String key) {
		if(super.get(key)!=null)
		{
			return super.get(key).toString();
		}
		else
		{
			return null;
		}		
	}
	
	public Object getObj(String key) {
		return super.get(key);
	}
}

이걸 기반으로 하는 commonDAO

import java.util.List;
import java.util.Map;

import 삭제.CommonData;


public interface commonDAO {  
  public List<Map<String, Object>> selectlist(CommonData in_data , String sql_id) throws Exception;
  public CommonData select(CommonData in_data , String sql_id) throws Exception;
  public int listSearchCount(CommonData in_data , String sql_id) throws Exception;
  public int insert(CommonData in_data , String sql_id) throws Exception ;
  public int update(CommonData in_data , String sql_id) throws Exception;
  public int delete(CommonData in_data , String sql_id) throws Exception; 
  public CommonData selectone(CommonData in_data , String sql_id) throws Exception;
  public String selectstr(CommonData in_data , String sql_id) throws Exception;
  public Long selectLong(CommonData in_data , String sql_id) throws Exception;
  
}

 

 crssms_commonDAOImpl 내용인데요. 

import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.inject.Inject;

import org.apache.ibatis.session.SqlSession;
import org.springframework.stereotype.Repository;

import 삭제.CommonData;


@Repository
public class crssms_commonDAOImpl  implements commonDAO
{
	@Inject
	@Resource(name="sqlSession2")
	private SqlSession session;
	private String namespace = "";
	@Override
	public int insert(CommonData in_data , String sql_id) throws Exception {
	    return session.insert(namespace + sql_id, in_data);
	}
	@Override
	public int update(CommonData in_data , String sql_id) throws Exception {
		return session.update(namespace + sql_id, in_data);
	}
	@Override
	public int delete(CommonData in_data , String sql_id) throws Exception {
		return session.update(namespace + sql_id, in_data);
	}
	@Override
	public int listSearchCount(CommonData in_data, String sql_id) throws Exception {
		// TODO Auto-generated method stub
	    return session.selectOne(namespace + sql_id, in_data);
	}
	@Override
	public CommonData selectone(CommonData in_data, String sql_id) throws Exception {
		// TODO Auto-generated method stub
		return session.selectOne(namespace + sql_id, in_data);
	}
	@Override
	public String selectstr(CommonData in_data, String sql_id) throws Exception {
		// TODO Auto-generated method stub
		return session.selectOne(namespace + sql_id, in_data);
	}
	@Override
	public List<Map<String, Object>> selectlist(CommonData in_data, String sql_id) throws Exception {
		return session.selectList(namespace + sql_id, in_data);
	}
	@Override
	public CommonData select(CommonData in_data, String sql_id) throws Exception {
		// TODO Auto-generated method stub
		return (CommonData) session.selectList(namespace + sql_id, in_data);
	}
	@Override
	public Long selectLong(CommonData in_data, String sql_id) throws Exception {
		// TODO Auto-generated method stub
	    return session.selectOne(namespace + sql_id, in_data);
	}
	
}

common_Service 내용인데요.

import java.util.List;
import java.util.Map;

import 삭제.CommonData;





public interface common_Service {
	  public List<Map<String, Object>> selectlist(CommonData in_data , String sql_id) throws Exception;
	  public CommonData select(CommonData in_data , String sql_id) throws Exception;
	  public int listSearchCount(CommonData in_data , String sql_id) throws Exception;
	  public int insert(CommonData in_data , String sql_id) throws Exception ;
	  public int update(CommonData in_data , String sql_id) throws Exception;
	  public int delete(CommonData in_data , String sql_id) throws Exception; 
	  public CommonData selectone(CommonData in_data , String sql_id) throws Exception;
	  public String selectstr(CommonData in_data , String sql_id) throws Exception;
	  public Long selectLong(CommonData in_data, String sql_id) throws Exception;	
}

Crssms_ServiceImpl 내용인데요

import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import 삭제.CommonData;
import 삭제.persistence.crssms_commonDAOImpl;





@Service
public class Crssms_ServiceImpl implements common_Service {
	
	@Autowired 
	private crssms_commonDAOImpl dao;	
	
	@Override
	public List<Map<String, Object>> selectlist(CommonData in_data, String sql_id) throws Exception {
	
		return dao.selectlist(in_data, sql_id);
	}

	@Override
	public CommonData select(CommonData in_data, String sql_id) throws Exception {
	
		return dao.select(in_data, sql_id);
	}

	@Override
	public int listSearchCount(CommonData in_data, String sql_id) throws Exception {
	
		return dao.listSearchCount(in_data, sql_id);
	}
	@Override
	public int insert(CommonData in_data, String sql_id) throws Exception {
	
		return dao.insert(in_data, sql_id);		
	}

	@Override
	public int update(CommonData in_data, String sql_id) throws Exception {
	
		return dao.update(in_data, sql_id);
	}

	@Override
	public int delete(CommonData in_data, String sql_id) throws Exception {
	
		return dao.delete(in_data, sql_id);
	}

	@Override
	public CommonData selectone(CommonData in_data, String sql_id) throws Exception {
	
		return dao.selectone(in_data, sql_id);
	}

	@Override
	public String selectstr(CommonData in_data, String sql_id) throws Exception {
	
		return dao.selectstr(in_data, sql_id);
	}
	@Override
	public Long selectLong(CommonData in_data, String sql_id) throws Exception {
	
		return dao.selectLong(in_data, sql_id);
	}

}

이렇고 추가한 mybatis파일은 

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="Common_Mapper">
   
	
	<!-- 문자발송 관련 공통 쿼리 처리 기존 쿼리 및 경로 모두 수정할것!! -->
	<insert id="SDK_SMS_SEND">
				INSERT INTO SDK_SMS_SEND (USER_ID, SCHEDULE_TYPE, SUBJECT, SMS_MSG, NOW_DATE, SEND_DATE, CALLBACK, DEST_COUNT, DEST_INFO) VALUES (
						                  '_crs' , 0      , '비밀',#{sMsg}, date_format(now(), '%Y%m%d%H%i%S'),date_format(now(), '%Y%m%d%H%i%S'),#{sMEM_Mobile},'1',
						                  CONCAT('name^',#{sMobile}))
	</insert>
	<insert id="SDK_MMS_SEND_INSERT">
				INSERT INTO SDK_MMS_SEND (USER_ID, SCHEDULE_TYPE, SUBJECT, MMS_MSG, NOW_DATE, SEND_DATE, CALLBACK, DEST_COUNT, DEST_INFO) VALUES (
						                  '_crs' , 0      , '비밀',#{sMsg}, date_format(now(), '%Y%m%d%H%i%S'),date_format(now(), '%Y%m%d%H%i%S'),#{sMEM_Mobile},'1',
						                  CONCAT('name^',#{sMobile}))
						                  
						                  
	</insert>	
</mapper>

context-datasource.xml  설정한곳을 봐서 알겠지만  파일위치는 

/src/main/resources/egovframework/mapper/first/Common_Mapper.xml

이렇습니다.  사용할 땐 이런 식으로 선언해서 사용합니다. 

import 삭제.dto.CommonData;
import 삭제.service.Crssms_ServiceImpl;

@Autowired
private Crssms_ServiceImpl sms_service;



중략 ...
				String sMEM_Mobile = "보내는 번호";
				String sMobile="받는번호";
		    	String sMsg = "메세지";
		    	String sName = "담당자";
                CommonData dto = new CommonData();
                 			dto.put("sMobile", sMobile);
							dto.put("sMEM_Mobile", sMEM_Mobile);
							dto.put("sMsg", sMsg);
                            sms_service.insert(dto, "Common_Mapper.SDK_SMS_SEND");

이렇게 해서 db를 하나 추가해서 문자 발송까지 정리해 보았습니다. 

수고하세요.

블로그 이미지

은호아빠

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

,

스프링 부트 자바 8버전 지원 POM.XML파일 

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
	    <groupId>org.springframework.boot</groupId>
	    <artifactId>spring-boot-starter-parent</artifactId>
	    <version>2.6.2</version>
	</parent>
	<groupId>com.iwillsoft</groupId>
	<artifactId>ex001</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>war</packaging>
	<name>ex001</name>
	<description>TEST</description>
	<properties>
		<java.version>1.8</java.version>
	</properties>
	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web-services</artifactId>
		</dependency>
		<dependency>
			<groupId>org.mybatis.spring.boot</groupId>
			<artifactId>mybatis-spring-boot-starter</artifactId>
			<version>3.0.3</version>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-devtools</artifactId>
			<scope>runtime</scope>
			<optional>true</optional>
		</dependency>
		<dependency>
			<groupId>com.microsoft.sqlserver</groupId>
			<artifactId>mssql-jdbc</artifactId>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>com.mysql</groupId>
			<artifactId>mysql-connector-j</artifactId>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>com.oracle.database.jdbc</groupId>
			<artifactId>ojdbc11</artifactId>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>org.mariadb.jdbc</groupId>
			<artifactId>mariadb-java-client</artifactId>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>org.postgresql</groupId>
			<artifactId>postgresql</artifactId>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-tomcat</artifactId>
			<scope>provided</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.mybatis.spring.boot</groupId>
			<artifactId>mybatis-spring-boot-starter-test</artifactId>
			<version>3.0.3</version>
			<scope>test</scope>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

</project>

 

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>me.meseoul10</groupId>
	<artifactId>Standard_erp</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>war</packaging>

	<name>Standard_erp</name>
	<description>micro_erp</description>

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.0.4.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<java.version>1.8</java.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-jdbc</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.mybatis.spring.boot</groupId>
			<artifactId>mybatis-spring-boot-starter</artifactId>
			<version>1.3.2</version>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-oauth2</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-devtools</artifactId>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<optional>true</optional>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-tomcat</artifactId>
			<scope>provided</scope>
		</dependency>
		<dependency>
		    <groupId>org.apache.tomcat.embed</groupId>
		    <artifactId>tomcat-embed-jasper</artifactId>
		</dependency>
		<dependency>
		    <groupId>javax.servlet</groupId>
		    <artifactId>jstl</artifactId>
		</dependency>
		
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-security</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.security</groupId>
			<artifactId>spring-security-test</artifactId>
			<scope>test</scope>
		</dependency>
		<dependency>
		    <groupId>org.springframework.security</groupId>
		    <artifactId>spring-security-taglibs</artifactId>
		    <version>5.0.7.RELEASE</version>
		</dependency>
		<!-- webflux -->
		<dependency>
		  <groupId>org.springframework.boot</groupId>
		  <artifactId>spring-boot-starter-webflux</artifactId>
		</dependency>
		
	  
		
		<!-- log4jdbc -->
		<dependency>
		    <groupId>org.bgee.log4jdbc-log4j2</groupId>
		    <artifactId>log4jdbc-log4j2-jdbc4.1</artifactId>
		    <version>1.16</version>
		</dependency>
		
		<!-- 파일업로드 다운로드. -->
		<!-- 아파치.. -->
		<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>
		<!-- Apache Commons IO -->
		<!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
		<dependency>
		    <groupId>commons-io</groupId>
		    <artifactId>commons-io</artifactId>
		    <version>2.6</version>
		</dependency>
		<dependency>
			<groupId>org.imgscalr</groupId>
			<artifactId>imgscalr-lib</artifactId>
			<version>4.2</version>
		</dependency>
		
		<dependency>
			<groupId>com.googlecode.json-simple</groupId>
			<artifactId>json-simple</artifactId>
			<version>1.1</version>
		</dependency>
		<!-- 압축파일 -->
		<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-compress -->
		<dependency>
		    <groupId>org.apache.commons</groupId>
		    <artifactId>commons-compress</artifactId>
		    <version>1.15</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/commons-codec/commons-codec -->
		<dependency>
		    <groupId>commons-codec</groupId>
		    <artifactId>commons-codec</artifactId>
		    <version>1.11</version>
		</dependency>
		
		
				


		<!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
		<dependency>
			<groupId>commons-fileupload</groupId>
			<artifactId>commons-fileupload</artifactId>
			<version>1.3.2</version>
		</dependency>
		
		<dependency>
	    	<groupId>org.aspectj</groupId>
	    	<artifactId>aspectjweaver</artifactId>
	    	<version>1.6.1</version>
		</dependency>
		
		<dependency>
		    <groupId>org.apache.commons</groupId>
		    <artifactId>commons-lang3</artifactId>
		    <version>3.4</version>
		</dependency> 
		
		<!-- https://mvnrepository.com/artifact/org.apache.tika/tika-core -->
		<dependency>
		    <groupId>org.apache.tika</groupId>
		    <artifactId>tika-core</artifactId>
		    <version>1.20</version>
		</dependency>
				
		
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>


	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>org.springframework.cloud</groupId>
				<artifactId>spring-cloud-dependencies</artifactId>
				<version>Finchley.SR1</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
		</dependencies>
	</dependencyManagement>
</project>

 

블로그 이미지

은호아빠

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

,

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

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#

,

스프링 리스스 파일 읽고 다운로드 되는 코드를 작성해보자.

이미지 다운로드

웹페이지에 이런경로로 파일 다운로드 요청을 한다. 

리소스 아래에 file이라는 폴더를 생성해 파일을 올린다.

컨트롤러는 아래와 같이 작성한다. 

@RequestMapping("/file_resource")
	public ResponseEntity<byte[]> file_resource(HttpServletRequest request,HttpServletResponse response, String fileName) throws Exception{
		
	    String saveFileName = fileName;
	    String f1 = "한글 파일명.hwp";
		String dirName = "file";//리소스 경로
		if(saveFileName.equals("team"))
		{
			fileName = f1;
		}
		String root_path = request.getSession().getServletContext().getRealPath("/");
		HttpHeaders headers =new HttpHeaders();
		InputStream in=null;
		String filedownloadpath = dirName+File.separatorChar+fileName;
		ClassPathResource resource = new ClassPathResource(filedownloadpath);
		in =resource.getInputStream();
		
		
		headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);		
		headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename*=UTF-8''" + URLEncoder.encode(fileName, "UTF-8"));
		ResponseEntity<byte[]> entity=new ResponseEntity<byte[]>(IOUtils.toByteArray(in), headers, HttpStatus.CREATED);
		in.close();
		return entity;
	}

ClassPathResource resource = new ClassPathResource(filedownloadpath);
in =resource.getInputStream();

리소스 경로에 있는 파일을 읽는다.

 

블로그 이미지

은호아빠

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

,

CommonData 

package com.iwillsoft.domain;

import java.util.LinkedHashMap;

public class CommonData extends LinkedHashMap {
	public void put(String key, Object value){
		super.put(key, value);
	}

	public String get(String key) {
		if(super.get(key)!=null)
		{
			return super.get(key).toString();
		}
		else
		{
			return null;
		}		
	}
	public String get(String key,String value)
	{
		if(super.get(key)!=null)
		{
			return super.get(key).toString();
		}
		else
		{
			return value;
		}	
	}
	public Object getObj(String key) {
		return super.get(key);
	}
}

궁금해 하시는 분들이 계셔서 적어 놓습니다. 

CommonData 값을 리턴할때 

CommonData result_list = first_service.selectone(dto,"Sub01_Mapper.select_one");
			 
			 Iterator keyData4 = result_list.keySet().iterator();
		     while (keyData4.hasNext()) {
		    	String key = ((String)keyData4.next());
		     	String value = result_list.get(key);          
		     	model.addAttribute(key,value);
		     }

 

자바 버전 1.8이상부터 지원하던가 foreach 문으로 값 출력해볼때 

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());
			});

저는 위쪽을 더 자주 사용합니다. 

 

블로그 이미지

은호아빠

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

,

json 전송시 시크립트에서 json 을 만들어 전송을 하였는데 

form에서 json 으로 전송할려면 enctype를 추가해주면 되었다. 

<form id="frmFormSearch" enctype='application/json'method="post" action="${pageContext.request.contextPath}/주소">
<input type="text" class="before" id="before" name="before"  placeholder="기존이름">
<input type="text" class="after" id="after" name="after"  placeholder="변경이름">
<button type="submit" class="btn_search">적용</button>
</form>

서버단 컨트롤러는 이렇게 작성해주면 되었다.

//사이트 컨텍스트 변경시
	@ResponseBody
	@RequestMapping(value = "/경로", method = RequestMethod.POST, produces = "application/json;charset=UTF-8")
	public CommonData image_path_update(@RequestParam Map<String, Object> map) throws Exception{
		smsp.print_String("/경로");
	    Iterator<String> keys = map.keySet().iterator();
	    while( keys.hasNext() ){
	    	String strKey = keys.next();
	    	String strValue = (String) map.get(strKey);
	    	//출력( strKey +":"+ strValue );
	    	
	    }
		
		// 받아온 변수...별작업 없이 리턴		
		return map;
	}

 

블로그 이미지

은호아빠

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

,

Spring mvc samesite cookie 결제 모듈 연동시 세션이 끊어지는 경우

1. 시험환경

    ˙ Spring 5 Framework 

    ˙ Apache Tomcat 8.5

2. 목적

    ˙ Spring Framework 개발환경에서 SameSite 쿠키를 설정하고 동작을 확인한다.

3. 적용

    ① web.xml에서 쿠키 설정을 추가한다.

        - web.xml은 Spring Framework 개발시 한글 설정, 로그인 등 web 화면에서 나타나는 부분을 설정하는 파일이다.

<cookie-config>
    <http-only>true</http-only>
    <secure>true</secure>
</cookie-config>

잘 작동하시나요?

저는 나이스 본인인증에 적용중입니다..

 

참고사이트

https://languagestory.tistory.com/3

블로그 이미지

은호아빠

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

,

SPRING MVC 카카오톡 로그인 해보기

카카오톡 로그인이라기보다 카카오톡 간편 가입이라고 제목을 붙였어야 했나 잠깐 고민이되었지만 이게 중요한게 아니니 넘어 가야겠다. 

카카오톡 로그인을 하기 위해선 카카오톡 개발자 사이트에 애플리케이션을 등록해야하는데요. 

developers.kakao.com/console/app

 

카카오계정 로그인

여기를 눌러 링크를 확인하세요.

accounts.kakao.com

애플리케이션추가하기

애플리케이션을 추가를 합니다. 입력만 하면 되는거라 어렵지 않을것이에요 입력을 하고 나면 생성이 되는데요. 

요약정보를 눌러보면 앱키를 발급해줘요 저는 자바스크립트로 로그인을 할건데요. 여기서 2가지 앱키가 필요해요. 

JAVASCRIPT 키와 REST API 키가 필요합니다. 

옆에 메뉴를 눌러보다가 보면 플랫폼이라고 보이는데요 거기에 WEB을 추가합니다. 

WEB
WEB를 추가해요. 
카카오 로그인

카카오 로그인을 ON으로 활성화 시켜주세요. 

동의 항목을 설정을 하시구요. 

 

동의항목

이러면 대충 개발자 사이트에선 설정이 된거 같아요. 

여기서 중요한점은 REDIRECT URI 인데요 인데요. 제가 로그인하겠다고 앱키와 넘겨주면 코드값을 받을 주소를 입력하는곳이에요. ^^ 

그럼 세팅이 되었다면 계속 진행해볼께요. 

메뉴를 이동해야 하는데요. 문서 > 카카오로그인 > 이해하기 

여기로 이동해요. developers.kakao.com/docs/latest/ko/kakaologin/common

 

Kakao Developers

카카오 API를 활용하여 다양한 어플리케이션을 개발해보세요. 카카오 로그인, 메시지 보내기, 친구 API, 인공지능 API 등을 제공합니다.

developers.kakao.com

그럼 아래쪽에 카카오 로그인 JAVASCRIPT가 보이는데요. 

로그인 설명

여기에 나와 있는대로 차근차근 따라하시면 되요. 

<!-- 카카오 로그인 -->              
<script type="text/javascript" src="https://developers.kakao.com/sdk/js/kakao.min.js" charset="utf-8"></script>
<script type="text/javascript">
//초기화 시키기. 
$(document).ready(function(){	
	Kakao.init('자바스크립트 앱키 입력');
	Kakao.isInitialized();
});
</script>

로그인 하는페이지에 카카오라이브러리를 초기화 시켜주시고요. 

로그인 버튼을 만드시고 실행되게 하세요. 

<script type="text/javascript">
function loginWithKakao() {
  Kakao.Auth.authorize({
	  redirectUri: 'http://localhost:8080/user/loginpage_kakao_callback'
	});
  }
</script>

로그인버튼을 누르면 이렇게 실행이 될껀데요. 그럼 서버에서 코드값을 받아서 넘어와요. 

코드값으로 토근을 값을 받아와야 하는데요 이건 스크립트로 지원하지 않아요 REST API를 사용해서 해야 해요.

컨트롤러 단에서 loginpage_kakao_callback이 호출될때 코드값으로 토근값을 받아와서 페이지로 넘기도록 할게요. 

//카카오톡 로그인.. 
		@RequestMapping(value = "/loginpage_kakao_callback", method = RequestMethod.GET)
		public String loginpage_kakao_callback(HttpServletRequest request, HttpServletResponse response,
				HttpSession session, Model model) throws Exception {
			UrlPathHelper urlPathHelper = new UrlPathHelper();
			String originalURL = urlPathHelper.getOriginatingRequestUri(request);
			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());
			}
			String url = "https://kauth.kakao.com/oauth/token";
			RestTemplate restTemplate = new RestTemplate();
			HttpHeaders headers = new HttpHeaders();
			headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
			LinkedMultiValueMap<String, String> map = new LinkedMultiValueMap<String, String>();
			map.add("client_id", "REST 앱키를 입력하세요.");
			String redirect_url = "http://localhost:8080/user/loginpage_kakao_callback";
			map.add("redirect_uri", redirect_url);
			map.add("grant_type", "authorization_code");
			map.add("code", dto.get("code"));
            
			HttpEntity<LinkedMultiValueMap<String, String>> request2 = new HttpEntity<LinkedMultiValueMap<String, String>>(
					map, headers);
			CommonData response2 = restTemplate.postForObject(url, request2, CommonData.class);
			map.clear();
			model.addAttribute("access_token", response2.get("access_token"));
			return "/user/loginpage_kakao_callback";
		}

code 값으로 access_token 값을 받아와요. 

그럼 이것으로 이제 사용자 정보를 받아와 볼께요. 

<script type="text/javascript">
var kakao_message = new Object();   
	$(document).ready(function(){	
		var ACCESS_TOKEN= $("#access_token").val();
		//할당받은 토근을  세팅
		Kakao.Auth.setAccessToken(ACCESS_TOKEN);
		console.log(Kakao.Auth.getAccessToken());		
		Kakao.API.request({
		    url: '/v2/user/me',
		    success: function(response) {
		        console.log(response);
		        kakao_message['id']=response['id'];
				kakao_message['email']=response['kakao_account']['email'];
				kakao_message['nickname']=response['kakao_account']['profile']['nickname'];
		        console.log(kakao_message);
		        var m_uid = 'KAKAO_'+kakao_message['id'];
				console.log(""+window.location.hostname+"");
				var data = JSON.stringify({
					uid : m_uid
				 , uname : kakao_message['nickname']
				 , uemail : kakao_message['email']
				 , join_pass : 'KAKAO'
				});
				// 로그인시 서버에서 넘어왔음.. 
				//로그인정보가 있다면 로그인 시도하기.. 
				var url = '/user/userid_duplicate_check';
				getPostData(url,data,callback_userid_duplicate_check, false);	
				
				if(!is_userid) //sns가입된 id가 있다면 로그인 시도.
				{
					url = '/user/naver_kakao_sns_login';					
					getPostData(url,data,callback_join_ok, false);
				}
				else if(is_userid) //sns로 가입된 id가 없다면 가입시도..
				{
					$("#i_id").val(m_uid);
					$("#i_name").val(kakao_message['nickname']);
					$("#i_email").val(kakao_message['email']);
				}
		    },
		    fail: function(error) {
		        console.log(error);
		    }
		});
	});
	
</script>

loginpage_kakao_callback 에서 페이지 로드가 되면 발급 받은 토근으로 정보를 받아와야하는데요. 

Kakao.API.request({ url: '/v2/user/me' }); 를 호출 하면 되요. 

로그인에 성공을 하면 닉네임과 이메일 그리고 id를 받아올수 있었어요. 

이제 이걸로 제가 간편가입을 한적이 있는지 체크를 해볼텐데요. ajax로 알아봐요.

uid로 체크를 하는데요.

체크하는 컨트롤러는 이렇게 해봤어요. 

@RequestMapping(value = "/userid_duplicate_check", method = RequestMethod.POST)
	@ResponseBody
	public CommonData userid_duplicate_check(HttpServletRequest request, HttpServletResponse response, @RequestBody CommonData dto, Model model) throws Exception
	{
		Util_Message smsp = Util_Message.getInstance();
		CommonData result = new CommonData();
		int cnt = first_service.listSearchCount(dto, "MemberMapper.userid_duplicate_check");
		if (cnt > 0)
		{
			result.put("result", "id_duplication");
			return result;
		}
		result.put("result", "ok");
		return result;
	}

간단하게 id중복체크로 가입된적이 있는지 확인을해요.

 <select id="userid_duplicate_check" resultType="int"> 
        SELECT count(1)
          from tb2019_member
     <trim prefix="WHERE" prefixOverrides="AND|OR">
	  	<if test="uid != null and uid != ''">
	   		and uid = #{uid}
	  	</if>
	 </trim>
    </select>

체크가 끝났으면요.

var callback_userid_duplicate_check = function(result)
{
	console.log(result);
	if(result['result']=='id_duplication')
	{	
		is_userid = false;
	}
	else if(result['result']=='ok')
	{													
		is_userid = true;			
	}
}

is_userid값을 확인을 하는데요. 있다면 false값을 넣어 바로 로그인으로 넘기고 없다면 가입하는 절차를 거쳐야 해요. 

휴대폰 번호를 추가로 입력을 받아야해서 카카오에서 받은 이름과 이멜은 입력해주시고요 휴대폰번호만 입력하도록 해요.  이게 필요없다면 자동가입시키시면 되요. 

패스워드는 제가 임의로 생성해서 넣어두었는데요 SNS로 로그인시 아디나 비번을 직접 입력할게 아니라서 임의로 넣었어요. 

그리고 가입처리를 하고나서 로그인 처리를 하시면 됩니다. 

DB는 기존 홈페이지 가입시 쓰는 테이블과 혼용해서 사용중이고요. JOIN_PASS 값으로 카카오 네이버 홈페이지가입 이렇게 처리를 했어요. 이후 방법은 일반적인 홈페이지 내용과 동일해서 이만 줄일게요. 

 

블로그 이미지

은호아빠

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

,