Post

๐Ÿฅœ [Spring] AOP (+annotation) & Spring-Boot

AOP

JoinPoint ์€ Adivce ์˜ Cross Cutting Concern์ด Target ํด๋ž˜์Šค์˜ ์–ด๋Š ๋ฉ”์†Œ๋“œ, ์–ด๋Š ์œ„์น˜์— ๊ฝ‚ํžˆ๋Š” ๊ณณ์ด๋‹ค.

JoinPoint ์ŠคํŽ™๋ฅผ ์ƒ์„ธํ•˜๊ฒŒ ์ ์–ด๋†“์€ ๊ฒƒ์€ PointCut ์ด๋‹ค.

์ €๋ฒˆ ํฌ์ŠคํŠธ์˜ AOP advice class ๋ฅผ ์ฐธ๊ณ ํ•˜์ž

1
2
3
4
5
6
7
8
9
10
public class LoggingAdvice {
	private Log log = LogFactory.getLog(getClass());
	
	public void logPush(ProceedingJoinPoint pjp) throws Throwable{
        log.info("\ncheck...before logging...");

        Object ret=pjp.proceed();//target์œผ๋กœ weaving๋˜๋Š” ์‹œ์ 
        System.out.println("target method return..."+ret);
	}
}

ProceedingJoinPoint๊ฐ€ proceed() ํ•จ์ˆ˜๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋Š”๋ฐ, ์ด๊ฒƒ์ด Target์ด ํ˜ธ์ถœ๋˜๋ฉด proceed() ๊ฐ€

ํ˜ธ์ถœ๋˜์–ด Targetํ˜ธ์ถœ ์œ„์น˜๋ฅผ ๊ฐ์ง€ํ•œ๋‹ค.

๋”ฐ๋ผ์„œ ๊ทธ๊ณณ์— ์›ํ•˜๋Š” ๋ถ€๋ถ„์— Advice ๋ฅผ weaving ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ด๋‹ค.

Object ret=pjp.proceed()

Target ํ•จ์ˆ˜์˜ return ํƒ€์ž…์œผ๋กœ ๋ฐ˜ํ™˜๋œ๋‹ค. ๋”ฐ๋ผ์„œ ret๋Š” Targetํ•จ์ˆ˜์˜ returnํƒ€์ž…์ด ๋“ค์–ด๊ฐ„๋‹ค.

1
2
3
4
5
6
7
8
<!-- Advice์˜ ์–ด๋–ค ๋ฉ”์†Œ๋“œ๊ฐ€ Target์— ์–ด๋””๋กœ weaving ๋˜๋Š”์ง€๋ฅผ ์ง€์ •ํ•ด์ค˜์•ผ ํ•œ๋‹ค. => <aop:config> -->
<!--Advice์˜ ์–ด๋–ค ๊ธฐ๋Šฅ์ด Target ๋ฉ”์†Œ๋“œ ํ˜ธ์ถœ ๋  ๋•Œ weaving ๋˜๋Š”์ง€๋ฅผ ์ž์„ธํžˆ ์„ค์ •ํ•˜๋Š” ๋ถ€๋ถ„์ด๋‹ค.  -->
<aop:config>
	<aop:aspect id="loggingAspect" ref="logging">
		<aop:pointcut expression="execution(* spring.aop..*(..))" id="pc"/> <!--Target์˜ ํ™•์žฅ์ž๋Š” ์ƒ๊ด€์—†๊ณ , spring.aop ๋ฐ‘์— ์•„๋ฌด๊ฑฐ๋‚˜ ์ƒ๊ด€์—†์ด  -->
		<aop:around method="logPush" pointcut-ref="pc"/>
	</aop:aspect>
</aop:config>

<aop:pointcut>์€ Target ์˜ ์–ด๋Š ๋ถ€๋ถ„์ด JoinPoint ์ธ์ง€ ์ •ํ•ด์ฃผ๊ณ  ์žˆ๋‹ค.

(..) ์•ž์— ์žˆ๋Š” ๊ฒƒ์€ ํ•จ์ˆ˜ ๋ช…์ด๋‹ค.

*(..) : Target ํด๋ž˜์Šค์˜ ๋ชจ๋“  ํ•จ์ˆ˜์— ์ ์žฌํ–ˆ๋‹ค.

spring.aop.Service : spring โ†’ aop โ†’ Serviceํด๋ž˜์Šค ์— ์žˆ๋Š” ๋ชจ๋“  ํ•จ์ˆ˜

spring.aop. : spring โ†’ aop ์— ์กด์žฌํ•˜๋Š” ๋ชจ๋“  ํด๋ž˜์Šค

์ด๋ ‡๊ฒŒ xml ์„ ์ž‘์„ฑํ•˜๋ฉด ๊ธธ์–ด์งˆ ์ˆ˜ ์žˆ๋‹ค.

๋”ฐ๋ผ์„œ Annotation ์œผ๋กœ ๋งŒ๋“ค์–ด์•ผ ํ•œ๋‹ค.

์ €๋ฒˆ์— ๋งŒ๋“ค์—ˆ๋˜ LogginAdvice(Advice Class) ๋ฅผ Annotation ์œผ๋กœ ๋ณ€ํ™˜ํ•˜์ž

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package spring.aop.anno;

/*
 * ๋ถ€์ˆ˜์ ์ธ ๊ด€์‹ฌ์‚ฌ๋งŒ ๋ชจ์•„ ๋†“์€ ํด๋ž˜์Šค...Cross Cutting Concern
 * Advice Class
 * Annotation์œผ๋กœ ๋งŒ๋“ ๋‹ค๋Š” ์˜๋ฏธ๋Š” aop์„ค์ •์„ ์ฝ”๋“œ๋กœ ์ž‘์„ฑํ•œ๋‹ค๋Š” ์˜๋ฏธ
 */
//<aop:config> ์„ค์ • ๋ถ€๋ถ„์€ ์ด์ œ xml์—์„œ ์‚ฌ๋ผ์ง„๋‹ค.
@Aspect
public class LoggingAdvice {
	private Log log = LogFactory.getLog(getClass());
	
	//Target ํด๋ž˜์Šค ๋ฉ”์†Œ๋“œ์˜ return ํƒ€์ž…์ด String์ด๊ณ  springํŒจํ‚ค์ง€ ์•„๋ž˜์— ์žˆ๋Š” ๋ชจ๋“  ํ•˜์œ„ ํŒจํ‚ค์ง€ ์ค‘์—์„œ 
	//ํด๋ž˜์Šค ์ด๋ฆ„์ด Product๋กœ ์‹œ์ž‘ํ•˜๋Š” ํด๋ž˜์Šค ...ํ•จ์ˆ˜๋ช…์ด delete๋กœ ์‹œ์ž‘ํ•˜๊ณ ...์ธ์ž๊ฐ’์ด 1๊ฐœ ์ด์ƒ์ธ
	@Around("execution(String spring..Product*.delete*(..))")
	public void logPush(ProceedingJoinPoint pjp) throws Throwable{
        log.info("\ncheck...before logging...");
        Object ret=pjp.proceed();//target์œผ๋กœ ์œ„๋น™๋˜๋Š” ์‹œ์ 
        System.out.println("target method return..."+ret);
	}
}

์œ„์˜ ์ฝ”๋“œ์—์„œ ์ฃผ์„์„ ์ž˜ ์‚ดํŽด๋ณด์ž.

@Aspect ์„ ์ฒ˜์Œ์— ์„ ์–ธํ•ด์ฃผ๊ณ , @Around ๋ฅผ Cross Cutting Concern ์•ž์— ๋„ฃ์–ด์ค€๋‹ค.

์œ„์— Advice ๋Š” Annotation ์œผ๋กœ ๋งŒ๋“ค์–ด์„œ Bean ์„ค์ • ๋ฌธ์„œ๋ฅผ ๋‹ค์‹œ ์„ค์ •ํ•ด์•ผ ํ•œ๋‹ค.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?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"
	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-4.0.xsd">

<!-- Target 2๊ฐœ (member, product),  Advice 1๊ฐœ (logging)  -->
<bean id="member" class="spring.aop.anno.MemberService"/>
<bean id="product" class="spring.aop.anno.ProductService"/>
<bean id="logging" class="spring.aop.anno.LoggingAdvice"/>

<!--aopconfig์„ annotation์œผ๋กœ ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ์•Œ๋ ค์ค˜์•ผ ํ•œ๋‹ค.  -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy> //์ถ”๊ฐ€!!!!!!!!!!!!!!!!!

</beans>

์ด์ „์— xml ์—์„œ aop ๊ฐ€ ๋‹ค ์‚ฌ๋ผ์ง€๊ณ  ์œ„์—์„œ ์ƒˆ๋กญ๊ฒŒ ์ถ”๊ฐ€ํ•œ ํ•œ์ค„๋งŒ ๋„ฃ์–ด์ฃผ๋ฉด ๋œ๋‹ค.



๊ฒ€์ƒ‰์–ด ์ˆœ์œ„ ๊ธฐ๋Šฅ ๊ตฌํ˜„

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
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<h2 align="center">Product Register Form...</h2>
	<form action="myProduct.do" method="post">
	์ƒํ’ˆ๋ช… : <input type="text" name="name"><br><br>
	์ œ์กฐ์‚ฌ : <input type="text" name="maker"><br><br>
	๊ฐ€  ๊ฒฉ  : <input type="text" name="price"><br><br>
	
	<input type="submit" value="์ƒํ’ˆ๋“ฑ๋ก">
	</form>
	
	+++++++++++++++++++++++++++++++++++++++++++++++++++
	<br><br>
	<form action="productSearch.do">
	์ƒํ’ˆ๋ช… ๊ฒ€์ƒ‰  <input type="text" name="word"><br><br>
	<input type="submit" value="๊ฒ€์ƒ‰ํ•˜๊ธฐ">
	</form>
	
	<p>
	<hr>
	<a href="report.do">๊ฒ€์ƒ‰์–ด ์ˆœ์œ„๋ณด๊ธฐ</a>
</body>
</html>

๋จผ์ € ์ƒํ’ˆ๋ช… ๊ฒ€์ƒ‰์— ์ƒํ’ˆ๋ช…์„ ์ž…๋ ฅํ•˜๊ณ  ๊ฒ€์ƒ‰ํ•˜๊ธฐ ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด โ€œproductSearch.doโ€๋กœ ์š”์ฒญ์ด ๋“ค์–ด๊ฐ„๋‹ค.

1
2
3
4
5
6
7
@RequestMapping("productSearch.do")
	public String findByProductName(String word, Model model)throws Exception{		
		
		System.out.println("ProductController...findByProductName() :: "+word);	
		model.addAttribute("list", myProductService.findByProductName(word));
		return "find_result";
	}

๊ทธ๋ฆฌ๊ณ  find_result๋กœ ๋„ค๋น„๊ฒŒ์ด์…˜ ํ•ด์ค€๋‹ค. ๊ฒ€์ƒ‰์–ด๋Š” ์„ธํƒ๊ธฐ๋ฅผ ๊ฒ€์ƒ‰ํ•ด์ฃผ์—ˆ๋‹ค.

image-46 (์„ธํƒ๊ธฐ๋ฅผ ๊ฒ€์ƒ‰ํ•œ ๊ฒฐ๊ณผ)

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
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!--  jstl :: ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๋‹ค์šด, taglib ์„ ์–ธ-->
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<style type="text/css">
	td, h2{
		text-align: center;
	}
	table{
		background-color: yellow;
	}
</style>
</head>
<body>
	<h2>+++++++++ ์ƒํ’ˆ์ •๋ณด๋ฅผ ์ถœ๋ ฅํ•ฉ๋‹ˆ๋‹ค ++++++++++++</h2>
	<table border="2" align='center' width="50%">
		<thead>
			<tr>
				<th>์•„์ด๋””</th><th>์ƒํ’ˆ๋ช…</th><th>์ œ์กฐ์‚ฌ</th><th>๊ฐ€๊ฒฉ</th>
			</tr>
		</thead>
		<tbody>
			<c:forEach items="${list}"  var="vo">
				<tr>
					<td>${vo.id}</td>
					<td>${vo.name}</td>
					<td>${vo.maker}</td>
					<td>${vo.price}</td>
				</tr>
			</c:forEach>
		</tbody>
	</table>
	<p></p>
	<center><a href="product.jsp">์ƒํ’ˆ๊ฐ€์ž…ํ•˜๊ธฐ ํ™ˆ์œผ๋กœ...</a></center>
</body>
</html>

์ด์ œ๋Š” ๋ฉ”์ธํŽ˜์ด์ง€์—์„œ ๊ฒ€์ƒ‰์–ด ์ˆœ์œ„ ๋ณด๊ธฐ ๋ฅผ ๋ˆ„๋ฅด๋ฉด report.do๋กœ ์š”์ฒญ์ด ๋“ค์–ด๊ฐ„๋‹ค.

์—ฌ๊ธฐ์„œ AOP๊ธฐ์ˆ ์ด ๋“ค์–ด๊ฐ„๋‹ค.

์ƒํ’ˆ๋ช…์ด ๊ฒ€์ƒ‰์ด ๋˜๋ฉด Advice ํด๋ž˜์Šค๊ฐ€ ๊ฐœ์ž…ํ•ด ์–ผ๋งˆ๋‚˜ ๋งŽ์ด ๊ฒ€์ƒ‰ํ–ˆ๋Š”์ง€ ๊ฒ€์ƒ‰์–ด๋ฅผ ์„ธ์–ด์•ผ ํ•œ๋‹ค.

์ด๋•Œ AOP๊ฐ€ ์‚ฌ์šฉ๋œ๋‹ค.

์ผ๋‹จ ๋จผ์ € ๊ฒ€์ƒ‰์–ด๋ฅผ ์ €์žฅํ•˜๊ธฐ ์œ„ํ•ด report๋ผ๋Š” ํ…Œ์ด๋ธ”์„ ์ƒˆ๋กœ๋งŒ๋“ค์–ด ์ฃผ์—ˆ๋‹ค.

1
2
word -- ๊ฒ€์ƒ‰์–ด
cnt --๊ฒ€์ƒ‰์–ด๊ฐ€ ์–ผ๋งˆ๋‚˜ ๋งŽ์ด ๊ฒ€์ƒ‰๋˜์—ˆ๋Š”์ง€

ํ…Œ์ด๋ธ”์ด ์ƒˆ๋กœ ์ถ”๊ฐ€๋˜์—ˆ์œผ๋ฏ€๋กœ ํ•ด๋‹น DB ์ฟผ๋ฆฌ๋ฅผ ์ž‘์„ฑํ•˜๊ธฐ ์œ„ํ•ด mapping.xml์„ ์ž‘์„ฑํ•ด์•ผํ•œ๋‹ค.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
	"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="ns.sql.reportMapper">
	<insert id="insertReport" parameterType="string">
		INSERT INTO report VALUES(#{VALUE}, 1)
	</insert>

	<update id="updateReport" parameterType="string">
		UPDATE report SET cnt = cnt+1 WHERE word=#{VALUE}
	</update>
	
	<select id="selectReport" resultType="hashmap">
        <![CDATA[
            SELECT word, cnt, ranking FROM(
                SELECT word, cnt, rank() over(ORDER BY cnt DESC) as ranking
                FROM report
            )
            WHERE ranking <= 5
        ]]>
  </select> 
</mapper>

์œ„ xml ํŒŒ์ผ์„ ๊ธฐ์ค€์œผ๋กœ DAO ํด๋ž˜์Šค์™€ Service ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค์–ด ์ฃผ์ž.

๋จผ์ € DAO ํด๋ž˜์Šค์ด๋‹ค.

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
// dao class
package com.service.spring.aop.model;

@Repository
public class ReportDAOImpl implements ReportDAO{
	
	@Autowired
	private SqlSessionTemplate sqlSession;
	public static final String NS="ns.sql.reportMapper.";
	
	@Override
	public void insertReport(String word) throws SQLException {
		sqlSession.insert(NS+"insertReport",word);
		
	}

	@Override
	public int updateReport(String word) throws SQLException {
		return sqlSession.update(NS+"updateReport",word);
	}

	@Override
	public List selectReport() throws SQLException {
		return sqlSession.selectList(NS+"selectReport");
	}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// Service class
package com.service.spring.aop.model;

@Service
public class ReportServiceImpl implements ReportService{
	
	@Autowired
	private ReportDAO reportDAO;
	
	
	@Override
	public List selectReport() throws SQLException {		
		return reportDAO.selectReport();
	}

	@Override
	public void saveReport(String word) throws SQLException {
		int result=reportDAO.updateReport(word);	
		System.out.println(result+"***************************");
		if(result==0) //0์ด๋ผ๋Š” ๊ฒƒ์€ ์ตœ์ดˆ๋กœ ๊ฒ€์ƒ‰๋œ ๊ฒ€์ƒ‰์–ด๋ผ๋Š” ์˜๋ฏธ์ด๋‹ค. ๋”ฐ๋ผ์„œ DB์— ๋„ฃ์–ด์ค€๋‹ค.
			reportDAO.insertReport(word);
	}
}

reportService ์˜ ํ•จ์ˆ˜๋Š” 2๊ฐœ

  1. selectReport

    ๋žญํ‚น ์ˆœ์œ„ ๊ฒฐ๊ณผํŽ˜์ด์ง€

  2. saveReport

    ์—ฌ๊ธฐ์„œ AOP๊ฐ€ ์ ์šฉ๋œ๋‹ค

์ด์ œ report.do์˜ ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•  Controller ๋ฅผ ๋งŒ๋“ค์–ด์ค€๋‹ค.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package com.service.spring.aop.controller;

@Controller
public class ReportController {
	
	@Autowired
	private ReportService reportService;
	
	@RequestMapping("/report.do")
	public String selectReport(Model model)throws Exception{
		
		model.addAttribute("list", reportService.selectReport());		
		return "report_result";
	}	
}

์—ฌ๊ธฐ์„œ๋Š” ๊ทธ๋ƒฅ ์ˆœ์œ„ ๋ฆฌ์ŠคํŠธ๋งŒ ๋ฐ›์•„์„œ model ์— ์ €์žฅํ•ด์ค€๋‹ค.

์ด์ œ AOP ๊ฐ€ ๋“ค์–ด๊ฐ€๋Š” ๋ถ€๋ถ„์„ ๋ณด์ž.

Advice ์˜ ํด๋ž˜์Šค๋ฅผ ๋ณด์ž

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// advice class
package com.service.spring.aop.advice;

@Component
@Aspect
@EnableAspectJAutoProxy //ํ•ด๋‹น Annotation์„ ์‚ฌ์šฉํ•˜๋ฉด xmlํŒŒ์ผ์— ์•„๋ฌด๊ฒƒ๋„ ์“ธ ํ•„์š”๊ฐ€ ์—†๋‹ค
public class ReportAspect {
	@Autowired
	private ReportService reportService;	
	
	@Around("execution(* com.service..*Service*.find*(String))")	
	public Object report(ProceedingJoinPoint pjp)throws Throwable{
		Object retValue;
		
		retValue = pjp.proceed();//target ๋ฉ”์†Œ๋“œ๊ฐ€ ํ˜ธ์ถœ..
		System.out.println("target call...");
		List list = (List)retValue;
		if(!list.isEmpty()) { //์ฐพ์€ list๊ฐ€ ์žˆ์œผ๋ฉด... cnt=cnt+1๋กœ updateํ•ด์ค˜์•ผ ํ•œ๋‹ค.
			Object[ ] params=pjp.getArgs();
			reportService.saveReport(params[0].toString());			
		}
		return list;
	}
}

com.service ํŒจํ‚ค์ง€ ๋˜๋Š” ๊ทธ ํ•˜์œ„ ํŒจํ‚ค์ง€์— ์žˆ๋Š”, ์ด๋ฆ„์ด Service๋กœ ๋๋‚˜๋Š” ํด๋ž˜์Šค์—, find๋กœ ์‹œ์ž‘ํ•˜๊ณ  String ํƒ€์ž…์˜ ์ธ์ž๋ฅผ ๋ฐ›๋Š” ๋ชจ๋“  ๋ฉ”์„œ๋“œ๋ฅผ ๋Œ€์ƒ์œผ๋กœ ํ•œ๋‹ค.

๋ฐ”๋กœ

1
2
3
4
5
6
7
package com.service.spring.service;

public interface MyProductService {
	int addProduct(MyProduct vo) throws Exception;
	
	public List<MyProduct> findByProductName(String name)throws Exception;
}

findByProductName์ด๋‹ค.

findByProductName() ์ด ํ˜ธ์ถœ๋˜๋ฉด Targetํด๋ž˜์Šค์ด๋‹ค.

์ด์ œ ๊ฒฐ๊ณผํŽ˜์ด์ง€์ธ report_result.jsp๋ฅผ ๋ณด์ž

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
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c"  uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">  
<title>Insert title here</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/css/bootstrap.min.css">
<script src="https://cdn.jsdelivr.net/npm/jquery@3.6.4/dist/jquery.slim.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/js/bootstrap.bundle.min.js"></script>
</head>
<body>
	<div class="container  text-center">
	  <div class="jumbotron">
	  	<h3>AOP๋ฅผ ์ด์šฉํ•ด์„œ ๊ฒ€์ƒ‰์–ด ํ†ต๊ณ„๋ณด๊ธฐ</h3>
	  </div>  
	
	<table class="table table-bordered">
		<thead>
		<tr>
			<th>๋žญ ํ‚น</th><th>๊ฒ€์ƒ‰์–ด</th><th>์กฐํšŒ์ˆ˜</th>
		</tr>
		</thead>
		<c:forEach var="reportMap" items="${list}">
			<tr>		
				<td>${reportMap.RANKING}</td>
				<td>${reportMap.WORD}</td>
				<td>${reportMap.CNT}</td>
			</tr>
		</c:forEach>
	</table>
	</div>
</body>
</html>

image-47 (๊ฒฐ๊ณผ ํ™”๋ฉด)



Spring Boot

  1. Spring Boot๋Š” Tomcat server๊ฐ€ ๋‚ด์žฅ๋˜์–ด์ ธ ์žˆ๋‹ค.
  2. Spring Boot๋Š” web.xml์ด ์ œ๊ณต๋˜์ง€ ์•Š๋Š”๋‹ค.
  3. Context Path๊ฐ€ ์žกํžˆ์ง€ ์•Š๋Š”๋‹ค. ์—†๋‹ค.

image-48

com.service.spring ํ•˜์œ„์— ๋ชจ๋“ ๊ฒƒ์„ ๋งŒ๋“ค์–ด์•ผ ํ•œ๋‹ค.

๊ทธ๋ž˜์•ผ Spring Boot์˜ ์˜ํ–ฅ์„ ๋ฐ›์„ ์ˆ˜ ์žˆ๋‹ค.

๋จผ์ € Spring Boot ์„œ๋ฒ„๋ฅผ ๊ฐ€๋™์‹œ์ผœ์•ผ ํ•œ๋‹ค.

๋ฐ”๋กœ Sq18Boot1Application.java ๋ฅผ ์‹คํ–‰์‹œํ‚จ๋‹ค.

1
2
3
4
5
6
7
8
9
10
11
12
package com.service.spring;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Sp18Boot1Application {

	public static void main(String[] args) {
		SpringApplication.run(Sp18Boot1Application.class, args);
	}
}
This post is licensed under CC BY 4.0 by the author.