2017년 3월 14일 화요일

ajax에서 return 값을 json 형태 또는 text 형태로 반환 받았을 경우 한글이 깨지는 경우의 대처 방법

ajax 호출 뒤 결과 메시지의 한글이 ???로 표기되어 나타날 경우, 여러가지 방법을 사용해 봤다.
사용해 본 결과들에 대해서 몇 가지 정리해보면,

@RequestMapping(value = "/upload")
@ResponseBody
public String upload(MultipartHttpServletRequest req, HttpServletRequest request) throws IOException {
 :
 :
  strResult = URLEncoder.encode(strResult, "UTF-8");
 :
 :
  return strResult;
}

Spring의 Controll 단에서 return 되는 문자에 대해서 URLEncoder.encode를 사용해서 문제를 해결했다.
Client단의 ajax success 부분에 문자를 변환해서 처리함.
var Ca = /\+/g;
var fileInfo = decodeURIComponent(data.replace(Ca, " "));

근데 다른 사람의 브라우저에서는 undefined라는 메시지가 나오면서 ajax 결과가 정상적으로 반영되지 않는 문제를 발견했다.
모든 사람의 브라우저가 다 안되는 것이 아니라 몇 몇 브라우저에서 문제가 발생했다.
charset의 문제로 보여지며 utf-8 이 강제로 iso-8859-1 변환되고 있는 것이 아닌가 싶다.

Spring의 Controll 단에서 utf-8로 강제로 변환해서 처리하고 나니 기존의 오류가 나던 브라우저들도 문제 없이 동작함.

@RequestMapping(value = "/upload", produces = "application/text; charset=utf8")
@ResponseBody
public String upload(MultipartHttpServletRequest req, HttpServletRequest request) throws IOException {
 :
 :
}

2017년 3월 10일 금요일

Spring Framework에서 JavaMailSender로 메일 보내기.

Spring의 JavaMailSender를 추가하기 위해서는 spring-context-support jar 파일을 반드시 lib폴더에 추가해야 한다.
또한 javax.mail 관련 jar 파일도 포함 해야 한다.
maven repository에서 가져올 경우

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${version.spring}</version>
</dependency>

<dependency>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
<version>1.4.7</version>
</dependency>

상기의 2개를 추가해서 lib폴더에 추가.

아래는 JavaMailSender를 위한 Java Config 설정이다.

import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.JavaMailSenderImpl;
:
:

@Bean
public static JavaMailSender mailSender() {
JavaMailSenderImpl mailSenderImpl = new JavaMailSenderImpl();
mailSenderImpl.setHost("smtp.naver.com");
mailSenderImpl.setPort(587);
mailSenderImpl.setUsername("사용자 메일 계정");
mailSenderImpl.setPassword("비밀번호");
mailSenderImpl.setDefaultEncoding("UTF-8");

Properties javaMailProps = new Properties();
javaMailProps.put("mail.smtp.auth", true);
javaMailProps.put("mail.smtp.starttls.enable", true);

mailSenderImpl.setJavaMailProperties(javaMailProps);

return mailSenderImpl;
}

Service로 호출을 하기 위해서 먼저 Interface를 정의한다.

package org.uniworks.groupware.service;

/**
 * @author gomoosin
 *
 */
public interface EmailSender {
public <T> boolean emailSender(T report);
}

EmailSender를 구현한 클래스는 아래와 같다.

package org.uniworks.groupware.service.internal;

import javax.mail.internet.MimeMessage;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.mail.javamail.MimeMessagePreparator;
import org.springframework.stereotype.Service;
import org.uniworks.groupware.service.EmailSender;

/**
 * @author gomoosin
 *
 */
@Service
public class EmailSenderImpl implements EmailSender {
private static final Logger logger = LoggerFactory.getLogger(EmailSenderImpl.class);
@Autowired JavaMailSender javaMailSender;

/* (non-Javadoc)
* @see org.uniworks.groupware.service.EmailSender#emailSender(java.lang.Object)
*/
@Override
public <T> boolean emailSender(T report) {
// TODO Auto-generated method stub
logger.debug("Sending report by email....");
boolean retVal = false;

try {
            final String emailTo = "test01@gmail.com";
            final String emailFrom = "test01@naver.com";
            final String subject = "test subject";
            final String message = (String) report;

            javaMailSender.send(new MimeMessagePreparator() {

                @Override
                public void prepare(MimeMessage paramMimeMessage) throws Exception {
                    MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(paramMimeMessage, true, "UTF-8");

                    mimeMessageHelper.setTo(emailTo);
                    mimeMessageHelper.setFrom(emailFrom);
                    mimeMessageHelper.setSubject(subject);
                    mimeMessageHelper.setText(message);

                    /*
                    final File file = new File("test filename");

                    mimeMessageHelper.addAttachment(MimeUtility.encodeText("filename"), new InputStreamSource() {

                        @Override
                        public InputStream getInputStream() throws IOException {
                            // TODO Auto-generated method stub
                            return new FileInputStream(file);
                        }
                    });
*/                  
                };
            });

            retVal = true;
        } catch (Exception e) {
            logger.error("Can't send email... " + e.getMessage(), e);
        }

return retVal;
}

}

위에 만든 Service를 호출해서 테스트한 테스트 케이스는 아래와 같다.

package org.uniworks.groupware.service;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.transaction.annotation.Transactional;
import org.uniworks.groupware.common.config.AppConfig;
import org.uniworks.groupware.common.config.BoneCPConfig;

/**
 * @author gomoosin
 *
 */
@RunWith(SpringJUnit4ClassRunner.class)
public class EmailSenderTest {
@Autowired private EmailSender emailSender;

@Test
public void emailSenderTest() {
emailSender.emailSender("text message......");
}
}

2015년 11월 2일 월요일

import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 정규표현식을 이해하기 위한 테스트 클래스
 * . : 임의의 한 문자(필수)를 의미
 * ? : 바로 앞에 문자가 없거나 하나가 있음을 의미
 * * : 바로 앞에 문자가 없거나 하나이상 반복을 의미
 * + : 바로 앞에 문자가 하나 이상 반복을 의미
 * ^ : 문자열의 시작을 의미
 * [^] : ^이후의 괄호안 형식을 제외함을 의미
 * $ : 문자열의 끝을 의미
 * [] : []안의 형식 일치를 의미
 * {} : {}앞 문자열(혹은 문자) 반복 갯수를 의미
 * () : ()안의 내용을 하나의 묶음으로 사용함을 의미
 * | : or 연산을 의미
 * [0-9] : (부터 - 까지)의 숫자를 의미
 * [a-z] : (부터 - 까지)의 소문자를 의미
 * [a-zA-Z] : (부터 - 까지)의 대,소문자를 의미
 * \p(Alpha) : 대,소문자 알파벳을 의미
 * \p(Digit) : 숫자를 의미
 * \p{Alnum} : 대/소문자 알파벳, 숫자를 의미
 * \d : 숫자를 의미
 * \D : 숫자가 아닌 것을 의미
 * \s : 공백 문자를 의미
 * \S : 공백 문자가 아닌 나머지 문자를 의미
 * \w : 알파벳이나 숫자
 * \W : 알파벳이나 숫자를 제외한 문자
 * \ : 정규표현식 역슬래시(\)는 확장 문자. 역슬래시 다음에 일반 문자가 오면 특수문자로 취급하고 역슬래시 다음에 특수문자가 오면 그 문자 자체를 의미
 * (?i) : 앞 부분에 (?i)라는 옵션을 넣어주면 대소문자를 구분하지 않음
 *
 * 사용예
 * 1) 숫자만 : ^[0-9]*$
 * 2) 영문자만 : ^[a-zA-Z]*$
 * 3) 한글만 : ^[가-힣]*$
 * 4) 영어 & 숫자만 : ^[a-zA-Z0-9]*$
 * 5) E-Mail : ^[_a-z0-9-]+(.[_a-z0-9-]+)*@(?:\\w+\\.)+\\w+$            
 * 6) 휴대폰 : ^01(?:0|1|[6-9]) - (?:\d{3}|\d{4}) - \d{4}$
 * 7) 일반전화 : ^\d{2.3} - \d{3,4} - \d{4}$
 * 8) 주민등록번호 : \d{6} \- [1-4]\d{6}
 * 9) IP 주소 : ([0-9]{1,3}) \. ([0-9]{1,3}) \. ([0-9]{1,3}) \. ([0-9]{1,3})
 *
 */

/** @author
 * 정규표현식 이해를 하기 위해서 만들어 본 클래스입니다.
 * 여기 예제의 대부분은 http://www.java2go.net/java/java_regex.html 에서 참조했습니다.
 * 작성일자 : 2015.11.03
 */
public class RegExTest {

/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
RegExTest regExTest = new RegExTest();
regExTest.regEx01();
regExTest.regExMailIDCheck();
regExTest.regEx02();
regExTest.regEx03();
regExTest.regEx04();
regExTest.regEx05();
regExTest.regEx06();
}

/**
* Pattern 객체는 Perl 문법과 비슷한 형태로 정의된 정규표현식을 나타낸다.
* 문자열로 정의한 정규표현식은 사용되기전에 반드시 Pattern클래스의 인스턴스로 컴파일되어야 한다.
* 컴파일된 패턴은 Matcher객체를 만드는데 사용되며, Matcher객체는 임의의 입력문자열이 패턴에 부합되는지 여부를 판가름하는 기능을 담당.
*/
private void regEx01() {
//정규표현식 적용 a로 시작하며, a 다음 아무 문자 1개만, 마지막은 c로 끝남
String regex = "^a.c$";
System.out.println("regEx01-abc : " + "abc".matches(regex)); //true
System.out.println("regEx01-abbc : " + "abbc".matches(regex)); //false
System.out.println("regEx01-a*c : " + "a*c".matches(regex)); //true
System.out.println("regEx01-a1c : " + "a1c".matches(regex)); //true
System.out.println("regEx01-a1cc : " + "a1cc".matches(regex)); //false

Pattern p = Pattern.compile("a*b");
Matcher m = p.matcher("aaaaaab");
boolean b = m.matches();

if (b) {
System.out.println("match");
} else {
System.out.println("not match");
}
}

//Mail 주소 체크.
private void regExMailIDCheck() {
String regex = "^[_a-z0-9-]+(.[_a-z0-9-]+)*@(?:\\w+\\.)+\\w+$"; //소문자만 인식
System.out.println("test001@hotmail.com : " + "test001@hotmail.com".matches(regex)); //true
System.out.println("test001@bbb.co.kr : " + "test001@bbb.co.kr".matches(regex)); //true
System.out.println("test001@bbb : " + "test001@bbb".matches(regex)); //false
System.out.println("TEST001@BBB.CO.KR : " + "TEST001@BBB.CO.KR".matches(regex)); //false

regex = "^[_a-zA-Z0-9-]+(.[_a-zA-Z0-9-]+)*@(?:\\w+\\.)+\\w+$"; //대문자도 인식할 수 있도록 변경
System.out.println("test001@hotmail.com : " + "test001@hotmail.com".matches(regex)); //true
System.out.println("test001@bbb.co.kr : " + "test001@bbb.co.kr".matches(regex)); //true
System.out.println("test001@bbb : " + "test001@bbb".matches(regex)); //false
System.out.println("TEST001@BBB.CO.KR : " + "TEST001@BBB.CO.KR".matches(regex)); //true
System.out.println("test001@bbb!.com : " + "test001@bbb!.com".matches(regex)); //false
}

/**
* 문자열 치환하기
* appendReplacement 메소드는 일치하는 패턴이 나타날 때까지의 모든 문자들을 버퍼로 옮기고 찾아진 문자열 대신 교체 문자열로 채워 넣는다.
* appendTail 메소드는 캐릭터 시퀀스의 현재 위치 이후의 문자들을 버퍼에 복사해 넣는다.
*/
private void regEx02() {
Pattern p = Pattern.compile("cat");
Matcher m = p.matcher("one cat two cats in the yard");

StringBuffer sb = new StringBuffer();
while(m.find()) {
m.appendReplacement(sb, "dog");
}
m.appendTail(sb);
System.out.println(sb.toString());
}

/**
* 이메일 주소 유효검사
*/
private boolean isValidEmail(String email) {
Pattern p = Pattern.compile("^(?:\\w+\\.?)*\\w+@(?:\\w+\\.)+\\w+$");
Matcher m = p.matcher(email);
return m.matches();
}

/**
* 이메일 주소 유효성 테스트
*/
private void regEx03() {
String[] emails = {"test@abc.com", "a@.com", "abc@mydomain", "ABC@mydoamin.COM", "chungwan.park@mydomin.co.kr"};

for (int i = 0; i < emails.length; i++) {
if (isValidEmail(emails[i])) {
System.out.println(emails[i]);
}
}
}

/**
* HTML 태그 제거
*/
private String stripHTML(String htmlStr) {
Pattern p = Pattern.compile("<(?:.|\\s)*?>");
Matcher m = p.matcher(htmlStr);
return m.replaceAll("");
}

private void regEx04() {
String htmlStr = "<html><body><h1>Java2go.net</h1> <p>Linuxwan's Personal Workspace...</p></body></html>";
System.out.println(stripHTML(htmlStr));
}

/**
* HTML 링크 만들기
*/
private String linkedText(String sText) {
Pattern p = Pattern.compile("(http|https|ftp)://[^\\s^\\.]+(\\.[^\\s^\\.]+)*");
Matcher m = p.matcher(sText);

StringBuffer sb = new StringBuffer();
while(m.find()) {
m.appendReplacement(sb, "<a href='" + m.group() + "'>" + m.group() + "</a>");
}
m.appendTail(sb);

return sb.toString();
}

private void regEx05() {
String strText = "My linked URL is http://wans-devstory.blogspot.kr/search/label/Android.";
System.out.println(linkedText(strText));
}

/**
* 금지어 필터링 하기
*/
private String filterText(String sText) {
Pattern p = Pattern.compile("fuck|shit|개새끼", Pattern.CASE_INSENSITIVE);
Matcher m = p.matcher(sText);

StringBuffer sb = new StringBuffer();
while(m.find()) {
m.appendReplacement(sb, maskWord(m.group()));
}
m.appendTail(sb);

return sb.toString();
}

private String maskWord(String word) {
StringBuffer buff = new StringBuffer();
char[] ch = word.toCharArray();
for (int i = 0; i < ch.length; i++) {
if (i < 1) {
buff.append(ch[i]);
} else {
buff.append("*");
}
}
return buff.toString();
}

private void regEx06() {
String sText = "Shit! Read the fucking manual. 개새끼야.";
System.out.println(filterText(sText));
}
}

2015년 9월 7일 월요일

jQuery UI의 tab을 동적으로 생성하는 방법

jQuery UI의 tab을 동적으로 생성하는 방법.

$(function() {
$('#main_tab').tabs();
});

tab을 생성하는 함수.
function fn_tabAdd() {
no++;
var tabs = $("#main_tab").tabs();
var ul = tabs.find("ul");

$("<li><a href='#tabs-" + no + "'>" + "Tab No." + no + "</a></li>").appendTo(ul);
$("<div id='" + "tabs-" + no + "'>" + "Tabs No." + no + "</div>" ).appendTo(tabs);
tabs.tabs("refresh");
}

html파일.
..
<div id="main_tab">
<ul id="tab_head">
<li><a href="#tabs-0">Tab 1</a></li>
</ul>
<div id="tabs-0">Tab 01</div>
</div>
..

2015년 3월 18일 수요일

파이썬 프로그래밍 - Chapter 03

string.py


fred = "Why do gorillas have big nostrils? Big fingers!!"
print (fred)

fred = 'Why do gorillas have big nostrils? Big fingers!!'
print (fred)

fred = '''How do dinosaurs pay their bills?
With tyrannosaurus checks!'''
print (fred)

silly_string = '''He said, "Aren't can't shouldn't wouldn't."'''
print (silly_string)

#escape
single_quote_str = 'He said, "Aren\'t can\'t shouldn\'t wouldn\'t."'
print (single_quote_str)

double_quote_str = "He said, \"Aren't can't shouldn't wouldn't.\""
print (double_quote_str)

myscore = 1000
message = 'I scored %s points'
print (message % myscore)

#placeholder
nums = 'What did the number %s say to the number %s? Nice belt!!'
print (nums % (0, 8))

myletter.py


spaces = ' ' * 25
print('%s 12 Butts Whnd' % spaces)
print('%s Twinklebottom Heath' % spaces)
print('%s West Snoring' % spaces)
print('')
print('')
print('Dear Sir')
print('')
print('I wish to report that tiles are missing from the')
print('outside toilet roof.')
print('I think it was bad wind the other night that blew them away.')
print('')
print('Regards')
print('Malcolm Dithering')

List.py


wizard_list = 'spider legs, toe of frog, eye of newt, bat wing, slug butter, snake dandruff'
print(wizard_list)

wizard_list = ['spider legs', 'toe of frog', 'eye of newt', 'bat wing', 'slug butter', 'snake dandruff']
print(wizard_list)
print(wizard_list[2])

wizard_list[2] = 'snail tongue'
print(wizard_list)
print(wizard_list[2:5])

some_numbers = [1, 2, 5, 10, 20]
print(some_numbers)

some_things = ['Which', 'Witch', 'Is', 'Which']
print(some_things)

number_and_strings = ['Why', 'was', 6, 'afraid', 'of', 7, 'because', 7, 8, 9]
print(number_and_strings)

numbers = [1, 2, 3, 4]
strings = ['I', 'kicked', 'my', 'toe', 'and', 'it', 'is', 'sore']
mylist= [numbers, strings]
print(mylist)

wizard_list.append('bear burp')
print(wizard_list)

wizard_list.append('mandrake')
wizard_list.append('hemlock')
wizard_list.append('swamp gas')

print(wizard_list)

del wizard_list[5]
print(wizard_list)

del wizard_list[8]
del wizard_list[7]
del wizard_list[6]
print(wizard_list)

list1 = [1, 2, 3, 4]
list2 = ['I', 'tripped', 'over', 'and', 'hit', 'the', 'floor']
print(list1 + list2)
list3 = list1 + list2
print(list3)

list1 = [1, 2]
print(list1 * 5)

#tuple
fibs = (0, 1, 1, 2, 3)
fibs2 = (4, 5, 6, 7, 8)
print(fibs[3])
print(fibs * 2)
print(fibs + fibs2)

#map
favorite_sports = {'Ralph Williams' : 'Football',
                   'Michael Tippett' : 'Basketball',
                   'Edward Elgar' : 'Baseball',
                   'Rebecca Clarke' : 'Netball',
                   'Ethel Smyth' : 'Badminton',
                   'Frank Bridge' : 'Rugby'}
print(favorite_sports['Rebecca Clarke'])

del favorite_sports['Ethel Smyth']
print(favorite_sports)

favorite_sports['Ralph Williams'] = 'Ice Hockey'
print(favorite_sports)

파이썬 프로그래밍 - Chapter 02

variable.py


found_coins = 20
magic_coins = 10
stolen_coins = 3
msg = "found_coins + magic_coins * 365 - stolen_coins * 52 = %s"
sum = found_coins + magic_coins * 365 - stolen_coins * 52
print (msg % sum)

stolen_coins = 2
sum = found_coins + magic_coins * 365 - stolen_coins * 52
print (msg % sum)

magic_coins = 13
sum = found_coins + magic_coins * 365 - stolen_coins * 52
print (msg % sum)

2014년 12월 2일 화요일

C#으로 구현한 하위 폴더에서 특정 확장자의 파일 갯수를 카운트하는 프로그램.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.IO;
using System.Windows.Forms;

namespace FileCounter
{
    public partial class FileCounter : Form
    {
        private int counter = 0;

        public FileCounter()
        {
            InitializeComponent();
        }

        private void label1_Click(object sender, EventArgs e)
        {

        }

        private void txtFolderPath_TextChanged(object sender, EventArgs e)
        {

        }

        private void btnOpenFolderDlg_Click(object sender, EventArgs e)
        {
            FolderBrowserDialog folderBrowserDialog = new FolderBrowserDialog();
            folderBrowserDialog.SelectedPath = @"C\";

            if (folderBrowserDialog.ShowDialog() == DialogResult.OK)
            {
                txtFolderPath.Text = folderBrowserDialog.SelectedPath;
            }
        }

        private void btnFileCount_Click(object sender, EventArgs e)
        {
            //파일을 찾아야 폴더 선택 여부 확인
            if (txtFolderPath.Text == "" || txtFolderPath.Text.Length < 1)
            {
                MessageBox.Show("대상 폴더를 선택하세요. !!");
                return;
            }

            //찾아야 할 파일 확장자 입력 여부 확인
            if (txtFileExt.Text == "" || txtFileExt.Text.Length < 1)
            {
                MessageBox.Show("파일 확장자를 입력하세요. !!");
                return;
            }

            lbCount.Text = "";
            counter = 0;

            //Root폴더 아래의 파일 검색
            RootSearchFileExtCounter(txtFolderPath.Text, txtFileExt.Text);
            //하위 폴더 아래의 파일 검색
            DirSearchFileExtCounter(txtFolderPath.Text, txtFileExt.Text);
           
            lbCount.Text = "" + counter;          
        }

        private void btnCancel_Click(object sender, EventArgs e)
        {
            //종료
            this.Close();
        }

        //Root폴더 아래의 파일을 검색
        void RootSearchFileExtCounter(string sDir, string sExt)
        {
            //입력된 파일 확장자에서 순수한 확장자만 추출
            string strExt = sExt;
            if (sExt.IndexOf("*") > -1) strExt = strExt.Replace("*", "");
            if (sExt.IndexOf(".") > -1) strExt = strExt.Replace(".", "");

            //검색을 위한 패턴 생성
            string searchPattern = "*." + strExt;

            string[] rootFileEntries = Directory.GetFiles(sDir, searchPattern);
            foreach (string rootFileName in rootFileEntries)
            {
                //순수 확장자가 파일명의 끝에 있는지 체크해서 카운트.
                if (rootFileName.EndsWith(strExt))
                {
                    counter = counter + 1;
                }
            }
        }

        void DirSearchFileExtCounter(string sDir, string sExt)
        {
            string strExt = sExt;
            if (sExt.IndexOf("*") > -1) strExt = strExt.Replace("*", "");          
            if (sExt.IndexOf(".") > -1) strExt = strExt.Replace(".", "");          

            string searchPattern = "*." + strExt;

            try
            {              
                //Root폴더 아래의 하위 폴더 갯수 만큼 Looping
                foreach (string d in Directory.GetDirectories(sDir))
                {
                    //searchPattern에 맞는 파일 목록을 가져온다.
                    string[] searchFileEntries = Directory.GetFiles(d, searchPattern);
                    //가져온 파일 목록만큼 Looping
                    foreach (string sFileName in searchFileEntries)
                    {
                        //순수 확장자가 파일명의 끝에 있는지 체크해서 카운트.
                        if (sFileName.EndsWith(strExt))
                        {
                            counter = counter + 1;
                        }
                    }
                    //하위 폴더 검색을 위한 재귀호출
                    DirSearchFileExtCounter(d, searchPattern);
                }
            }
            catch (System.Exception excpt)
            {
                Console.WriteLine(excpt.Message);
            }          
        }
    }
}