@Aspect
어노테이션을 이용한 AOPkr.spring.ch02
생성 후 클래스 MyFirstAspect
생성package kr.spring.ch02;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
@Aspect
public class MyFirstAspect {
// 공통 기능 수행
@Pointcut("execution(public String launch())")
public void getPointcut() {
}
// @Before("getPointcut()")
public void before() {
// 메서드 시작 직전에 동작하는 어드바이스
System.out.println("Hello Before! **메서드가 호출되기 전에 나온다!");
}
// @AfterReturning(value = "getPointcut()", returning = "msg")
public void afterReturning(String msg) {
// 메서드 호출이 예외를 내보내지 않고 종료했을 때 동작하는 어드바이스
System.out.println("Hello AfterReturning! **메서드가 호출한 후에 나온다! 전달된 객체 : " + msg);
}
// @AfterThrowing(value = "getPointcut()", throwing = "ex")
public void afterThrowing(Throwable ex) {
// 메서드 호출이 예외를 던졌을 때 동작하는 어드바이스
System.out.println("Hello AfterThrowing! **예외가 생기면 나온다! 예외 : " + ex);
}
// @After("getPointcut()")
public void after() {
// 예외가 발생해도 실행됨
// 메서드 종료 후에 동작하는 어드바이스
System.out.println("Hello After! **메서드가 호출된 후에 나온다!");
}
@Around("getPointcut()")
public String around(ProceedingJoinPoint joinpoint) throws Throwable {
// 메서드 호출 전후에 동작하는 어드바이스
System.out.println("Hello Around before! **메서드가 호출되기 전에 나온다!");
String s = null;
// try~catch~finally 구조로 명시해야 예외가 발생해도 메서드 실행 후 공통 기능을 수행함
try {
// 핵심 기능이 수행된 후 데이터 반환
s = (String)joinpoint.proceed();
}
catch(Exception e) {
e.printStackTrace();
}
finally {
System.out.println("Hello Around after! **메서드가 호출된 후에 나온다! 반환된 객체 : " + s);
}
return s;
}
}
src/main/resources
에 applicationContextAnnote.xml
생성<?xml version="1.0" encoding="UTF-8"?>
<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"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p"
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.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 어노테이션 방식으로 AOP를 구현할 때 사용 -->
<aop:aspectj-autoproxy/>
<!-- 공통 기능을 구현한 클래스를 bean으로 등록 -->
<bean id="myFirstAspect" class="kr.spring.ch02.MyFirstAspect"/>
<!-- 핵심 기능을 구현한 클래스를 bean으로 등록 -->
<bean id="product" class="kr.spring.product.Product"/>
</beans>
SpringMain
생성package kr.spring.ch02;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import kr.spring.product.Product;
public class SpringMain {
public static void main(String[] args) {
AbstractApplicationContext context = new ClassPathXmlApplicationContext("applicationContextAnnote.xml");
// 핵심 기능 실행, 설정 파일에 지정한 설정대로 공통 기능이 수행됨
Product p = (Product)context.getBean("product");
p.launch();
context.close();
}
}
web.xml
에서 설정ActionMap.properties
처럼 요청 URL에 대응할 모델 클래스 정보를 가지고 있음servlet-context.xml
에서 설정pom.xml
.jar
파일들)web.xml
root-context.xml
servlet-context.xml
ch04MVC
, 최상위 패키지명을 kr.spring.mvc
로 지정하고 Spring MVC Project 선택pom.xml
에서 <properties>
태그 사이의 내용을 다음처럼 변경 <java-version>1.8</java-version>
<org.springframework-version>5.0.20.RELEASE</org.springframework-version>
src/main/webapp/WEB-INF
의 web.xml
열고 <web-app>
태그 사이의 내용을 다음처럼 변경 <servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
<filter> <!-- POST 방식 전송시 인코딩 처리를 위해 내장된 필터를 사용; 필터는 요청이 DispatcherServlet에 의해 다뤄지기 전,후에 동작 -->
<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>
</filter>
<filter-mapping> <!-- 컨텍스트 루트 하위의 모든 요청(*.do뿐만 아니라 *.jsp 등 확장자가 다른 경우까지 포함)에 대해 인코딩 필터 처리하도록 설정 -->
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
webapp
폴더 오른쪽 클릭하고 index.jsp
생성<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Spring MVC</title>
</head>
<body>
Hello Spring!!
</body>
</html>
C:\javaWork\apps\apache-tomcat-9.0.55
로 지정하고 Next 선택한 다음 ch04MVC를 Add하고 Finishsrc/main/webapp/WEB-INF/spring/appServlet
에서 servlet-context.xml
열고 다음을 삭제 <context:component-scan base-package="kr.spring.mvc" />
kr.spring.mvc
패키지 삭제kr.spring.ch01.controller
생성 후 새 클래스 HelloController
생성package kr.spring.ch01.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
@Controller // 어노테이션으로 클래스를 HandlerMapping에 등록
public class HelloController {
// 요청 URL과 실행 메서드 연결
@RequestMapping("/hello.do")
public ModelAndView hello() { // 요청 매핑은 어노테이션으로 처리되기 때문에 메서드명은 자유롭게 지정 가능
ModelAndView mav = new ModelAndView();
// 뷰 이름 지정
mav.setViewName("hello"); // JSP 파일명만 지정; servlet-context.xml에 설정된 prefix와 suffix를 조합하여 뷰의 전체 경로를 얻게 됨
// 뷰에서 사용할 데이터 세팅
mav.addObject("greeting", "안녕하세요"); // addOjbect() 메서드로 ModelAndView 객체에 속성명과 속성값을 저장하면 DispatcherServlet에 의해 해당 데이터가 request로 넘겨짐
return mav; // DispatcherServlet에 ModelAndView 객체를 반환
}
}
servlet-context.xml
설정src/main/webapp/WEB-INF/spring/appServlet
에서 servlet-context.xml
열고 <beans:beans>
태그 사이에 다음의 내용을 추가 <!-- MVC 기본 설정 -->
<beans:bean id="helloController" class="kr.spring.ch01.controller.HelloController"/>
webapp
에서 index.jsp
의 <body>
태그 사이의 내용을 다음처럼 수정<a href="${pageContext.request.contextPath}/hello.do">HelloController</a><br>
src/main/webapp/views
에서 home.jsp
삭제하고 새 JSP 파일 hello.jsp
생성<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>인사</title>
</head>
<body>
인사말 : <strong>${greeting}</strong>
</body>
</html>
@RequestParam
kr.spring.ch02.controller
생성 후 새 클래스 SearchController
생성package kr.spring.ch02.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
@Controller
public class SearchController {
/*
* @RequestParam 어노테이션은 HTTP 요청 파라미터를 메서드의 인자로 전달하며, 파라미터명과 호출 메서드의 인자명이 같으면 어노테이션은 생략 가능
* 자료형 역시 인자의 자료형에 맞게 자동으로 형변환됨
*
* @RequestParam 어노테이션은 required 속성의 기본값이 true라 파라미터를 전달하지 않으면 400 오류가 발생
* 해당 속성을 false로 설정하거나 또는 아예 어노테이션을 생략하면 파라미터 값이 없을 때 인자가 null로 처리되어 400 오류가 발생하지 않음
* 단, 인자의 자료형이 int 등 객체가 아닌 경우에는 null을 처리할 수 없어 500 오류가 발생하므로 defaultValue 속성에 값을 지정하는 방식을 사용해야 함
*/
@RequestMapping("/search/internal.do")
public ModelAndView searchInternal(@RequestParam("query") String name, @RequestParam(value = "p", defaultValue = "1") int pageNumber) {
System.out.println("name = " + name + ", p = " + pageNumber);
return new ModelAndView("search/internal"); // 뷰만 반환시에는 ModelAndView 생성자에 뷰 이름을 전달
}
@RequestMapping("/search/external.do")
public ModelAndView searchExternal(@RequestParam(value = "query", required = false) String query, @RequestParam(value = "p", defaultValue = "1") int pageNumber) {
System.out.println("query = " + query + ", p = " + pageNumber);
return new ModelAndView("search/external");
}
}
servlet-context.xml
의 <beans:beans>
태그 사이에 다음의 내용을 추가 <!-- 파라미터(=GET 방식)로 전송된 데이터 처리 -->
<beans:bean id="searchController" class="kr.spring.ch02.controller.SearchController"/>
index.jsp
의 <body>
태그 사이에 다음의 내용을 추가<a href="${pageContext.request.contextPath}/search/internal.do?query=dev">SearchController : internal.do</a><br>
<a href="${pageContext.request.contextPath}/search/external.do">SearchController : external.do</a><br>
views
폴더에 하위 폴더로 search
를 만들고 새 JSP 파일 internal.jsp
생성<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>내부 검색</title>
</head>
<body>
내부 검색
</body>
</html>
search
폴더에 새 JSP 파일 external.jsp
생성<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>외부 검색</title>
</head>
<body>
외부 검색
</body>
</html>
@GetMapping
, @PostMapping
, @ModelAttribute
kr.spring.ch03.controller
생성 후 새 클래스 NewArticleController
생성package kr.spring.ch03.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import kr.spring.ch03.service.ArticleService;
import kr.spring.ch03.vo.NewArticleVO;
@Controller
public class NewArticleController {
@Autowired // 프로퍼티에 @Autowired 명시한 경우, setter는 명시하지 않아도 어노테이션에 의해 자동으로 생성됨
private ArticleService articleService;
// GET 방식으로 폼 호출
// @RequestMapping(value = "/article/newArticle.do", method = RequestMethod.GET)
@GetMapping("/article/newArticle.do") // Spring 4.3에 추가된 보다 간편한 어노테이션
public String form() {
return "article/newArticleForm"; // 데이터 없이 뷰만 반환하는 경우, 메서드 반환형을 String으로 지정하고 뷰 이름을 문자열로 반환하면 DispatcherServlet에서 처리
}
/*
* 1) 호출 메서드에 인자로 자바빈을 명시하면, 실행시 자바빈을 생성해서 request에 전달된 데이터의 파라미터명과 자바빈의 프로퍼티명을 대조해서 일치하면 데이터를 프로퍼티에 세팅
* 2) 호출 메서드에 인자로 자바빈을 명시하면, 자바빈의 클래스명 첫 글자를 소문자로 바꾼 이름을 속성명으로 사용하여 자바빈을 request 영역에 저장
* 3) @ModelAttribute 어노테이션을 이용해서 자바빈을 지정하면, 자바빈을 request 영역에 저장시 속성명을 지정 가능(지정하지 않으면 어노테이션 사용하지 않을 경우와 동일한 속성명 사용)
*/
// POST 방식으로 폼으로부터 데이터를 전달받음
// @RequestMapping(value = "/article/newArticle.do", method = RequestMethod.POST)
@PostMapping("/article/newArticle.do") // Spring 4.3에 추가된 보다 간편한 어노테이션
public String submit(NewArticleVO vo) {
articleService.writeArticle(vo);
return "article/newArticleSubmitted";
}
}
servlet-context.xml
의 <beans:beans>
태그 사이에 다음의 내용을 추가 <!-- POST 방식으로 전송된 데이터 처리 -->
<beans:bean id="newArticleController" class="kr.spring.ch03.controller.NewArticleController"/>
index.jsp
의 <body>
태그 사이에 다음의 내용을 추가<a href="${pageContext.request.contextPath}/article/newArticle.do">NewArticleController</a><br>
views
폴더에 하위 폴더로 article
을 만들고 새 JSP 파일 newArticleForm.jsp
생성<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>게시글 쓰기</title>
</head>
<body>
게시글 쓰기 입력 폼
<form action="newArticle.do" method="post">
<input type="hidden" name="parentId" value="7">
제목 : <input type="text" name="title"><br>
내용 : <textarea rows="5" cols="30" name="content"></textarea><br>
<input type="submit" value="전송">
</form>
</body>
</html>
kr.spring.ch03.vo
생성하고 새 클래스 NewArticleVO
생성package kr.spring.ch03.vo;
public class NewArticleVO {
private String title;
private String content;
private int parentId;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public int getParentId() {
return parentId;
}
public void setParentId(int parentId) {
this.parentId = parentId;
}
@Override
public String toString() {
return "NewArticleVO [title=" + title + ", content=" + content + ", parentId=" + parentId + "]";
}
}
article
폴더에 새 JSP 파일 newArticleSubmitted.jsp
생성<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>게시글 등록 완료</title>
</head>
<body>
게시글 등록이 완료되었습니다.<br>
<br>
제목 : ${newArticleVO.title}<br>
내용 : ${newArticleVO.content}<br>
아이디 : ${newArticleVO.parentId}
</body>
</html>
kr.spring.ch03.service
생성하고 새 클래스 ArticleService
생성package kr.spring.ch03.service;
import kr.spring.ch03.vo.NewArticleVO;
public class ArticleService {
public void writeArticle(NewArticleVO vo) {
System.out.println("신규 게시글 등록 : " + vo);
}
}
servlet-context.xml
의 <beans:beans>
태그 사이에 다음의 내용을 추가 <!-- @Autowired 사용을 위해서 -->
<context:annotation-config/>
<!-- POST 방식으로 전송된 데이터 처리 -->
<beans:bean id="articleService" class="kr.spring.ch03.service.ArticleService"/>
@CookieValue
kr.spring.ch04.controller
생성하고 새 클래스 CookieController
생성package kr.spring.ch04.controller;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.CookieValue;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class CookieController {
@RequestMapping("/cookie/make.do")
public String make(HttpServletResponse response) { // 메서드가 구동될 때 인자의 자료형을 확인하여 일치하는 객체가 있으면 전달; HttpServletResponse 객체는 이미 생성되어 있으므로 전달됨
// 쿠키를 생성해서 클라이언트에 전송
response.addCookie(new Cookie("auth", "1"));
return "cookie/make";
}
/*
* @CookieValue 어노테이션을 이용하면 쿠키 값을 메서드 인자로 전달받을 수 있음
* 해당 쿠키가 존재하지 않으면 기본적으로 400 오류가 발생
* @CookieValue(value = "쿠키 이름", required = false)로 지정시, 쿠키가 존재하지 않으면 인자에 null 값을 전달
* @CookieValue(value = "쿠키 이름", defaultValue = "값")로 지정시, 쿠키가 존재하지 않으면 인자에 defaultValue에 지정했던 값을 전달
*/
@RequestMapping("/cookie/view.do")
public String view(@CookieValue(value = "auth", defaultValue = "0") String auth) {
System.out.println("auth 쿠키 : " + auth);
return "cookie/view";
}
}
views
폴더에 하위 폴더로 cookie
생성하고 새 JSP 파일 make.jsp
생성<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>쿠키</title>
</head>
<body>
쿠키를 생성함
</body>
</html>
servlet-context.xml
의 <beans:beans>
태그 사이에 다음의 내용을 추가<beans:bean id="cookieController" class="kr.spring.ch04.controller.CookieController"/>
index.jsp
의 <body>
태그 사이에 다음 내용을 추가<a href="${pageContext.request.contextPath}/cookie/make.do">CookieController : make.do</a><br>
<a href="${pageContext.request.contextPath}/cookie/view.do">CookieController : view.do</a><br>
cookie
폴더에 새 JSP 파일 view.jsp
생성<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>쿠키</title>
</head>
<body>
쿠키 확인
</body>
</html>