public class SessionBindingListener implements HttpSessionBindingListener {
private ServletContext context;
public SessionBindingListener(ServletContext context) {
this.context = context;
}
public void valueBound(HttpSessionBindingEvent event) {
context.log("BOUND to " + event.getSession().getId());
}
public void valueUnbound(HttpSessionBindingEvent event) {
context.log("UNBOUND from " + event.getSession().getId());
}
}
※ 자, 그럼 이걸 어디에 써먹어야 할까요???
이 예제는 보시면 아시겠지만 session.setAttribute 즉 session key/value 에 binding 되면 event 가 발생하게 되는 거랍니다.
그니까.. isNew() 할때.. 필요한 걸 session 에 저장한 다음.. session expired 되거나 하면 자동으로 삭제가 되도록 필요한 기능을 구현 하면 되겠죠.
불필요한 session 을 삭제 하거나 아니면 status 등을 처리 한다거나 할때.. 별도의 listener 없이 이걸 가지고 구현 하면 쉽게 할 수 있을 듯 합니다.
배도 고프고 해서 오늘은 여기까지만.. ㅎㅎ
실행 방법은 잘 아시죠.. servlet 하나 생성 하셔서 Run on Server 하시면 되요..
-> http://localhost:8080/proto.session/CreateSessionBinding
[실행로그]
2012. 3. 22 오후 7:32:39 org.apache.catalina.core.ApplicationContext log
정보: BOUND to C7A16EA8F0687784DAA17367695BA501
2012. 3. 22 오후 7:32:39 org.apache.catalina.core.ApplicationContext log
정보: new session.binding : C7A16EA8F0687784DAA17367695BA501
2012. 3. 22 오후 7:33:37 org.apache.catalina.core.ApplicationContext log
정보: UNBOUND from C7A16EA8F0687784DAA17367695BA501
- 보시면 처음 페이지가 열리면 BOUND 되구요.
- Session expired 되면 UNBOUND 됩니다.
- 또는 session.setAttribute 해서 binding 하셔도 UNBOUND 됩니다.
- tomcat 의 web.xml 에서 아래 처럼 변경했습니다. (1분)
<session-config>
<session-timeout>1</session-timeout>
</session-config>
역시 배고파서 작성하는 글은.. 좀 부족하내요.. ㅋㅋ
집에 와서 다시 업데이트..
위에 CreateSessionBinding 서블릿 클래스를 보시면 빨간 부분 보이시죠..
그렇습니다.
위에 설명한 "또는 session.setAttribute 해서 binding 하셔도 UNBOUND 됩니다." 는.. set 한 key 에 대해서 binding 되면 event 가 발생을 하게 되는 것입니다.
테스트가 부족했으니 내일 다시 최종 확인 결과 올리겠습니다. ㅡ.ㅡ;;
[최종테스트결과]
- 이론이 역시 맞습니다.
session.setAttribute("session.id", new SessionBindingListener(context));
- session 에 listener 를 등록해 줬기 때문에 이넘이 bound, unbound 되면 event 가 발생하게 되는 것입니다.
Access level modifiers determine whether other classes can use a particular field or invoke a particular method. There are two levels of access control:
At the top level—public, orpackage-private(no explicit modifier).
At the member level—public,private,protected, orpackage-private(no explicit modifier).
A class may be declared with the modifierpublic, in which case that class is visible to all classes everywhere. If a class has no modifier (the default, also known aspackage-private), it is visible only within its own package (packages are named groups of related classes — you will learn about them in a later lesson.)
At the member level, you can also use thepublicmodifier or no modifier (package-private) just as with top-level classes, and with the same meaning. For members, there are two additional access modifiers:privateandprotected. Theprivatemodifier specifies that the member can only be accessed in its own class. Theprotectedmodifier specifies that the member can only be accessed within its own package (as withpackage-private) and, in addition, by a subclass of its class in another package.
The following table shows the access to members permitted by each modifier.
Access Levels
Modifier
Class
Package
Subclass
World
public
Y
Y
Y
Y
protected
Y
Y
Y
N
no modifier
Y
Y
N
N
private
Y
N
N
N
The first data column indicates whether the class itself has access to the member defined by the access level. As you can see, a class always has access to its own members. The second column indicates whether classes in the same package as the class (regardless of their parentage) have access to the member. The third column indicates whether subclasses of the class — declared outside this package — have access to the member. The fourth column indicates whether all classes have access to the member.
Access levels affect you in two ways. First, when you use classes that come from another source, such as the classes in the Java platform, access levels determine which members of those classes your own classes can use. Second, when you write a class, you need to decide what access level every member variable and every method in your class should have.
Let's look at a collection of classes and see how access levels affect visibility.The following figureshows the four classes in this example and how they are related.
Classes and Packages of the Example Used to Illustrate Access Levels
The following tableshows where the members of the Alpha class are visible for each of the access modifiers that can be applied to them.
Visibility
Modifier
Alpha
Beta
Alphasub
Gamma
public
Y
Y
Y
Y
protected
Y
Y
Y
N
no modifier
Y
Y
N
N
private
Y
N
N
N
Tips on Choosing an Access Level:
If other programmers use your class, you want to ensure that errors from misuse cannot happen. Access levels can help you do this.
Use the most restrictive access level that makes sense for a particular member. Useprivateunless you have a good reason not to.
Avoidpublicfields except for constants. (Many of the examples in the tutorial use public fields. This may help to illustrate some points concisely, but is not recommended for production code.) Public fields tend to link you to a particular implementation and limit your flexibility in changing your code.
[ChatServlet.java]
- 이 파일은 tomcat.apache.org 에 있는 예제 입니다.
- 이걸로 전체 테스트를 진행 하였습니다.
- event.getEventType 이 READ 부분에 보시면 빨간 부분만 추가했습니다.
- 추가한 이유는 server 에서 client 로 message 를 넘길 영역을 테스트 하기 위해서 입니다.
- 녹색 추가 및 주석은 그냥 한글 코드랑 HTML 코드 형태가 아닌 그냥 text 스탈로 처리 하려고 넣었습니다.
package proto.dwp.comet;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.catalina.CometEvent;
import org.apache.catalina.CometProcessor;
/**
* Servlet implementation class ChatServlet
*/
public class ChatServlet extends HttpServlet implements CometProcessor {
private static final long serialVersionUID = 1L;
protected ArrayList<HttpServletResponse> connections = new ArrayList<HttpServletResponse>();
- 일단 이걸 가지고 뭘 해야 좋을지는 좀더 고민을 해봐야겠다.
- 테스트 하면서 느낀건데 이넘을 테스트 하면서 READ 상태에서 END 가 되지 않을경우 이전 message 에 대한 buffer 를 다 유지하고 있는 것 같다.
- 틀린 내용이라 삭제 합니다.. ㅡ.ㅡ;; 화면 출력할때.. 잘 못 했더라구요..이런..
- 코드를 깊게 분석하지 않은 관계로 원인 규명은 다음으로.. ;;;;;
- Server Push 기능이나 Notification Chatting 같은걸 구현 하는데 사용이 가능해 보인다.
- 다만 이런 것들이 HTML5 로 넘어 오면서 많은 부분들이 브라우저에서 처리가 가능해 졌다는 점에서...
- 뭐.. 여기까지만.. ㅋㅋ
- 패키지도 아래 처럼 바뀌었내요. (이건 소스코드 내려서 받아 보면 될듯 하내요.)
import org.apache.cordova.DroidGap;
[시작하기]
1. Eclipse
2. JDK
3. ADT Plugin
- 이건 eclipse plugin 으로 설치를 하셔도 되고 아님 걍 SDK 를 별도 설치 하셔서 location 지정을 하셔도 됩니다.
4. PhoneGap 다운로드 (.js / .jar / .xml)
- AVD 하나 생성 하시지요.
- 옆에 있는 New 버튼 누르시고 하면 됩니다. tutorial 에서 처럼 10MB 만 할당 했습니다.
- Android project 하나 생성하셔서 tutorial 에 있는 것처럼
- jar 파일은 libs 에, js 파일은 www 에 , xml 폴더는 res 에 복사해서 넣으시면 됩니다.
- index.html 파일은 만드시면 되구요.
- 그런 다음에 manifest 파일을 tutorial 에 있는 것처럼 수정 하시면 됩니다.
- 이제 Run As -> Android Application 을 해볼까요..
※ 해보시면 아시겠지만 어려울게 하나도 없습니다.
[소스코드] [helloworldActivity.java]
package proto.phonegap;
import org.apache.cordova.DroidGap;
import android.os.Bundle;
public class helloworldActivity extends DroidGap {
java 개발 하면서 TDD 많이들 들어 보셨을 겁니다.
또는 Code 의 품질 확보를 위한 방법으로도 junit 을 적용하기도 하구요.
뭐.. 이유야 어찌되었건... 오늘은 spring mvc 로 개발한 controller 에 대해서 test code 를 작성해 보겠습니다.
아래 예제는 Mockito 를 이용해서 작성 하였습니다.
[BoardContentViewControllerTest.java - Controller]
- 다들 아시겠지만, src/test/java 아래 동일 패키지명으로 해서 해당 클래스 뒤에 Test 만 붙히시면 됩니다.
- Model 같은 경우 interface 이기 때문에 initialize 를 하면 오류가 발생 합니다. 그렇다 보니 이넘이 구현체를 가지고 initialize 하시면 오류가 없습니다.
- Controller 에서 @Autowired 를 했기 때문에 따로 service 객체에 대한 setter 를 구현 안했었는데요, 이렇게 하니 Test 에서 service 객체가 null 이라고 계속 오류를 냅니다.
- 그래서 위에서 처럼 setter 를 생성 해서 해결 했습니다. (다른 방법 아시는 분은 공유 부탁 합니다.)
If the line starts with a U+003A COLON character (:)
Ignore the line.
If the line contains a U+003A COLON character (:)
Collect the characters on the line before the first U+003A COLON character (:), and letfieldbe that string.
Collect the characters on the line after the first U+003A COLON character (:), and letvaluebe that string. Ifvaluestarts with a U+0020 SPACE character, remove it fromvalue.
Process the fieldusing the steps described below, usingfieldas the field name andvalueas the field value.
Otherwise, the string is not empty but does not contain a U+003A COLON character (:)
Process the fieldusing the steps described below, using the whole line as the field name, and the empty string as the field value.
Once the end of the file is reached, any pending data must be discarded. (If the file ends in the middle of an event, before the final empty line, the incomplete event is not dispatched.)
The steps toprocess the fieldgiven a field name and a field value depend on the field name, as given in the following list. Field names must be compared literally, with no case folding performed.
If the field name is "event"
Set theevent namebuffer to field value.
If the field name is "data"
Append the field value to thedatabuffer, then append a single U+000A LINE FEED (LF) character to thedatabuffer.
If the field name is "id"
Set thelast event IDbuffer to the field value.
If the field name is "retry"
If the field value consists of only characters in the range U+0030 DIGIT ZERO (0) to U+0039 DIGIT NINE (9), then interpret the field value as an integer in base ten, and set the event stream'sreconnection timeto that integer. Otherwise, ignore the field.
Otherwise
The field is ignored.
[Event Stream onmessage Event - data]
[Case 1]
data: 1
data: 2
data: 3
[Case 1's onmessage]
- onmessage 이벤트는 두번처리 됩니다.
- data: 1, data: 2 를 묶어서 하나의 이벤트로 그리고 data: 3 을 또 다른 이벤트로 처리 합니다.
- 결국, empty line 이 없이 바로 연결된 경우는 data buffer 에 메시지가 함께 들어가게 되는 구조 입니다.
This registration is for community review and will be submitted to the IESG for review, approval, and registration with IANA.
Type name:
text
Subtype name:
event-stream
Required parameters:
No parameters
Optional parameters:
charset
Thecharsetparameter may be provided. The parameter's value must be "utf-8". This parameter serves no purpose; it is only allowed for compatibility with legacy servers.
Encoding considerations:
8bit (always UTF-8)
Security considerations:
An event stream from an origin distinct from the origin of the content consuming the event stream can result in information leakage. To avoid this, user agents are required to apply CORS semantics.[CORS]
Event streams can overwhelm a user agent; a user agent is expected to apply suitable restrictions to avoid depleting local resources because of an overabundance of information from an event stream.
Servers can be overwhelmed if a situation develops in which the server is causing clients to reconnect rapidly. Servers should use a 5xx status code to indicate capacity problems, as this will prevent conforming clients from reconnecting automatically.
Interoperability considerations:
Rules for processing both conforming and non-conforming content are defined in this specification.
Published specification:
This document is the relevant specification.
Applications that use this media type:
Web browsers and tools using Web services.
Additional information:
Magic number(s):
No sequence of bytes can uniquely identify an event stream.
File extension(s):
No specific file extensions are recommended for this type.
Macintosh file type code(s):
No specific Macintosh file type codes are recommended for this type.
※ 추가적으로 CORS 관련 문제는 이전에 작성한 PostMessage API 를 참고 하시면 좋을 것 같습니다.
Marks a method (typically a JavaBean setter method) as being 'required': that is, the setter method must be configured to be dependency-injected with a value.
Annotation at the field or method/constructor parameter level that indicates a default value expression for the affected argument.
Package org.springframework.context.annotation
Annotation support for the Application Context, including JSR-250 "common" annotations, component-scanning, and Java-based metadata for creating Spring-managed objects
Indicates that a class declares one or more @Bean methods and may be processed by the Spring container to generate bean definitions and service requests for those beans at runtime, for example:
@Configuration
public class AppConfig {
@Bean
public MyBean myBean() {
// instantiate, configure and return bean ...
Enables support for handling components marked with AspectJ's @Aspect annotation, similar to functionality found in Spring's <aop:aspectj-autoproxy> XML element.
Activates a Spring LoadTimeWeaver for this application context, available as a bean with the name "loadTimeWeaver", similar to the <context:load-time-weaver> element in Spring XML.
When used as a type-level annotation in conjunction with the Component annotation, indicates the name of a scope to use for instances of the annotated type.
JDK 1.5+ method-level annotation that indicates to expose a given bean property as JMX attribute, with added Descriptor properties to indicate that it is a metric.
JDK 1.5+ method-level annotation used to provide metadata about operation parameters, corresponding to an array of ManagedOperationParameter attributes.
Bean post-processor that automatically applies asynchronous invocation behavior to any bean that carries the Async annotation at class or method-level by adding a corresponding AsyncAnnotationAdvisor to the exposed proxy (either an existing AOP proxy or a newly generated proxy that implements all of the target's interfaces).
Bean post-processor that registers methods annotated with @Scheduled to be invoked by a TaskScheduler according to the "fixedRate", "fixedDelay", or "cron" expression provided via the annotation.
Test annotation which indicates that the ApplicationContext associated with a test is dirty and should be closed: after the current test, when declared at the method level after each test method in the current test class, when declared at the class level with class mode set to AFTER_EACH_TEST_METHOD after the current test class, when declared at the class level with class mode set to AFTER_CLASS
Deprecated.as of Spring 3.1 in favor of using built-in support for declaring expected exceptions in the underlying testing framework (e.g., JUnit, TestNG, etc.)
Deprecated.as of Spring 3.0, in favor of moving the non-transactional test method to a separate (non-transactional) test class or to a @BeforeTransaction or @AfterTransaction method.
ProfileValueSourceConfiguration is a class-level annotation which is used to specify what type of ProfileValueSource to use when retrieving profile values configured via the @IfProfileValue annotation.
Annotation that identifies methods which initialize the WebDataBinder which will be used for populating command and form object arguments of annotated handler methods.
Indicates that an annotated class is a "Repository", originally defined by Domain-Driven Design (Evans, 2003) as "a mechanism for encapsulating storage, retrieval, and search behavior which emulates a collection of objects".
Indicates that an annotated class is a "Service", originally defined by Domain-Driven Design (Evans, 2003) as "an operation offered as an interface that stands alone in the model, with no encapsulated state."
Package java.lang.annotation
Provides library support for the Java programming language annotation facility.
자료실에 올라와 있는 교육자료를 받아 보시면 자세하게 나와 있습니다.
간략하게만 정리 합니다.
[준비물]
- eGovFrameDev-2.0.0-FullVer 다운로드
- egovframework-bbsmanagement-2.0.0 다운로드
[프로젝트생성]
- eGovFrame Web Project 생성
- eGovFrame Common Component Implements 추가
- 여기서 공통, 게시판 이렇게 두개 선택 합니다.
- 저는 그냥 Database Source 에 사용하는 mysql 서버 등록해 놓고 걍 사용자 DB에 생성해서 Table 만들었습니다.
- 이렇게 하시면 별도로 globals.properties 를 수정 하지 않아도 됩니다.
[프로젝트실행]
- 해당 프로젝트에서 Run on Server 로 Tomcat 등록 후 실행
- 아래와 같은 관리자 화면이 나오게 됩니다.
- 이미 게시판을 하나 생성을 했지요.
- 일반 사용자가 쓸수 있도록 하기 위해서는
1. 게시판속성관리에서 게시판을 생성 하시구요.
2. 게시판사용정보에서 등록 버튼 누르신 후 생성한 게시판을 등록해 주시면 됩니다.