Elasticsearch local 환경에서 하나의 클러스터에 n개 이상의 노드(인스턴스)생성


데이터 경로는 다른 클러스터의 여러 노드에 의해 공유 될수 있다. 이는 개발 시스템에서 장애 조치 및 다른 구성을 테스트하는데는 유용하다. 하지만 운영환경에서는 하나의 서버당 하나의 노드만 실행하는 것이 좋다. , 하나의 서버에 하나의 노드만 실행시키기 위해서는 node.max_local_storage_nodes:1 로 설정하고, 만약 하나의 머신에서 여러 개의 노드를 실행시키기 위해서는 설정을 1 이상으로 조정해야된다. 만약 한 머신에서 두개 이상의 노드를 운영한다면 샤드들은 elasticsearch에서 자동으로 분배해준다.


elasticsearch.yml의 적당한 위치에 node.max_local_storage_nodes를 생성할 노드수 만큼 설정을 해준다. 그래서 한 데이터를 여러노드가 공유할 수 있게 설정을 해주면 된다. 그리고 여러개의 터미널을 켜서 node 인스턴스들을 생성하면 생성된 샤드가 자동으로 각 노드에 분배가 된다.


culr "localhost:9200/_cat/shards?v" 명령어를 실행시켜서 shard들의 분배상태를 확인할수 있다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
index        shard prirep state   docs store ip        node
get-together 1     r      STARTED    1 7.9kb 127.0.0.1 _qpD4qV
get-together 1     p      STARTED    1 7.9kb 127.0.0.1 f6xhNIi
get-together 3     r      STARTED    1 7.9kb 127.0.0.1 _qpD4qV
get-together 3     p      STARTED    1 7.9kb 127.0.0.1 f6xhNIi
get-together 4     r      STARTED    1 7.5kb 127.0.0.1 _qpD4qV
get-together 4     p      STARTED    1 7.5kb 127.0.0.1 f6xhNIi
get-together 2     r      STARTED    2 8.9kb 127.0.0.1 _qpD4qV
get-together 2     p      STARTED    2 8.9kb 127.0.0.1 f6xhNIi
get-together 0     r      STARTED    0  261b 127.0.0.1 _qpD4qV
get-together 0     p      STARTED    0  261b 127.0.0.1 f6xhNIi
myindex      1     r      STARTED    0  261b 127.0.0.1 _qpD4qV
myindex      1     p      STARTED    0  261b 127.0.0.1 f6xhNIi
myindex      3     r      STARTED    0  261b 127.0.0.1 _qpD4qV
myindex      3     p      STARTED    0  261b 127.0.0.1 f6xhNIi
myindex      4     r      STARTED    0  261b 127.0.0.1 _qpD4qV
myindex      4     p      STARTED    0  261b 127.0.0.1 f6xhNIi
myindex      2     r      STARTED    0  261b 127.0.0.1 _qpD4qV
myindex      2     p      STARTED    0  261b 127.0.0.1 f6xhNIi
myindex      0     r      STARTED    0  261b 127.0.0.1 _qpD4qV
myindex      0     p      STARTED    0  261b 127.0.0.1 f6xhNIi
new-index    1     r      STARTED    0  261b 127.0.0.1 _qpD4qV
new-index    1     p      STARTED    0  261b 127.0.0.1 f6xhNIi
new-index    3     r      STARTED    0  261b 127.0.0.1 _qpD4qV
new-index    3     p      STARTED    0  261b 127.0.0.1 f6xhNIi
new-index    4     r      STARTED    0  261b 127.0.0.1 _qpD4qV
new-index    4     p      STARTED    0  261b 127.0.0.1 f6xhNIi
new-index    2     r      STARTED    0  261b 127.0.0.1 _qpD4qV
new-index    2     p      STARTED    0  261b 127.0.0.1 f6xhNIi
new-index    0     r      STARTED    0  261b 127.0.0.1 _qpD4qV
new-index    0     p      STARTED    0  261b 127.0.0.1 f6xhNIi
 
cs

posted by 여성게
:
Web/Spring 2018. 6. 16. 17:33

스프링에서 정적리소스 자원 사용하기(매핑),<mvc:resource>


어느때에 갑자기 jsp에서 작동하던 css, js 등의 정적 자원들이 적용이 안되는 경우가 있다. 


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<!-- Processes application requests -->
    <servlet>
        <servlet-name>appServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
        
    <servlet-mapping>
        <servlet-name>appServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
cs

이런 경우에 먹질 않는 경우가 많다는 것이다. 요즘은 RESTFUL한 웹페이지 개발이 많기때문에 보통 servlet url 매핑을 이와 같이 하는 경우가 많다. 보통 *.do와같은 url을 매핑하게되면 *.do 형식이 아닌 url로 들어오는 요청은 전부다 defaultHandler에게 넘겨버린다. (이 안에 jsp,js,css 등 정적 리소스들의 url매핑을 처리하게 된다.) *.do 면 문제가 안된다. 단순히 servlet은 이 형태로 들어오는 url만 처리하면 되기에, 하지만 위의 코드와 같이 servlet의 url 매핑을 걸 경우는 조금 다르다. /css/.. ,/js/.., resources/css/... 등등 jsp에서 정적 자원을 활용하기 위해 link를 걸거나 스크립트 태그안의 src 속성에 url을 넣게 되면 이 마저도 servlet 매핑에 걸리게 되는 것이다. 그럼 당연히 위와 같은 매핑에 대해 controller는 작성해 놓지 않기에  404 not found가 뜨게 되는 것이다. 이문제를 해결하는 방법이 있다.(방식 자체는 2~3개 있겠지만 여기서는 그 중 한가지 방법을 소개)



1
2
3
4
5
<script src="https://code.jquery.com/jquery-2.1.1.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.2/angular.min.js"></script>
<script type="text/javascript" src="resources/js/app.js"></script>    
<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="resources/css/app.css">
cs

jsp 안에서 이런 자바 스크립트가 있다는 가정하에, 아무런 조치가 없다면 app.js , app.css 등은 404not found라는 응답이 발생할 것이다. 



<webapp 디렉토리 구조>


1
2
<!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
    <mvc:resources mapping="/resources/**" location="/resources/" />
cs


servlet-context.xml 에 위와 같은 설정을 해줌으로써 /resources/** 로 들어오는 모든 요청은 ${webapproot}/resources/ 로 모두 매핑시켜버리겠다는 설정이다. 이로써 정적리소스는 문제 없이 사용이 가능하게 된다. 이 방법 말고도 아예 defaultServlet 자체를 선언하여 /resources/* 라는 url을 defaultServlet 이 처리하도록 명시할 수도 있다.

posted by 여성게
:
Web/Spring 2018. 6. 16. 13:42

Spring EmbeddedDatabase(스프링 내장형 DB란)


스프링 임베디드 데이터베이스란 애플리케이션에 내장되서 애플리케이션과 함께 시작되고 종료되는 DB를 말한다. 데이터는 메모리 상에 저장되기 때문에 런타임에 IO로 인해 발생하는 부하가 적어서 성능이 뛰어나다. 동시에 Map과 같은 컬렉션이나 오브젝트를 이용해 메모리에 데이터를 저장해두는 방법에 비해 매우 효과적이고 안정적인 방법으로 등록,수정,검색이 가능하다. 최적화된 락킹, 격리수준, 트랜잭션 또한 적용 가능하다.

임베디드데이터베이스는 메모리로 읽어들인 데이터를 여러 가지 조건으로 검색하거나 통계를 내야하고 필요에 따라 데이터를 조작해가면서 복잡한 로직을 처리해야 하는 경우 컬렉션 혹은 자바빈 오브젝트 등에 담아서 사용하는 것보다 편리하게 진행 할수 있다. 물론 내장형 데이터베이스도 메모리 상에 상주하기에 담고있는 데이터가 커질 경우에는 부하가 생길 수 있다.




간단한 사용법



pom.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<!-- 임베디드 데이터베이스용 hsql -->
        <!-- https://mvnrepository.com/artifact/org.hsqldb/hsqldb -->
        <dependency>
            <groupId>org.hsqldb</groupId>
            <artifactId>hsqldb</artifactId>
            <version>2.3.1</version>
            <scope>test</scope>
        </dependency>
        <!-- 스프링에서 JDBC 를 사용하기 위한 라이브러리 입니다. -->
        <dependency>
           <groupId>org.springframework</groupId>
           <artifactId>spring-jdbc</artifactId>
           <version>${org.springframework-version}</version>
        </dependency>
cs


schema.sql

1
2
3
4
CREATE TABLE MAPTYPE(
    KEY_ VARCHAR(100) PRIMARY KEY,
    VALUE_ VARCHAR(100) NOT NULL
);
cs
data.sql

1
2
INSERT INTO MAPTYPE VALUES('KEY1','VALUE1');
INSERT INTO MAPTYPE VALUES('KEY2','VALUE2');
cs



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package com.web.angular;
 
import static org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType.HSQL;
 
import java.util.Arrays;
 
import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabase;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
 
public class EmbeddedDatabaseTest {
 
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        EmbeddedDatabase db=(EmbeddedDatabase) new EmbeddedDatabaseBuilder().setType(HSQL).addScript("classpath:schema.sql").addScript("classpath:data.sql")
                .build();
        
        SimpleJdbcTemplate template=new SimpleJdbcTemplate(db);
        
        System.out.println("select * from maptype>> "+Arrays.toString(template.queryForList("select * from maptype").toArray()));
    }
 
}
 
cs


db 라는 변수에 담기는, 즉 EmbeddedDatabaseBuilder 가 최종적으로 리턴하는 객체는 DB에 접근할 수 있는 Connection을 생성해주는 DataSource인터페이스를 상속한 EmbeddedDatabase 타입이다. 이 값을 jdbcTempalte 생성자 매개변수에 넣어서 내장형 디비를 실행 시킬 수 있다.

결과


posted by 여성게
:

JAXB - unmarshal & marshal


XML은 이제 데이터를 표현하는 표준이며, Java Object를 XML로 나열할 때 사용하는 다양한 XML 파싱 기술들이 개발되어왔고, 그 중에 많이 쓰이는 대표적인 기술이 SAXParser와 DOMParser이다. 하지만 프로그래머들이 즉각적인 테스트를 할 방법으로 필요한 기술을 원했고 이 경우에 사용하는 기술이 JAXB이다.  JAXB는 Java Architecture for XML Bind의 약자로 XML로 부터 Java Object를 직렬화 하는 Unmarshalling과 이 반대의 Marshalling을 수행 할수 있도록 해주는 API이다.




-Binding Compiler(xjc) : 사용자가 정의한 XML Schema를 가지고, Schema에 정의 된 데이터 모델을 Java Object로 표현 할 수 있는 Java interface 또는 classes를 생성해주는 컴파일러이다.

-Schema-Derived Classes&Interface: XML Schema에 정의된 데이터 모델을 Java Object로 표현 할 수 있는 Java Interface & Classes이다.

-marshal: Java Object를 XML문서로 변환

-Unmarshal: XML문서를 Java Object로 매핑해주는 역할.




xml schema 파일 작성



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema" 
    targetNamespace="http://www.epril.com/sqlmap" 
    xmlns:tns="http://www.epril.com/sqlmap" elementFormDefault="qualified">
 
    <element name="sqlmap">
        <complexType>
            <sequence>
                <element name="sql" maxOccurs="unbounded" type="tns:sqlType"/>
            </sequence>
        </complexType>        
    </element>
    <complexType name="sqlType">
        <simpleContent>
            <extension base="string">
                <attribute name="key" use="required" type="string"/>
            </extension>
        </simpleContent>
    </complexType>
</schema>
cs


간단한 xml 스키마를 작성하였다. 이 스키마는 jdbc를 사용할 때, DAO클래스에 난무하는 SQL문을 별도의 XML 파일로 분리하여 DAO에서 간단히 이 XML에 정의된 SQL문을 XML파일을 언마샬링하는 별도의 클래스에서 주입받아 사용하기 위해 작성했던 예제에서 쓰던 XML스키마이다.




이 스키마를 해당 프로젝트 워크스페이스 루트 경로에 저장하고 밑의 cmd 명령어를 실행해준다.



우선 워크스페이스에 있는 해당 프로젝트 폴더까지 가준다. 그리고 xjc 명령어로 시작으로 -p com.web.jpa 는 schema-derived classes&interface가 저장될 패키지명을 fullname으로 써준다. 그리고 -d src는 이 패키지를 포함하는 classes&interface가 저장될 루트 경로를 정해준다.( 위의 src는 편의상 넣은 것이고, 별도로 해당 프로젝트의 코드들이 존재하는 패키지의 루트를 같은레벨로 넣어주면 될것 같다.)


실행 후에 ObjectFactory.java & package-info.java & Sqlmap.java & SqlTyple.java 가 생성된 것을 볼 수 있다.


1
2
3
4
5
6
7
<?xml version="1.0" encoding="UTF-8"?>
<sqlmap xmlns="http://www.epril.com/sqlmap"    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://www.epril.com/sqlmap ../../../../../sqlmap.xsd">
    <sql key="add">insert</sql>
    <sql key="get">select</sql>
    <sql key="delete">delete</sql>
</sqlmap>
cs

언마샬링을 할 xml 예제 파일이다.




Unmarshalling & Marshalling



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
package com.web.jpa;
 
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Iterator;
import java.util.List;
 
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
 
import org.aspectj.weaver.tools.cache.GeneratedCachedClassHandler;
 
public class Test {
 
    public static void main(String[] args) throws JAXBException, FileNotFoundException {
        // TODO Auto-generated method stub
        TestClass t= new TestClass();
        t.readSqlmap();
    }
    
}
 
class TestClass{
    public void readSqlmap() throws JAXBException, FileNotFoundException {
        String contextPath=Sqlmap.class.getPackage().getName();
        System.out.println(contextPath);
        JAXBContext context=JAXBContext.newInstance(contextPath);
        Unmarshaller um=context.createUnmarshaller();
        
        Sqlmap sqlmap=(Sqlmap)um.unmarshal(getClass().getResourceAsStream("sqlmap.xml"));
        
        List<SqlType> sqlList=sqlmap.getSql();
        
        Iterator<SqlType> it=sqlList.iterator();
        while(it.hasNext()) {
            SqlType s=it.next();
            System.out.println(s.getKey()+":"+s.getValue());
        }
        Marshaller ms=context.createMarshaller();
        ms.marshal(sqlmap, new FileOutputStream("marshall.xml"));
    }
}
 
cs


위의 코드는 언마샬링을 시작으로 마지막에 마샬링 기능으로 끝나는 코드이다.


String contextPath=Sqlmap.class.getPackage().getName(); => 이 코드는 Schema-Derived-Classes&Interface가 존재하는 contextPath를 얻어 내기위한 코드이다. 이 코드를 이용하여 JAXBContext 객체를 얻을 수 있다. (result : com.web.jpa)


JAXBContext context=JAXBContext.newInstance(contextPath); =>이 코드는 위의 "JAXB를 간략하게 설명한 그림"에서 Schema-Derived-Classes&Interface가 JAXB를 가르키고 있는 화살표에 해당하는 과정이라고 생각하면 된다. contextPath를 이용해 해당 클래스와 인터페이스를 읽어들여서 파싱에 필요한 정보를 얻어내는 과정이다.


Unmarshaller um=context.createUnmarshaller(); =>언마샬링에 필요한 언마샬러 객체를 생성한다. 


Sqlmap sqlmap=(Sqlmap)um.unmarshal(getClass().getResourceAsStream("sqlmap.xml"); => 우선 sqlmap.xml은 이 Test.java 와 같은 디렉토리에 있다는 가정하에 진행한다. 그렇기에 getClass().getResourceAsStream("sqlmap.xml")을 통해 Test.java와 같은 레벨에 있는 sqlmap.xml을 자원을 inputStream객체형태로 리턴을 받는다. 그리고 이 리턴받은 자원을 이용해 unmarshalling을 진행한다. unmarshal( )의 리턴타입은 Object이기에 이것을 Sqlmap클래스 타입으로 cast 해준다. Sqlmap & SqlType 클래스의 코드는 밑과 같다. 코드를 천천히 해석하다보면 전부다는 아니지만 대략적으로 이런 형태를 가졌구나 정도는 이해가 된다. Sqlmap은 SqlType의 sql 엘리먼트를 List 형태로 갖고 있는 형태이고, SqlType은 sql 엘리먼트의 타입을 보여주는 클래스이다. key&value 형태로 되있는 sql 엘리먼트라는 것이 짐작이 갈 것이다.




1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
//
// 이 파일은 JAXB(JavaTM Architecture for XML Binding) 참조 구현 2.2.8-b130911.1802 버전을 통해 생성되었습니다. 
// <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a>를 참조하십시오. 
// 이 파일을 수정하면 소스 스키마를 재컴파일할 때 수정 사항이 손실됩니다. 
// 생성 날짜: 2018.06.03 시간 02:20:59 PM KST 
//
 
 
package com.web.jpa;
 
import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
 
 
/**
 * <p>anonymous complex type에 대한 Java 클래스입니다.
 * 
 * <p>다음 스키마 단편이 이 클래스에 포함되는 필요한 콘텐츠를 지정합니다.
 * 
 * <pre>
 * <complexType>
 *   <complexContent>
 *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
 *       <sequence>
 *         <element name="sql" type="{http://www.epril.com/sqlmap}sqlType" maxOccurs="unbounded"/>
 *       </sequence>
 *     </restriction>
 *   </complexContent>
 * </complexType>
 * </pre>
 * 
 * 
 */
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
    "sql"
})
@XmlRootElement(name = "sqlmap")
public class Sqlmap {
 
    @XmlElement(required = true)
    protected List<SqlType> sql;
 
    /**
     * Gets the value of the sql property.
     * 
     * <p>
     * This accessor method returns a reference to the live list,
     * not a snapshot. Therefore any modification you make to the
     * returned list will be present inside the JAXB object.
     * This is why there is not a <CODE>set</CODE> method for the sql property.
     * 
     * <p>
     * For example, to add a new item, do as follows:
     * <pre>
     *    getSql().add(newItem);
     * </pre>
     * 
     * 
     * <p>
     * Objects of the following type(s) are allowed in the list
     * {@link SqlType }
     * 
     * 
     */
    public List<SqlType> getSql() {
        if (sql == null) {
            sql = new ArrayList<SqlType>();
        }
        return this.sql;
    }
 
}
 
cs


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
//
// 이 파일은 JAXB(JavaTM Architecture for XML Binding) 참조 구현 2.2.8-b130911.1802 버전을 통해 생성되었습니다. 
// <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a>를 참조하십시오. 
// 이 파일을 수정하면 소스 스키마를 재컴파일할 때 수정 사항이 손실됩니다. 
// 생성 날짜: 2018.06.03 시간 02:20:59 PM KST 
//
 
 
package com.web.jpa;
 
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlType;
import javax.xml.bind.annotation.XmlValue;
 
 
/**
 * <p>sqlType complex type에 대한 Java 클래스입니다.
 * 
 * <p>다음 스키마 단편이 이 클래스에 포함되는 필요한 콘텐츠를 지정합니다.
 * 
 * <pre>
 * <complexType name="sqlType">
 *   <simpleContent>
 *     <extension base="<http://www.w3.org/2001/XMLSchema>string">
 *       <attribute name="key" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
 *     </extension>
 *   </simpleContent>
 * </complexType>
 * </pre>
 * 
 * 
 */
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "sqlType", propOrder = {
    "value"
})
public class SqlType {
 
    @XmlValue
    protected String value;
    @XmlAttribute(name = "key", required = true)
    protected String key;
 
    /**
     * value 속성의 값을 가져옵니다.
     * 
     * @return
     *     possible object is
     *     {@link String }
     *     
     */
    public String getValue() {
        return value;
    }
 
    /**
     * value 속성의 값을 설정합니다.
     * 
     * @param value
     *     allowed object is
     *     {@link String }
     *     
     */
    public void setValue(String value) {
        this.value = value;
    }
 
    /**
     * key 속성의 값을 가져옵니다.
     * 
     * @return
     *     possible object is
     *     {@link String }
     *     
     */
    public String getKey() {
        return key;
    }
 
    /**
     * key 속성의 값을 설정합니다.
     * 
     * @param value
     *     allowed object is
     *     {@link String }
     *     
     */
    public void setKey(String value) {
        this.key = value;
    }
 
}
 
cs



<언마샬링의 결과>



Marshaller ms=context.createMarshaller();
        ms.marshal(sqlmap, new FileOutputStream("marshall.xml"));


=>이 코드는 XML 스키마에 적합한 Sqlmap 형태의 객체(언마샬링한 객체를 그대로 재활용하였다.)를 marshal.xml 이라는 xml파일로 내보내는 코드이다.

    

<마샬링결과>


별도의 경로를 지정해주지 않았음으로 워크스페이스에 해당 프로젝트 폴더 루트에 저장이 된다. 


저희가 사용하는 xBatis 같은 경우에도 모든 sql문을 xml파일로 관리하여 connection관리 등 설정 또한 xml로 관리를 합니다. 그러한 것도 정확히 JAXB기술을 사용하는지는 알수 없으니 이와 비슷한 기술을 사용하여 xBatis를 사용하는 것으로 알고 있습니다.

이상으로 JAXB의 간단한 예제를 보여드렸습니다. 다음에는 JAXB와 동일한 기능을 하는 많은 OXM API들을 소개시켜드리겠습니다.(SAX,DOM포함)

posted by 여성게
:

JavaScript 타이머 함수


자바스크립트에서 타이머함수란 전역객체인 window 객체 안에 있는 함수들입니다. 그렇다면 타이머 함수가 할수 있는 일은 무엇이 있을까요?


1. 특정시간마다 특정 함수를 계속 호출해서 실행 시킬 수 있다. => setInterval(function, duration)

2. 특정시간 이후에 딱 한번만 특정함수를 호출해 실행시킨다. => setTimeOut(function, duration)

3. 특정 타이머 id값을 가진 타이머 함수를 종료시킨다. => clearInterval(timerid)






1. 특정시간마다 특정함수를 호출/실행, setInterval 함수



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
<!DOCTYPE html PUBLIC "-//W3C//DTD Xhtml 1.0 Transitional//EN"
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title></title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }
 
        #output {
            width: 200px;
            height: 200px;
            border: 4px solid #000;
            margin: 50px;
 
            font-size: 100px;
            text-align: center;
            line-height: 200px;
            vertical-align: middle;
 
        }
    </style>
    <script src="../../libs/jquery-1.11.0.min.js"></script>
 
    <script>
        // 예제01: 1초에 한 번씩 변수 값을 1씩 증가시키고 이 값을 #output 영역에 출력해 주세요.
        $(document).ready(function () {
 
            var $output = $("#output");
            var count = 0;
 
            // 여기에 풀이를 입력해주세요.
            // 함수 생성
            function addCount() {
                // 값 증가
                count++;
                // 값을 출력
                $output.text(count);
            }
 
            addCount();
            setInterval(addCount, 1000);
 
        })
 
    </script>
 
 
</head>
 
<body>
<div id="output">
    0
</div>
</body>
</html>
 
cs


이 코드는 1초 마다 숫자를 1씩 증가시켜주는 코드입니다. 딱히 어렵지 않은 코드라고 생각합니다. 여기서 하나 알아야 할 것은 setInterval 함수가 어떠한 리턴 값 없이 매개변수안에 있는 실행구문을 실행시켜주고 끝이 아닙니다. setInterval 함수는 코드내 유일한 timer id를 int 형태로 반환하는 함수입니다. (timer id값은 clearInterval 함수로 타이머 함수를 종료시킬 때 사용 될수 있는 유니크 키 값이라고 생각해도 좋습니다.)






2. 특정시간 이후에 딱 한번만 함수 호출/실행 , setTimeOunt 함수



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
<!DOCTYPE html PUBLIC "-//W3C//DTD Xhtml 1.0 Transitional//EN"
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title></title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }
 
        #output {
            width: 600px;
            height: 200px;
            border: 4px solid #000;
            margin: 50px;
 
 
            text-align: center;
            line-height: 200px;
            vertical-align: middle;
 
        }
    </style>
    <script src="../../libs/jquery-1.11.0.min.js"></script>
 
    <script>
        // 예제02: 3초 후에 “안녕하세요. 환영합니다.” 메시지를 화면에 출력해 주세요.
        $(document).ready(function () {
 
            var $output = $("#output");
 
            // 여기에 풀이를 입력해주세요.
            setTimeout(function () {
                $output.text("안녕하세요. 환영합니다.")
            }, 3000);
 
        })
 
    </script>
 
 
</head>
 
<body>
<div id="output">
 
</div>
</body>
</html>
 
cs

이 코드는 3초 후에 매개변수 안에 있는 익명함수를 호출하여 "안녕하세요. 환영합니다"라는 메시지를 $("#output") 안에 출력하는 기능을 딱 한번만 실행시켜주는 코드입니다.





3. 특정 타이머 함수를 종료시켜주는 함수 , clearInterval 함수



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
<!DOCTYPE html PUBLIC "-//W3C//DTD Xhtml 1.0 Transitional//EN"
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title></title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }
 
        #output {
            width: 200px;
            height: 200px;
            border: 4px solid #000;
            margin: 50px;
 
            font-size: 100px;
            text-align: center;
            line-height: 200px;
            vertical-align: middle;
 
        }
    </style>
    <script src="../../libs/jquery-1.11.0.min.js"></script>
 
    <script>
        /*
         예제 03: 1초에 한번씩 숫자 값 출력하기
         변수 값을 1초에 한 번 1씩 증가시키고 이 값을 화면에 출력해 주세요.
         단, 정지버튼(#stip)을 누르면 더 이상 실행되지 않게 타이머 함수를 중지시켜 주세요.
         */
        $(document).ready(function() {
 
            var $output = $("#output");
            var count = 0;
            var timerID=0;
            timerID = setInterval(function() {
                // 값 증가
                count++;
                // 값을 출력
                $output.text(count);
            }, 1000);
 
 
            $("#stop").click(function() {
                // 여기에 풀이를 입력해주세요.
                clearInterval(timerID);
            });
 
        })
 
    </script>
 
 
</head>
 
<body>
<button id="stop">멈춤</button>
<div id="output">
    0
</div>
</body>
</html>
 
cs

이 코드는 setInterval 함수에 의해서 1초마다 1씩 증가되는 값을 출력시켜주는 타이머 함수를 종료시켜주는 코드입니다. 여기에 쓰이는 함수가 clearInterval 함수입니다. 여기서 보이는 것은 setInterval 함수의 리턴 값을 timerID라는 변수에 담아주고 이 변수를 이용해 clearInterval 함수를 사용하여 특정타이머를 종료시켜줍니다. 






posted by 여성게
:

서블릿(Servlet) 이란?


서블릿이란 클라이언트의 요청에 따라 서버가 실행시키는 자바 프로그램입니다. 예전에는 웹서버가 모든 클라이언트의 요청을 받아서 처리를 했었는데, 요즘처럼 인터넷이 활성화된 시대에서는 웹서버 혼자서 모든 요청을 처리 할수 없게 되었습니다. 그래서 나온 것이 서블릿입니다. 웹서버에게 요청이 가면 그 요청을 서블릿 컨테이너에게 넘기고 서블릿 컨테이너가 요청에 알맞은 서블릿 객체를 생성시켜주게 됩니다. 하지만 여기에서 중요한 것은 서블릿 컨테이너가 모든 요청에 대해 서블릿 객체를 생성시키지 않는다는 점입니다. 만약 해당이 요청이 서버 입장에서 첫 요청이라면 서블릿 객체를 생성시키지만 만약 첫 요청이 아니라면 메모리에 이미 생성된 서블릿객체에 대해 스레드를 생성해서 요청을 처리하고 응답을 하게 됩니다.


서블릿 API 문서 -> http://tomcat.apache.org



 


서블릿은 어떻게 구현될까?



우선 서블릿을 구현할 때는 javax.servlet.http.HttpServlet 클래스를 상속하여 개발하게 됩니다. 그러한 서블릿은 서블릿 컨테이너가 생명주기를 관장하게 됩니다. 우선 HttpServlet의 상속 구조를 알아보면,





서블릿 API에 나와있는 위 글을 보면 최상위는 interface인 "Servlet", 그리고 그것은 상속한 abstract class인 "GenericServlet"를 HttpServlet 클래스는 상속을 받게 됩니다.




각각에 대해서 간단히 설명하면 인터페이스인 Servlet은 서블릿 프로그램을 개발할 때 반드시 구현해야 하는 메소드를 선언하고 있는 인터페이스입니다. 




이 5개의 메소드가 서블릿의 생명주기와 관련된 메소드라고 생각하시면 됩니다.



다음은 추상클래스인 GenericServlet 입니다. Servlet 인터페이스를 상속하여 클라이언트-서버 환경에서 서버단의 애플리케이션으로서 필요한 기능을 구현한 추상 클래스입니다. service( ) 를 제외한 모든 메소드를 재정의하여 적절한 기능으로 구현하였습니다.




마지막으로는 GenericServlet을 상속받은 HttpServlet 입니다. GenericServlet을 상속하여 service( )를 재정의함으로써 http 프로토콜에 알맞은 동작을 수행하도록 구현한 클래스입니다. 즉, http 프로토콜 기반으로 브라우저로부터 요청을 전달받아서 처리하도록 하는 클래스입니다. service( )에서는 요청방식(get,post,delete,put....)에 따라서 정해진 사양의 메소드가 호출되도록 구현되어 있습니다.



여기서 볼것은 service( ) 메소드가 2개 오버로딩되어있다는 것입니다. 그것을 설명하면 처음에 요청이 들어오면 매개변수가 ServletRequest req,ServletResponse res 인 service( )가 호출되고 이 메소드는 간단히 다른 service( )를 호출해주는 역할을 하고 두번째로 호출된 service( )에서 각 요청에 알맞은 방식의 메소드를 호출하는 역할을 하게 됩니다.





서블릿 동작흐름




참조:http://sjh836.tistory.com/126?category=679845

             


그리고 이러한 서블릿을 설정하는 파일이 web.xml 파일입니다. 웹서버가 서비스를 시작하기 위해 구동할 때 서버에서 많은 일이 일어나는데, 그 중의 하나가 클라이언트에 서비스하기 위한 웹 애플리케이션을 준비하는 작업입니다. 이때 웹서버는 각 웹 애플리케이션의 web.xml 파일을 읽고, web.xml에 정의된 내용대로 웹 애플리케이션을 실행하기 위한 설정을 수행하게 됩니다. 따라서 web.xml을 잘못 작성하게 되는 순간에는 웹 애플리케이션 안에 있는 모든 파일은 서비스 될수 없게 됩니다.




posted by 여성게
:
프로그래밍언어/Python 2018. 5. 13. 13:36

Python에서 사용할 module의 디렉토리가 같지 않아도 사용 가능하려면??


python에서는 기본적으로 모듈을 import해서 사용하려면 같은 디렉토리 경로 상에 존재해야 모듈을 사용가능 하다 하지만 같은 디렉토리 경로가 아니더라도 해당 모듈을 import해서 사용할 수 있다면?? 방법은 sys모듈에서 모듈 경로를 추가해주는 것이다!!


>>>import sys

>>>sys.path.append("c:/python/modules") ====>사용할 모듈들을 모아놓을 디렉토리

>>>sys.path ====>추가한 디렉토리가 잘 추가 되었는지 확인!!



이렇게 디렉토리를 추가시켜놓으면 "c:/python/modules" 경로 내에 있는 모듈들을 어디에서든지 사용이 가능하다!!




혹은 위 방법 말고도 set PYTHONPATH=C:\python\modules 로 환경변수를 사용하는 방법도 있다!!

'프로그래밍언어 > Python' 카테고리의 다른 글

Python - 클래스의 생성자  (0) 2018.05.12
posted by 여성게
:
프로그래밍언어/Python 2018. 5. 12. 21:39


Python 클래스에서 만약 인자가 있는 생성자 외에 디폴트 생성자까지 만들고 싶다면?


만약 윤씨 집안의 사람을 만드는 클래스라고 생각해보자. 그러면 클래스의 인스턴스를 생성하는 방법은 2가지가 있을 것이다. 생성자에 이름 인자를 넣어서 인스턴스를 생성하는 방법과 우선은 디폴트 생성자로 윤씨인 인스턴스를 만들고 그 다음에 setter 메소드를 이용해 이름을 결정짓는 방법 이렇게 2가지 일 것이다. 



1
2
3
4
5
6
7
8
class HouseYoon:
    lastname='윤'
    
    def __init__(self,name=None):
        if name != None:
            self.fullname=self.lastname+name
    def setname(self,name):
        self.fullname=self.lastname+name
cs


이런식으로 __init__메소드의 name이라는 인자가 가변적으로 있을 수도 없을 수도 있는 상태로 만들어주는 것이다. 바로 인자의 초깃값을 바로 넣어주는 방식이다. 이렇게 되면 만약 name자리에 인자가 들어오지 않는다면 name의 데이터는 거짓인 형태 None으로 초기화가 된다. 즉, 인자가 있는 생성자 메소드가 있더라도 인자를 넣지 않아도 되는 상황이 생길 수 있는 것이다.!!

'프로그래밍언어 > Python' 카테고리의 다른 글

Python module 디렉토리 설정  (0) 2018.05.13
posted by 여성게
: