728x90

-개발환경-

IDE : Eclipse 2018-12 (4.10.0)
Spring Tool Suite : 3.9.7.RELEASE
WAS : Pivotal tc Server Developer Edition v4.0 (피보탈 톰캣 서버)

-설정-

-서버 포트번호 변경-


서버가 오라클,SQL 포트번호와 충돌안나게 안쓰는것으로 변경해주는것이 목표.
디폴트로 서버 포트번호는 8080임 
서버들어가서 => Properties의 nio.http.port 를 9090이나 남는 포트번호로 변경하기


-STS 브라우저 테스트환경 설정해주기-
WINDOW => Web Browser => Chrome 선택해서 테스트 환경을 크롬으로 잡아주기

-한글깨짐방지 태그 추가해주기-
web.xml 파일에서 아래 태그들 추가.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<filter>
    <filter-name>encodingFilter</filter-name>
    <filter-class>
        org.springframework.web.filter.CharacterEncodingFilter     
    </filter-class>
    <init-param>
        <param-name>encoding</param-name>   
        <param-value>UTF-8</param-value>
    </init-param>
    <init-param>
        <param-name>forceEncoding</param-name>  
        <param-value>true</param-value>
    </init-param>
</filter>    
 
<filter-mapping>
    <filter-name>encodingFilter</filter-name>
    <url-pattern>/*</url-pattern>                 
</filter-mapping>
cs

-파일구성-

 

 

-servlet-context.xml-

1
<context:component-scan base-package="com.koreait.springMVCSample" />
cs

 

server-context.xml 에서
<context:component-scan base-package="com.koreait.springMVCSample" /> 가 의미하는것은 아래와 같다.
controller가 있는 패키지 경로를 잡아준다.
base-package는 프로젝트를 생성할때 사용자가 입력한 내용으로 만들어주는 패키지로
@Controller어노테이션을 붙여준 컨트롤러 클래스 파일을 읽어들이는 기본 위치가 된다. 
즉 , @Controller 어노테이션이 붙어있다고 해서 모두 컨트롤러로 인식되는 것이 아니고 
base-package로 지정된 곳에서 @Controller어노테이션이 붙어 있는 클래스만 컨트롤러로 인식한다.

 

-servlet-context.xml-
1
2
3
4
5
<!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory -->
<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <beans:property name="prefix" value="/WEB-INF/views/" />
    <beans:property name="suffix" value=".jsp" />
</beans:bean>
cs

 

servlet-context.xml의 <beans:bean> 태그에서,
컨트롤러 클래스의 @RequestMapping 어노테이션이 붙은 메소드가 리턴하는 view 페이지 이름,앞,뒤에 
자동으로 붙여줄 내용을 지정한다.
@RequestMapping 어노테이션이 붙은 메소드가 리턴하는 view 페이지 이름이 "home" 이라면
"/WEB-INF/views/home.jsp" 가 된다.

 

-HomeController.java-

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package com.koreait.springMVCSample;
 
import java.text.DateFormat;
import java.util.Date;
import java.util.Locale;
 
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
 
@Controller
public class HomeController {
    private static final Logger logger = LoggerFactory.getLogger(HomeController.class);
 
    @RequestMapping( "/index.nhn")
    public String home() {
        return "home"
    }
}
cs

 

18 : 주소창에 서비스 요청이 들어오면 컨트롤러클래스의 
     @RequestMapping 어노테이션의 인수로 지정된 value 속성(생략가능)과
     일치되는지 비교후,  일치된다면 @RequestMapping 어노테이션이 붙어 있는 
     메소드가 실행된다.

     @RequestMapping 속성으로 RequestMethod.GET 이 지정되면 get 방식의 요청만 
     처리할 수 있고 RequestMethod.POST가  지정되면 post방식의 요청만 처리할 수 있다. 
     추가로 , 요청방식이 일치하지 않으면 405 에러가 발생된다.
     ex) @RequestMapping(value = "/", method = RequestMethod.POST)

     아래와 같이 @RequestMapping 어노테이션에서 method 속성을 생략하면 get방식과 post 방식을
     구분하지 않고 모든 요청을 받아 처리할 수 있다.
     value 속성만 남았을때, 'value=' 는 생략 가능

20 : @RequestMapping 어노테이션이 붙은 메소드는
      수행후 view페이지(jsp파일)이름을 리턴시킨다.
      view 페이지 이름은 문자열이므로 메소드의 리턴 타입은 String 이 되고 
      리턴되는 view 페이지 이름의 앞,뒤에 붙여주는 내용은 servlet-context.xml
      파일에서설정한다

 

-MyController.java-

1
2
3
4
5
6
7
@Controller
public class MyController {
    @RequestMapping("/view")    
    public  String view() {
        System.out.println("MyController의 view() 메소드 실행");
        return "view";
    }
cs

일반적인 SPRING MVC 순서. 
     클라이언트로 부터 서비스 요청이 들어왔을 때 , 컨트롤러로 진입하게 되고 
     컨트롤러는 요청에 따른 작업을 실행한 후 뷰 페이지로 데이터를 전달한다.

컨트롤러 제작순서
1. base-package로 지정된 패키지에 임의의 이름으로 클래스를 만들고 @Controller 어노테이션을 붙여서
   컨트롤러로 사용할 클래스임을 스프링에게 알려준다.
2. @RequestMapping어노테이션의 인수로 클라이언트에서 넘어오는 것을 지정한다.
   3.요청을 처리할 임의의 이름의 메소드를 만든다. 
   뷰 페이지 이름은 문자열이므로 메소드의 리턴 타입은 String으로 지정한다.
4. 작성한 메소드에서 필요한 작업을 모두 완료한 후 뷰 페이지(jsp 파일)의 이름을 리턴시킨다.

 

-MyController.java-

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Controller
public class MyController {
 
    ~~~생략~~~
 
@RequestMapping("/model")
    public String model(Model model) {
        System.out.println("MyController의 model() 메소드 실행");
        model.addAttribute("id","asdfg");
        model.addAttribute("pw","12345");
        model.addAttribute("name","홍길동");
        
        return "model/model";
    }
    ~~~생략~~~
cs

 

7 : @RequestMapping 어노테이션이 설정된 메소드는
    Model 인터페이스 객체를 인수로 가질수 있다.
    Model 인터페이스 객체는 컨트롤러에서 뷰 페이지로 넘겨줄 데이터를 저장한다. 
    jsp 의 response객체와 같은 역할을 한다.

9~11 : Model객체변수.addAttribute(key,value) : Model 인터페이스 객체에
          key에 따른  value를 넣어준다.

13 : servlet_context.xml 파일에 의해서 "/WEB-INF/views/model/model.jsp"로 변환된다.
      그리고 해당파일 호출.

-MyController.java-

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Controller
public class MyController {
    ~~~ 생략 ~~~
 
@RequestMapping("/modelAndView")
    public ModelAndView modelAndView(Model model) {
        System.out.println("MyController의 modelAndView() 메소드 실행");
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("modelAndView/modelAndView");
        modelAndView.addObject("id","qwert");
        modelAndView.addObject("pw","67890");
        modelAndView.addObject("name","임꺽정");    
        return modelAndView;
    }
}
cs

 

6 : ModelAndView 클래스 객체는 컨트롤러에서 뷰페이지로 
    뷰 페이지 이름과  데이터를 저장한다.
    뷰 페이지 이름과 뷰페이지로 넘겨줄 데이터를 ModelAndView 클래스 객체에 저장해서
    리턴 시켜야 하므로 메소드의 리턴 타입은 ModelAndView를 사용한다.

기존의 방식은 String을 리턴타입으로 하였다. 차이점 숙지.

8 : 뷰 페이지로 넘겨줄 데이터와 뷰페이지 이름을 저장할 ModelAndView 클래스 객체를 생성한다.

9 : setViewName() : 뷰 페이지 이름을 넣어준다.

10~ 12 : addObject(key,value) : 뷰 페이지로 넘겨줄 데이터를 KEY-VALUE로 저장한다.

13 : ModelAndView  객체를 리턴한다.

 

-YourController.java-(자주 사용되지는 않는다.)

1
2
3
4
5
6
7
8
9
10
@Controller
@RequestMapping("/board")
public class YourController {
 
    @RequestMapping("/contentView")
    public String contentView() {
        System.out.println("YourController의 contentView() 메소드 실행");
        return "board/contentView";
    }
}
cs

 

controller클래스에 @RequestMapping 어노테이션이 직접적으로 붙는다면 ,
controller에 붙은 어노테이션과 메소드에 붙은 어노테이션을 합쳐서
요청해야 뷰페이지를 제대로 찾아갈 수 있다.
이 예제에선 /board/contentView 로 요청해야한다.

 

-servlet-context.xml-

1
2
3
4
<resources mapping="/resources/**" location="/resources/" />
<resources mapping="/images/**" location="/WEB-INF/images/" /> 
<resources mapping="/css/**" location="/WEB-INF/css/" /> 
<resources mapping="/js/**" location="/WEB-INF/js/" /> 
cs

 

resources 태그의 mapping 속성에 지정된 요청이 들어오면 controller클래스를 검색하지 않고 
resources 태그의 location 속성에 지정된 경로를 검색한다.
위의 예에서는 image,css,js 경로를 잡아주었다.

 

 

-model.jsp-

1
2
<link rel="stylesheet" type="text/css" href="css/style.css" >
<script type="text/javascript" src="js/script.js"></script>
cs

css폴더와 , js폴더의 경로는 servlet-context.xml에서 미리 mapping된 경로를 따라간다.

 

-model.jsp-

1
2
3
4
5
6
7
8
9
10
<body>
    <h1 onclick="hello()">model.jsp 입니다<br/></h1>
 
    id: ${id}<br/>
    pw: ${pw}<br/>
    name: ${name}<br/>
    
    <img alt="아무이미지" src="./images/download.jpg"/>
</body>
</html>
cs

4~6 : controller에서 Model인터페이스객체에 저장되서 넘어오는 데이터는
        EL 을 사용해서 얻어오면 된다.
8 : 이미지 src 경로는 servlet-context.xml 에서 미리 정의된 resource mapping을 따라간다.

 

-요약-

-마침글-

 

인용

 

728x90

-개발환경-

IDE : Eclipse 2018-12 (4.10.0)
Spring Tool Suite : 3.9.7.RELEASE
WAS : Pivotal tc Server Developer Edition v4.0 (피보탈 톰캣 서버)

-설정-

-서버 포트번호 변경-


서버가 오라클,SQL 포트번호와 충돌안나게 안쓰는것으로 변경해주는것이 목표.
디폴트로 서버 포트번호는 8080임 
서버들어가서 => Properties의 nio.http.port 를 9090이나 남는 포트번호로 변경하기


-STS 브라우저 테스트환경 설정해주기-
WINDOW => Web Browser => Chrome 선택해서 테스트 환경을 크롬으로 잡아주기

-한글깨짐방지 태그 추가해주기-
web.xml 파일에서 아래 태그들 추가.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<filter>
    <filter-name>encodingFilter</filter-name>
    <filter-class>
        org.springframework.web.filter.CharacterEncodingFilter     
    </filter-class>
    <init-param>
        <param-name>encoding</param-name>   
        <param-value>UTF-8</param-value>
    </init-param>
    <init-param>
        <param-name>forceEncoding</param-name>  
        <param-value>true</param-value>
    </init-param>
</filter>    
 
<filter-mapping>
    <filter-name>encodingFilter</filter-name>
    <url-pattern>/*</url-pattern>                 
</filter-mapping>
cs

-파일구성-

 

 

-servlet-context.xml-

1
<context:component-scan base-package="com.koreait.springMVCSample" />
cs

 

server-context.xml 에서
<context:component-scan base-package="com.koreait.springMVCSample" /> 가 의미하는것은 아래와 같다.
controller가 있는 패키지 경로를 잡아준다.
base-package는 프로젝트를 생성할때 사용자가 입력한 내용으로 만들어주는 패키지로
@Controller어노테이션을 붙여준 컨트롤러 클래스 파일을 읽어들이는 기본 위치가 된다. 
즉 , @Controller 어노테이션이 붙어있다고 해서 모두 컨트롤러로 인식되는 것이 아니고 
base-package로 지정된 곳에서 @Controller어노테이션이 붙어 있는 클래스만 컨트롤러로 인식한다.

 

-servlet-context.xml-
1
2
3
4
5
<!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory -->
<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <beans:property name="prefix" value="/WEB-INF/views/" />
    <beans:property name="suffix" value=".jsp" />
</beans:bean>
cs

 

servlet-context.xml의 <beans:bean> 태그에서,
컨트롤러 클래스의 @RequestMapping 어노테이션이 붙은 메소드가 리턴하는 view 페이지 이름,앞,뒤에 
자동으로 붙여줄 내용을 지정한다.
@RequestMapping 어노테이션이 붙은 메소드가 리턴하는 view 페이지 이름이 "home" 이라면
"/WEB-INF/views/home.jsp" 가 된다.

 

-HomeController.java-

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package com.koreait.springMVCSample;
 
import java.text.DateFormat;
import java.util.Date;
import java.util.Locale;
 
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
 
@Controller
public class HomeController {
    private static final Logger logger = LoggerFactory.getLogger(HomeController.class);
 
    @RequestMapping( "/index.nhn")
    public String home() {
        return "home"
    }
}
cs

 

18 : 주소창에 서비스 요청이 들어오면 컨트롤러클래스의 
     @RequestMapping 어노테이션의 인수로 지정된 value 속성(생략가능)과
     일치되는지 비교후,  일치된다면 @RequestMapping 어노테이션이 붙어 있는 
     메소드가 실행된다.

     @RequestMapping 속성으로 RequestMethod.GET 이 지정되면 get 방식의 요청만 
     처리할 수 있고 RequestMethod.POST가  지정되면 post방식의 요청만 처리할 수 있다. 
     추가로 , 요청방식이 일치하지 않으면 405 에러가 발생된다.
     ex) @RequestMapping(value = "/", method = RequestMethod.POST)

     아래와 같이 @RequestMapping 어노테이션에서 method 속성을 생략하면 get방식과 post 방식을
     구분하지 않고 모든 요청을 받아 처리할 수 있다.
     value 속성만 남았을때, 'value=' 는 생략 가능

20 : @RequestMapping 어노테이션이 붙은 메소드는
      수행후 view페이지(jsp파일)이름을 리턴시킨다.
      view 페이지 이름은 문자열이므로 메소드의 리턴 타입은 String 이 되고 
      리턴되는 view 페이지 이름의 앞,뒤에 붙여주는 내용은 servlet-context.xml
      파일에서설정한다

 

-요약-



 

-마침글-

 

인용

 

728x90

-개요-

Eclipse 나 sts IDE를 이용하면서 WAS설정 관련 오류가 많이 발생도 하고,

웹 홈페이지 구축에도 WAS설정 관련정보지식은 필요할것 같아서 정리해보려 한다.

 

톰캣의 핵심 구성요소들

  • Catalina : 서블릿 컨테이너
  • Coyote : HTTP 커넥터
  • Jasper : JSP Engine

서블릿 컨테이너 : (웹 컨테이너=서블릿 컨테이너)는 웹 서버의 컴포넌트 중 하나이다.

웹 컨테이너는 서블릿의 생명주기를 관리한다.

또 URL과 특정 서블릿을 맵핑하며 URL 요청이 올바른 접근 권한을 갖도록 보장한다.

웹 컨테이너는 서블릿, JSP 파일, 그리고 서버-사이드 코드가 포함된 다른 타입의 파일들에 대한 요청을 다룬다.

웹 컨테이너는 서블릿 객체를 생성하고, 서블릿을 로드와 언로드하며, 요청과 응답 객체를 생성하고 관리하고, 다른 서블릿 관리 작업을 수행한다.

 

Coyote : Coyote는 HTTP 1.1 프로토콜을 웹 서버로 지원하는 Tomcat 용 커넥터구성요소이다.
Coyote는 특정 TCP 포트에서 서버로 들어오는 연결을 수신하고, 요청을 Tomcat 엔진에 전달하여 요청을 처리하고 요청하는 클라이언트에 응답을 다시 보냅니다.

 

Jasper : Jasper는 Tomcat의 JSP 엔진이다.
Jasper는 JSP 파일을 파싱하여 Java 코드를 서블릿으로 컴파일합니다 (Catalina에 의해 처리될수 있음).
런타임도중 JSP파일내용이 변경된다면,
Jasper는 JSP 파일의 변경 사항을 감지하고 다시 컴파일합니다.

 

해당컴포터넌트들을 그림으로 나타내면 아래와 같다.

Tomcat 실제 폴더 구조와 , 
내가 관심이 있는 conf폴더(server.xml  , web.xml  , context.xml , tomcat-users.xml ) 에 대해 기록해 놓았음.
링크  - > cassandra.tistory.com/4 

 

 

 

-참고-

이미지출처 : www.slideshare.net/jieunsys/ss-56543446

자료출처 : en.wikipedia.org/wiki/Apache_Tomcat

728x90

-개발환경-

IDE : Eclipse 2018-12 (4.10.0)
Spring Tool Suite : 3.9.7.RELEASE

-설정-

SPRING 에서 AOP를 사용하기 위해 AOP 라이브러리를 설치해야 한다. 

여기선 AOP 라이브러리들중 aspectj를 다루고 내용은 아래와 같다.

 

pom.xml 파일의 <dependencies> ~ </dependencies> 사이에 아래의 내용을 추가한다.
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.0</version>
<scope>runtime</scope>
</dependency>

-파일구성-

Student.java - 학생VO클래스+핵심메소드 인 클래스

Worker.java - 직장인VO클래스+핵심메소드 인 클래스

LogAOP.java - AOP어노테이션 + 공통기능 메소드(before,after,...)들 인 클래스

applicationCTX.xml - bean객체관리 , AOP일부 태그이용

MainClass.java

 

-LogAOP.java-

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
@Aspect
public class LogAOP {
    
    @Pointcut("within(com.koreait.springAOP2_java.Student)")
    public void pointcutMethod() {
    }
    @Before("pointcutMethod()")
    public void before() {
        System.out.println("LogAOP 클래스의 before() 메소드가 실행됨");
    }
    @AfterReturning("pointcutMethod()")
    public void afterReturning() {
        System.out.println("LogAOP 클래스의 afterReturning() 메소드가 실행됨");
    }
    @AfterThrowing("pointcutMethod()")
    public void afterThrowing() {
            System.out.println("LogAOP 클래스의 afterThrowing() 메소드가 실행됨");
    }
    @After("pointcutMethod()")
    public void after() {
        System.out.println("LogAOP 클래스의 after() 메소드가 실행됨");
    }
    
    @Around("execution(* com.koreait.springAOP2_java.Worker.*())")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
            System.out.println("LogAOP 클래스의 around() 메소드가 실행됨 - 핵심 기능 실행 전");
            long startTime = System.currentTimeMillis();
        try {
            System.out.println("LogAOP 클래스의 around() 메소드가 실행됨 - 핵심 기능 실행 중");
            Object object = joinPoint.proceed();
            return object;
        }finally {
            System.out.println("LogAOP 클래스의 around() 메소드가 실행됨 - 핵심 기능 실행 후");
            long endTime=System.currentTimeMillis();
            System.out.println("핵심 기능이 실행되는데 걸린 시간 : "+(endTime-startTime)/1000.+"초");
        }
    }
}
cs

 

 

1 : java 파일을 이용해서 AOP 설정을 하려면 
    AOP를 설정할 클래스에 @Aspect 어노테이션을 붙여준다.

pointcut을 지정하는 첫 번재 방법 
              1. 함수내용이 empty한 적당한 이름을 가진 메소드를 만든다.
              2. empty한 메소드 위에 @Pointcut 어노테이션을 붙여서 인수에 공통함수가 실행될 경로(pointcut)를 지정한다.
              3. AOP 어노테이션(@Before ,@AfterReturning, @AfterThrowing,@After,@Around) 을 의미가 동일한 메소드위에 각각 적어준다. 
              4. AOP 메소드각각에 pointcut(공통함수가 실행될 경로)을 지정하려면
              AOP 어노테이션(@Before ,@AfterReturning, @AfterThrowing,@After,@Around)의 인수로 pointcut 메소드를 적어준다.

4~22 : pointcut을 지정하는 첫 번재 방법이다.

pointcut을 지정하는 두 번재 방법 
1. AOP 어노테이션(@Before ,@AfterReturning, @AfterThrowing,@After,@Around) 을 의미가 동일한 메소드위에 각각 적어준다.
              2. AOP 어노테이션의 인수에 pointcut을 바로 지정할 수 있다.

24~25 : pointcut을 지정하는 두 번재 방법을 이용하였다.

 

-applicationCTX.xml-

1
2
3
4
5
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd">
cs

 

3 : aop namespace를 잡아준다.

 

-applicationCTX.xml-

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
    <aop:aspectj-autoproxy/>
    
    <bean id="LogAop" class="com.koreait.springAOP2_java.LogAOP"/>
 
    <bean id="student" class="com.koreait.springAOP2_java.Student">
        <property name="name" value="홍길동"/>
        <property name="age" value="15"/>
        <property name="gradeNum" value="2"/>
        <property name="classNum" value="1"/>
    </bean>
    <bean id="worker" class="com.koreait.springAOP2_java.Worker">
        <constructor-arg value="조세길"/>
        <constructor-arg value="20"/>
        <constructor-arg value="웹개발자"/>
    </bean>
</beans>
cs

 

1 : @Aspect 어노테이션을 붙여서 AOP를 설정한 java클래스를 읽어오기 위해서
    <aop:aspectj-autoproxy/> 태그를 추가한다.

3 : AOP 메소드와 설정이 저장된 @Aspect 어노테이션을 붙여준 클래스의 bean을 만든다.

 

-MainClass.java-

1
2
3
4
5
6
7
8
9
10
AbstractApplicationContext ctx = new GenericXmlApplicationContext("classpath:applicationCTX.xml");
Student student=ctx.getBean("student", Student.class);
Worker worker=ctx.getBean("worker", Worker.class);
System.out.println("=================================");
student.getStudentInfo();
System.out.println("=================================");
worker.getWorkerInfo();
System.out.println("=================================");
student.afternoon();
System.out.println("=================================");
cs

 

1 : AbstractApplicationContext-GenericXmlApplicationContext 형태로 컨테이너를 생성한다.

결과를 보자.

출력결과

 

-요약-



 

-마침글-

 

인용

 

728x90

-개발환경-

IDE : Eclipse 2018-12 (4.10.0)
Spring Tool Suite : 3.9.7.RELEASE

-설정-

SPRING 에서 AOP를 사용하기 위해 AOP 라이브러리를 설치해야 한다. 

여기선 AOP 라이브러리들중 aspectj를 다루고 내용은 아래와 같다.

 

pom.xml 파일의 <dependencies> ~ </dependencies> 사이에 아래의 내용을 추가한다.
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.0</version>
<scope>runtime</scope>
</dependency>

-파일구성-

Student.java - 학생VO클래스+핵심메소드 인 클래스

Worker.java - 직장인VO클래스+핵심메소드 인 클래스

Test.java - 외부패키지에 존재하며 , 단순 IntanceMethod 한기 보유한 클래스

LogAOP.java - 공통기능 메소드(before,after,...)를 모아놓은 클래스

applicationCTX.xml - bean객체 , aop태그들을 다루는 파일

MainClass.java

 

-LogAOP.java-

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
public class LogAOP {    
    public void before() {
        System.out.println("LogAOP 클래스의 before() 메소드가 실행됨");
    }
    public void afterReturning() {
        System.out.println("LogAOP 클래스의 afterReturning() 메소드가 실행됨");
    }
    public void afterThrowing() {
            System.out.println("LogAOP 클래스의 afterThrowing() 메소드가 실행됨");
    }
    public void after() {
        System.out.println("LogAOP 클래스의 after() 메소드가 실행됨");
    }
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
            System.out.println("LogAOP 클래스의 around() 메소드가 실행됨 - 핵심 기능 실행 전");
            long startTime = System.currentTimeMillis();
        try {
            System.out.println("LogAOP 클래스의 around() 메소드가 실행됨 - 핵심 기능 실행 중");
            Object object = joinPoint.proceed();
            return object;
        }finally {
            System.out.println("LogAOP 클래스의 around() 메소드가 실행됨 - 핵심 기능 실행 후");
            long endTime=System.currentTimeMillis();
            System.out.println("핵심 기능이 실행되는데 걸린 시간 : "+(endTime-startTime)/1000.+"초");
        }
    }
}
cs

 

around기능보유한 메소드 작성법 ( 개념은 chewingcandy.tistory.com/80 참고) 은 아래와 같다.

1. around AOP 메소드는 핵심기능이  실행되고 난 후 리턴되는 데이터 타입을 예측할 수 없으므로 반드시 리턴 타입을 Object로 지정해야 한다.
2. around AOP 메소드의 인수로 실행할 핵심 기능(메소드)이 넘어온다. => 반드시 인수로 ProceedingJoinPoint 인터페이스 타입의 변수를 사용한다.
3. around  AOP 메소드는 try ~ finally 형태로 실행되며 catch는 throws Throwable로 대체된다.

16 : 핵심 기능이 실행되기 전의 시간을 저장한다

17~20 : try 블록에서 핵심 기능을 실행한다.


19 : ProceedingJoinPoint 인터페이스 객체로 넘어온 핵심 기능을 실행한다.

20 : 핵심 기능을 실행한 결과를 리턴한다.

21~25 : finally 블록 내에서 핵심 기능이 실행되고 난 후 실행할 내용을 코딩한다.

23 : 핵심 기능이 종료되고 난 후 시간을 저장한다.

 

 

-applicationCTX.xml-

1
2
3
4
5
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd">
cs

 

3 : beans 태그에 aop namespace 를 추가해준다.

 

 

-applicationCTX.xml-

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
     <bean id="logAop" class="com.koreait.springAOP1_xml.LogAOP"/>
        <aop:config>
            <aop:aspect id="logger" ref="logAop">      
                <aop:pointcut expression="within(*)" id="beforeMethod"/>
                <aop:pointcut expression="within(*)" id="afterReturningMethod"/>
                <aop:pointcut expression="within(*)" id="afterThrowingMehod"/>        
                <aop:pointcut expression="execution(* com.koreait.springAOP1_xml.Student.*())" id="afterMethod"/>
                <aop:pointcut expression="execution(* com.koreait.springAOP1_xml.Student.*())" id="aroundMethod"/>
        
                <aop:before method="before" pointcut-ref="beforeMethod"/>
                <aop:after-returning method="afterReturning" pointcut-ref="afterReturningMethod"/>
                <aop:after-throwing method="afterThrowing" pointcut-ref="afterThrowingMehod"/>
                <aop:after method="after" pointcut-ref="afterMethod"/> 
                <aop:around method="around" pointcut-ref="aroundMethod"/> 
            </aop:aspect>
        </aop:config>
</beans>
cs

 

1 : AOP 관련 메소드들이 작성된 클래스의  bean을 생성한다.

2 :  aop:config 태그 내부에 aop:aspect 태그로 공통 기능 메소드를 정의한다. 

3 :  id 속성으로 AOP 메소드모음 객체인 bean을 식별한다. 식별만 가능하면 되므로 뭐를 적어도 상관없다.
     ref속성에는 AOP메소드모음 객체인 bean을 참조시킨다.  bean의 id 속성의 값을 쓴다.

4~8 : AOP가 실제로 시행될 경로를 잡아주고 id를 달아준다.
        먼저 , aop:pointcut 태그에서 공통 기능이 적용될 부분(pointcut)을 지정한다.  
        expression 속성은 within() 또는 execution()을 사용해서 pointcut을 지정한다. 
        within()은 클래스 단위로 pointcut을 지정하고
        execution()은 메소드 단위로 pointcut을 지정한다.  
        <aop:pointcut>의 id 속성은 pointcut을 식별하기만 하면 되기 때문에 뭐를 적어도 상관없다.

within(*) => 프로젝트의 모든 클래스에 AOP가 적용된다.
within(test.*) => test 패키지의 모든 클래스에 AOP가 적용된다.
within(com.koreait.springAOP1_xml.*) =>  com.koreait.springAOP1_xml 패키지의 모든 클래스지정
within(com.koreait.springAOP1_xml.Worker) => com.koreait.springAOP1_xml 패키지의 Worker 클래스지정
within(com.koreait.springAOP1_xml.*d*) => com.koreait.springAOP1_xml 패키지의 "d" 를 포함하는 클래스들 지정
 d* : d로 시작한다는 의미 , *d : d 로 끝나는 , *d* : d를 포함하는

execution() 은 () 안에 "*"을 먼저 입력하고 1칸 띄운 후 pointcut을 지정한다.
execution(* test.*.*()) => 구조를 볼때 ,  패키지이름.클래스이름.메소드이름() 꼴임.
execution(* *.*()) => 프로젝트의 모든 클래스의 모든 메소드.


10~14 :  method 속성에는  AOP메소드모음 클래스의 AOP 메소드이름을  적는다. 
            pointcut-ref 속성에는 <aop:pointcut>태그의 id 값을 써준다.

즉, 예시로 <aop:before>태그에서 수행할 AOP메소드를 결정해주고 , 
<aop:pointcut>태그에서 수행할 경로를 결정해주는 것이다.

10 :  핵심기능 실행전 메소드수행태그
11 :  핵심기능이 정상적으로 종료된 후 메소드수행태그
12 : 핵심 기능 실행중 예외가 발생된 후 메소드수행태그
13 : 핵심 기능이 예외 발생 여부와 관계 없이 종료된 후 수행되는 메소드수행태그
14 : exception 발생 여부와 관계없이 핵심 기능이 실행되기 전과 실행되고 난 후 둘다 수행되는 메소드수행태그

 

 

-MainClass.java-

1
2
3
4
5
6
7
8
9
10
11
12
13
AbstractApplicationContext ctx = new GenericXmlApplicationContext("classpath:applicationCTX.xml");
Student student=ctx.getBean("student", Student.class);
Worker worker=ctx.getBean("worker", Worker.class);
Test test=ctx.getBean("test", Test.class);
System.out.println("=================================");
student.getStudentInfo();
System.out.println("=================================");
worker.getWorkerInfo();
System.out.println("=================================");
test.test();
System.out.println("=================================");
student.afternoon();
System.out.println("=================================");
cs

 

1 : 일반적인 AbstractApplicationContext - GenericXmlApplicationContext 방식을 사용하여 bean을 생성하였다.

2~4 : 각각의 객체를 받아온 후.

6~ : 나름 핵심기능이라고 내 스스로 정의한 메소드를 실행시켜보았다.

 

출력결과

 

-요약-



 

-마침글-

 

인용

 

728x90

- AOP ( 관점 지향 프로그래밍) -

 

하나의 프로그램 내의 다양한 모듈(메소드)에서 공통적으로 실행되는 기능과 특정 모듈에서만 실행되는 기능(핵심 기능)을 분리시켜서 사용하는것.

한 모듈에 핵심 기능 이외의 기능이  응집되지 않도록 하기 위한 기술.

 

 

 

AOP 용어는 다음과 같다.

 

aspect - 공통 기능
advice - aspect 자체를 말한다.
joinpoint - advice를 적용해야 하는 멤버 변수나 메소드 => 스프링은 메소드에 적용하는 기능만 지원한다.
pointcut - advice가 실제로 실행되는 부분

 

 

 

SPRING에서 태그나 어노테이션으로 사용되는 AOP 관련 용어들은 다음과 같다.


before - 핵심 기능이 실행되기 전에 advice를 실행한다.
after-returning - 핵심 기능이 정상적으로 종료된 후 advice를 실행한다.
after-throwing - 핵심 기능을 실행하는 도중에 exception이 발생되면 advice를 실행한다.
after - 핵심 기능이 정상적으로 실행되거나 exception이 발생되는 경우를 구분하지 않고 advice를 실행한다.
around - 핵심 기능이 실행되기 전과 실행되고 난 후 exception 발생 여부와 관계없이 advice를 실행한다.

=> 실행 전의 데이터가 실행 후로 넘어간다.

 

 

 

SPRING 에서 AOP를 사용하기 위해 AOP 라이브러리를 설치해야 한다. 

여기선 AOP 라이브러리들중 aspectj를 다루고 내용은 아래와 같다.

 

pom.xml 파일의 <dependencies> ~ </dependencies> 사이에 아래의 내용을 추가한다.
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.0</version>
<scope>runtime</scope>
</dependency>

'21년이전 > IT용어' 카테고리의 다른 글

MIME타입  (0) 2021.06.14
오버헤드  (0) 2021.06.14
Maven  (0) 2021.04.23
sp (stored procedure)  (0) 2021.04.21
network Socket  (0) 2021.04.21
728x90

-개발환경-

IDE : Eclipse 2018-12 (4.10.0)
Spring Tool Suite : 3.9.7.RELEASE

-파일구성-

AdminConnection.java - VO를 다루는 클래스

ApplicationConfig.java- 어노테이션java 클래스

MainClass.java- 메인메소드가 있는 클래스

admin.properties- 'KEY'-'VALUE' 로 이루어진 파일

sub_admin.properties- 'KEY'-'VALUE' 로 이루어진 파일

 

-admin.properties-

1
2
admin.id=asdfg
admin.pw=12345
cs

 

-sub_admin.properties-

1
2
sub_admin.id=qwert
sub_admin.pw=5362
cs

 

-ApplicationConfig.java-

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
@Configuration
public class ApplicationConfig {
    @Value("${admin.id}")
    private String adminId; 
    @Value("${admin.pw}")
    private String adminPw; 
    @Value("${sub_admin.id}")
    private String sub_adminId; 
    @Value("${sub_admin.pw}")
    private String sub_adminPw;
 
    @Bean
    public AdminConnection adminConnection() {
        AdminConnection adminConnection = new AdminConnection();
        adminConnection.setAdminId(adminId);
        adminConnection.setAdminPw(adminPw);
        adminConnection.setSub_adminId(sub_adminId);
        adminConnection.setSub_adminPw(sub_adminPw);
        return adminConnection;
    }
    @Bean
    public static PropertySourcesPlaceholderConfigurer configurer() {
        System.out.println("리턴타입이 PropertySourcesPlaceholderConfigurer인 메소드 자동 실행 하하");
        PropertySourcesPlaceholderConfigurer placeholderConfigurer = new PropertySourcesPlaceholderConfigurer();
        Resource[] resources = new Resource[2]; // properties 파일을 읽어들일 배열을 선언한다.
        resources[0= new ClassPathResource("admin.properties");
        resources[1= new ClassPathResource("sub_admin.properties");
        placeholderConfigurer.setLocations(resources);
        return placeholderConfigurer;
    }
}
cs

 

13~20 : AdminConnection 클래스의 bean을 만든다.

22 : 어노테이션java에서 bean이 생성될 때 자동으로 실행되는 메소드.

반드시 리턴 타입이 PropertySourcesPlaceholderConfigurer 클래스타입이어야한다. 
메소드이름은 뭐를적어도 상관없다

24 : PropertySourcesPlaceholderConfigurer타입 객체 placeholderConfigurer 생성.

25~28 : 읽어야 할 properties 파일이 2개이상인 경우 = > 배열이용

 

읽어야 할 properties 파일이 1개일 경우 => 변수이용

25~28 줄대신에 다음의 순서를 따른다.

1. Resource resource = new ClassPathResource("admin.properties");
2. placeholderConfigurer.setLocation(resource);

 

29 : placeholderConfigurer 반환

3~10 : properties 파일에서 읽어온 데이터를 저장할 멤버 변수를 선언한다.
       properties 파일의 내용이 저장된 리턴 타입이
       PropertySourcesPlaceholderConfigurer 인 메소드가 있어야 해당표현식들을 수행할수있는데,
       @Value 어노테이션인자에 EL을 사용해서 Properties의 KEY-VALUE를 불러온다.
       @Value어노테이션 바로 아래의 멤버 변수에  properties 파일에서 읽어온 내용이 저장된다.

 

 

-MainClass.java-

1
2
3
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(ApplicationConfig.class);
AdminConnection adminConnection = ctx.getBean("adminConnection",AdminConnection.class);
System.out.println("admin.id => " + adminConnection.getAdminId());
cs

 

1. 어노테이션java를 쓸 경우처럼, AnnotationConfigApplicationContext 객체를 생성해서 컨테이너를 생성하였다.

-요약-



 

-마침글-

 

인용

 

728x90

이전에 오류잡겠다고  server.xml의 <Context> 태그를 신나게 건드렷던 적이 있다..

그 오류가 다시 나에게로 돌아와 파일이 분명 존재함에도 404 오류를 발생시켰다.

 

해결법과 <Context> 태그에 대한 설명을 하겠다.

 

<Context docBase="프로젝트명" path="/프로젝트명" reloadable="true" source="org.eclipse.jst.jee.server:프로젝트명"/>

 

이 기본 구조이며 ,  각 구조는 이렇다.

 

docBase : 파일이 실제로 위치한 경로
path : 기본 톰캣 주소뒤에 붙는 기본 경로인데, 
톰캣을 시작시 기본 주소는 http://아이피:포트/  이지만, path가 뒤에 붙어서 http://아피이:포트/path 가됨.

 

즉 Context를 잘못수정하거나 , 지워버리면 404 오류가 발생함.

근본적인 해결책은 아니지만, 파일이있음에도 오류가 발생한다면 Context 태그 부분을 체크하고 수동으로라도 데이터를 넣어주자.

 

-참고-

jeanette.tistory.com/98

 

728x90

-개발환경-

IDE : Eclipse 2018-12 (4.10.0)
Spring Tool Suite : 3.9.7.RELEASE

-파일구성-

AdminConnection.java - 객체 생성 정보가 담긴 class

MainClass.java - 메인 메소드가 담긴 class

admin.properties - KEY , Value로 구성된 파일

applicationCTX.xml - beans 을 관리하는 xml

 

-admin.properties-

1
2
admin.id=asdfg
admin.pw=12345
cs

 

-AdminConnection.java-

1
2
3
4
public class AdminConnection implements EnvironmentAware,InitializingBean{
    private String adminId;
    private String adminPw;
    private Environment env;
cs

 

AdminConnection 클래스의 bean이 생성되는 순간 admin.properties 파일의 내용을 읽어서 멤버 변수에 등록한다.

 

4 : 스프링 컨테이너의 환경설정 정보를 저장한다.

 

-AdminConnection.java-

1
2
3
4
5
6
7
8
    ~ 인스턴스 벨류들, 생성자 및 기본 메소드들 ~    
 
    @Override
    public void setEnvironment(Environment environment) {
        System.out.println("자동으로 setEnvironment() 메소드 실행");
        env = environment;
    }
 
cs

 

( EnvironmentAware인터페이스 - setEnvironment()추상메소드 ) 관계로 , 현 클래스에서 오버라이드됨.

4 : bean이 생성(refresh() 메소드가 실행)되는 순간 자동으로 실행된다.
    메소드의 인수인 Environment인터페이스 변수는 SpringContainer의 환경 설정 정보를 기억하는 객체변수이다.
    environment 에는 스프링이 알아서 AdminConnection 클래스의 bean이 생성되는 순간에 자동으로
    컨테이너(gCtx)의 환경 설정 정보를 넘겨준다.
    즉 ,  properties 정보가 넘어온다. 

6 : Environment인터페이스 타입 멤버 변수 env에 정보를 담는다.

 

-AdminConnection.java-

1
2
3
4
5
6
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("자동으로 afterPropertiesSet() 메소드 실행");
        adminId= env.getProperty("admin.id");
        adminPw= env.getProperty("admin.pw");
    }
cs

 

( InitializingBean인터페이스 - afterPropertiesSet()추상메소드 ) 관계. 현 클래스에서 오버라이드함.

2 : afterPropertiesSet()메소드는 bean이 생성될 때 생성자가 실행되고 난 후 자동으로 실행된다.
4~5 : env에 저장된 properties 정보를 멤버 변수에 저장한다.

함수 작동순서 : first-setEnvironment , second-afterPropertiesSet

 

-applicationCTX.xml-

1
<bean id="adminConnection" class="com.koreait.springProperties1_Environment.AdminConnection"/>
cs

 

단순 bean 객체 생성

 

-MainClass.java-

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
ConfigurableApplicationContext ctx = new GenericXmlApplicationContext();
ConfigurableEnvironment env = ctx.getEnvironment();
MutablePropertySources mutablePropertySources = env.getPropertySources();
        
        try {
            mutablePropertySources.addLast(new ResourcePropertySource("classpath:admin.properties"));
            System.out.println("admin.id => " + env.getProperty("admin.id"));
            System.out.println("admin.pw => " + env.getProperty("admin.pw"));
        } catch (IOException e) {
            e.printStackTrace();
        }
        System.out.println("단순히 properties파일의 내용을 읽어온다");
        System.out.println("=========================");
    
        GenericXmlApplicationContext gCtx = (GenericXmlApplicationContext)ctx;
        gCtx.load("classpath:applicationCTX.xml");
        gCtx.refresh();        
        AdminConnection adminConnection = gCtx.getBean("adminConnection",AdminConnection.class);
        System.out.println("admin.id => " + adminConnection.getAdminId());
        System.out.println("admin.pw => " + adminConnection.getAdminPw());
        System.out.println("=========================");     
        gCtx.close();
cs

 

1 : ConfigurableApplicationContext - 인터페이스. 
    환경 설정 정보를 읽어올 빈 객체(컨테이너)를 만든다.

2 : ConfigurableEnvironment - 인터페이스.
    ConfigurableEnvironment인터페이스 타입의 변수 env에 
    getEnvironment() 메소드로 스프링 컨테이너의 환경 설정 정보를 얻어와 저장한다.

3 : properties 정보를 저장할수 있는 
    MutablePropertySources클래스 변수 mutablePropertySources에다가
    env 의 getPropertySources() 메소드로 properties 정보만 얻어와 저장한다.

6 : properties 정보가 저장된 mutablePropertySources에
    addLast() 메소드로 맨 마지막 위치에 admin.properties 파일의 
    properties 내용을 읽어 추가한다.
    mutablePropertySources 에는 properties 가 저장될 때 key에 따라 value 값이
    저장되는 Map 형태로 저장된다.


7,8 : 스프링 컨테이너 환경에 추가된 properties 파일의 내용은 
       ConfigurableEnvironment인터페이스 객체인 env 의 getProperty() 메소드로 읽는다.

15 : xml 파일에서 bean 설정 정보를 읽어내는 능력과 properties 정보가 담긴 컨테이너 두개 다를
그대로 가져가기 위해서 ConfigurableApplicationContext인터페이스 타입 객체 ctx를
 GenericXmlApplicationContext 클래스 타입으로 형변환 시킨다.

16 : gCtx.load를 수행해서 xml 파일경로를 적재한다.

17 : gCtx.refresh()를 수행해서 bean들을 생성한다.

18 : id가 adminConnection 인 bean 을 얻어온다.

19,20 : 데이터가 정상적으로 출력된다.

-요약-



 

-마침글-

 

인용

 

728x90

-개발환경-

IDE : Eclipse 2018-12 (4.10.0)
Spring Tool Suite : 3.9.7.RELEASE

-admin.properties-

 

1
2
admin.id=asdfg
admin.pw=12345
cs

 

'=' 을 기준으로 왼쪽은 'KEY' 오른쪽은 'Value' 이다.

 

-sub_admin.properties-

 

1
2
sub_admin.id=qwert
sub_admin.pw=5362
cs

 

-applicationCTX.xml-

 

1
2
3
4
5
6
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd">
    ~~
cs

 

xml 파일에서 properties 파일의 내용을 읽어오려면 , 

  1. context namespace를 추가한후
  2. <context:property-placeholder/> 태그의 location 속성에 properties 파일이름을 지정한다.

3 : xml namespace로 context 추가.

 

-applicationCTX.xml-

 

1
2
3
4
5
6
7
<context:property-placeholder location="classpath:admin.properties, classpath:sub_admin.properties"/>
    <bean id="adminConnection" class="com.koreait.springProperties2_xml.AdminConnection">
        <property name="adminId" value="${admin.id}"/>
        <property name="adminPw" value="${admin.pw}"/>
        <property name="sub_adminId" value="${sub_admin.id}"/>
        <property name="sub_adminPw" value="${sub_admin.pw}"/>
    </bean>
cs

 

1 : <context:property-placeholder> 태그 내의 location 속성값으로 properties 파일들을 잡아준다.

    properties 파일들간 구분은 , 로 한다.

3 : 읽어들인 properties 파일의 내용을 참조하기위해 EL표현법 "${KEY값}" 을 이용하였다.

    KEY값으로 properties파일의 key를 적어주었다.

 

-MainClass.java-

 

1
2
3
AbstractApplicationContext ctx = new GenericXmlApplicationContext("classpath:applicationCTX.xml");
AdminConnection adminConnection = ctx.getBean("adminConnection",AdminConnection.class);
System.out.println("admin.id => " + adminConnection.getAdminId());
cs

 

1 : 경로를 가져오자마자 bean 생성을 위해 AbstractApplicationContext-GenericXmlApplicationContext

출력결과

 

 

-마침글-

 

인용

 

+ Recent posts