티스토리 뷰
Spring 프레임워크를 이용해 방명록 만들기
방명록 실습
- Spring JDBC를 이용한 DAO 작성
- Controller + Service + Dao
- 트랜잭션 처리
- Spring MVC에서 폼 값 입력받기
- Spring MVC에서 redirect하기
- Controller에서 jsp에게 전달한 값 el, jstl을 이용해 출력하기
방명록 요구사항
- 방명록 정보는 guestbook 테이블에 저장된다.
- id는 자동으로 입력된다.
- id, 이름, 내용, 등록일을 저장한다.
프로젝트 만들기
Maven 프로젝트, artifactid는 guestbook으로 생성
*pom.xml
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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115 |
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>kr.or.connect</groupId>
<artifactId>guestbook</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>guestbook Maven Webapp</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<spring.version>4.3.18.RELEASE</spring.version>
<jackson2.version>2.8.11</jackson2.version>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<!-- Servlet & JSP & jstl -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
<version>2.3.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!-- Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- Spring JDBC, JDBC drvier, connection pool -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.46</version>
</dependency>
<!-- basic data source -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-dbcp2</artifactId>
<version>2.1.1</version>
</dependency>
<!-- jacjson module -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>${jackson2.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jdk8</artifactId>
<version>${jackson2.version}</version>
</dependency>
</dependencies>
<build>
<finalName>guestbook</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.6.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
|
cs |
maven 업데이트 → ...core.xml 에서 web 모듈 3.1로 수정 → 이클립스 재실행 후 facet 확인
*WebMvcContextConfiguration.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
39
40
41
42
43
44
45
46
47 |
package kr.or.connect.guestbook.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
@Configuration
@EnableWebMvc //기본적인 설정들을 자동으로 해줌
@ComponentScan(basePackages = { "kr.or.connect.guestbook.controller" }) //컨트롤러 읽어오기
public class WebMvcContextConfiguration extends WebMvcConfigurerAdapter{
//아래 설정들은 DispatcherServlet이 읽게 된다.
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {//특정 파일들 읽어올 경로 따로 지정
registry.addResourceHandler("/css/**").addResourceLocations("/css/").setCachePeriod(31556926);
registry.addResourceHandler("/img/**").addResourceLocations("/img/").setCachePeriod(31556926);
registry.addResourceHandler("/js/**").addResourceLocations("/js/").setCachePeriod(31556926);
}
// default servlet handler를 사용하게 합니다.
// 매핑정보가 없는 요청이 들어올 때 처리하는 메서드
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
//특정 url에 대한 처리를 컨트롤러를 작성하지 않고 매핑할 수 있도록 해주는 부분
@Override
public void addViewControllers(final ViewControllerRegistry registry) {
System.out.println("addViewControllers가 호출됩니다. ");
registry.addViewController("/").setViewName("index");// '/'라는 요청이 들어오면 index라는 뷰네임의 뷰를 출력해주세요
}
@Bean
public InternalResourceViewResolver getInternalResourceViewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix(".jsp");
return resolver;
}
} |
cs |
*DBConfig.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
39
40
41
42
43 |
package kr.or.connect.guestbook.config;
import javax.sql.DataSource;
import org.apache.commons.dbcp2.BasicDataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.transaction.annotation.TransactionManagementConfigurer;
@Configuration
@EnableTransactionManagement // 트랜잭션과 관련된 설정들을 자동으로 해준다.
public class DBConfig implements TransactionManagementConfigurer {
private String driverClassName = "com.mysql.jdbc.Driver";
private String url = "jdbc:mysql://localhost:3306/connectdb?useUnicode=true&characterEncoding=utf8";
private String username = "connectuser";
private String password = "connect123!@#";
@Bean
public DataSource dataSource() {
BasicDataSource dataSource = new BasicDataSource();
dataSource.setDriverClassName(driverClassName);
dataSource.setUrl(url);
dataSource.setUsername(username);
dataSource.setPassword(password);
return dataSource;
}
@Override
public PlatformTransactionManager annotationDrivenTransactionManager() {
return transactionManger();
}
@Bean
public PlatformTransactionManager transactionManger() {
return new DataSourceTransactionManager(dataSource());
}
} |
cs |
*ApplicationConfig.java
1
2
3
4
5
6
7
8
9
10
11
12 |
package kr.or.connect.guestbook.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
@Configuration
@ComponentScan(basePackages = { "kr.or.connect.guestbook.dao", "kr.or.connect.guestbook.service"})
@Import({ DBConfig.class })
public class ApplicationConfig {
} |
cs |
*web.xml
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 |
<?xml version="1.0" encoding="UTF-8"?>
<web-app>
<display-name>Spring JavaConfig Sample</display-name>
<context-param> <!-- <init-param>처럼 contextLoaderListener가 참고할 것들 기재-->
<param-name>contextClass</param-name>
<param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext
</param-value>
</context-param>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>kr.or.connect.guestbook.config.ApplicationConfig<!-- 우리가 만든 config파일 -->
</param-value>
</context-param>
<listener><!-- 어떤 특정한 이벤트가 일어 났을때 동작하는 것 -->
<listener-class>org.springframework.web.context.ContextLoaderListener <!-- Context가 로딩될 때(서버 실행 될 떄) 실행될 클래스-->
</listener-class>
</listener>
<servlet>
<servlet-name>mvc</servlet-name><!-- 2. 여기로 모든 요청 전달 -->
<servlet-class>org.springframework.web.servlet.DispatcherServlet <!-- DispatcherServlet을 프론트 서블릿으로 등록 -->
</servlet-class>
<init-param> <!-- DispatcherServlet이 실행 될 때 참고할 것들 기재하는 태그 -->
<param-name>contextClass</param-name>
<param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext
</param-value>
</init-param>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>kr.or.connect.guestbook.config.WebMvcContextConfiguration
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>mvc</servlet-name>
<url-pattern>/</url-pattern><!-- 1.모든 요청을 받으면 mvc(DispatcherServlet)로 보낸다. -->
</servlet-mapping>
<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>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern> <!-- 필터 적용 범위 - /*: 전체 -->
</filter-mapping>
</web-app> |
cs |
*index.jsp
1
2
3
4
5 |
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
response.sendRedirect("list");
%> |
cs |
============================================================================================================
Repository Layer 구현하기
데이터 베이스 테이블 만들기
*guestbook Table
1 |
CREATE TABLE guestbook(id bigint(20) unsigned NOT NULL AUTO_INCREMENT, name varchar(255) NOT NULL, content text, regdate datetime, PRIMARY KEY (id)); |
cs |
*log Table
1 |
CREATE TABLE log(id bigint(20) unsigned NOT NULL AUTO_INCREMENT, ip varchar(255) NOT NULL, method varchar(10) NOT NULL, regdate datetime, PRIMARY KEY (id)); |
cs |
DTO 생성
*Guestbook.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 |
package kr.or.connect.guestbook.dto;
import java.util.Date;
public class Guestbook {
private Long id;
private String name;
private String content;
private Date regdate;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public Date getRegdate() {
return regdate;
}
public void setRegdate(Date regdate) {
this.regdate = regdate;
}
@Override
public String toString() {
return "Guestbook [id=" + id + ", name=" + name + ", content=" + content + ", regdate=" + regdate + "]";
}
} |
cs |
*Log.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
39 |
package kr.or.connect.guestbook.dto;
import java.util.Date;
public class Log {
private Long id;
private String ip;
private String method;
private Date regdate;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getIp() {
return ip;
}
public void setIp(String ip) {
this.ip = ip;
}
public String getMethod() {
return method;
}
public void setMethod(String method) {
this.method = method;
}
public Date getRegdate() {
return regdate;
}
public void setRegdate(Date regdate) {
this.regdate = regdate;
}
@Override
public String toString() {
return "Log [id=" + id + ", ip=" + ip + ", method=" + method + ", regdate=" + regdate + "]";
}
} |
cs |
DAO 생성
*LogDao..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 |
package kr.or.connect.guestbook.dao;
import javax.sql.DataSource;
import org.springframework.jdbc.core.namedparam.BeanPropertySqlParameterSource;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.jdbc.core.namedparam.SqlParameterSource;
import org.springframework.jdbc.core.simple.SimpleJdbcInsert;
import org.springframework.stereotype.Repository;
import kr.or.connect.guestbook.dto.Log;
@Repository
public class LogDao {
private NamedParameterJdbcTemplate jdbc;
private SimpleJdbcInsert insertAction;
public LogDao(DataSource dataSource) {
this.jdbc = new NamedParameterJdbcTemplate(dataSource);
this.insertAction = new SimpleJdbcInsert(dataSource)
.withTableName("log")
.usingGeneratedKeyColumns("id"); // id가 자동으로 입력되는 부분
}
public Long insert(Log log) {
SqlParameterSource params = new BeanPropertySqlParameterSource(log);
return insertAction.executeAndReturnKey(params).longValue(); //insert문을 내부적으로 생성하고 자동으로 생성된 id 값을 리턴
}
}
= |
cs |
*GuestbookDaoSqls.java
1
2
3
4
5
6
7
8 |
package kr.or.connect.guestbook.dao;
public class GuestbookDaoSqls {
// mysql query 중에 limit를 이용하면 시작값, 끝날 떄의 값을 설정해서 특정한 부분만 SELECT 해온다.
public static final String SELECT_PAGING = "SELECT id, name, content, regdate FROM guestbook ORDER BY id DESC limit :start, :limit";
public static final String DELETE_BY_ID = "DELETE FROM guestbook WHERE id = :id";
public static final String SELECT_COUNT = "SELECT count(*) FROM guestbook";
} |
cs |
*GuestbookDao.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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55 |
package kr.or.connect.guestbook.dao;
import static kr.or.connect.guestbook.dao.GuestbookDaoSqls.*;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.sql.DataSource;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.namedparam.BeanPropertySqlParameterSource;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.jdbc.core.namedparam.SqlParameterSource;
import org.springframework.jdbc.core.simple.SimpleJdbcInsert;
import org.springframework.stereotype.Repository;
import kr.or.connect.guestbook.dto.Guestbook;
@Repository
public class GuestbookDao {
private NamedParameterJdbcTemplate jdbc;
private SimpleJdbcInsert insertAction;
private RowMapper<Guestbook> rowMapper = BeanPropertyRowMapper.newInstance(Guestbook.class);
public GuestbookDao(DataSource dataSource) {
this.jdbc = new NamedParameterJdbcTemplate(dataSource);
this.insertAction = new SimpleJdbcInsert(dataSource)
.withTableName("guestbook")
.usingGeneratedKeyColumns("id");
}
public List<Guestbook> selectAll(Integer start, Integer limit) {
Map<String, Integer> params = new HashMap<>();
params.put("start", start);
params.put("limit", limit);
return jdbc.query(SELECT_PAGING, params, rowMapper);
}
public Long insert(Guestbook guestbook) {
SqlParameterSource params = new BeanPropertySqlParameterSource(guestbook);
return insertAction.executeAndReturnKey(params).longValue();
}
public int deleteById(Long id) {
Map<String, ?> params = Collections.singletonMap("id", id);
return jdbc.update(DELETE_BY_ID, params);
}
public int selectCount() {
return jdbc.queryForObject(SELECT_COUNT, Collections.emptyMap(), Integer.class);
}
} |
cs |
*GuestbookTest.java
- 참고로 테스트는 Junit과 같은 단위테스트를 이용하는 것이 바람직하나, 시간관계상 클래스를 만들어 main() 메서드 안에서 Guestbook, Log 테스트를 진행하였다.
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 |
package kr.or.connect.guestbook.dao;
import java.util.Date;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import kr.or.connect.guestbook.config.ApplicationConfig;
import kr.or.connect.guestbook.dto.Log;
public class GuestbookDaoTest {
public static void main(String[] atgs) {
ApplicationContext ac = new AnnotationConfigApplicationContext(ApplicationConfig.class);
/*
//guestbook 테스트
GuestbookDao guestbookDao = ac.getBean(GuestbookDao.class);
Guestbook guestbook = new Guestbook();
guestbook.setName("Kwon");
guestbook.setContent("Hello~~");
guestbook.setRegdate(new Date());
Long id = guestbookDao.insert(guestbook);
System.out.println("id : " + id);*/
LogDao logDao = ac.getBean(LogDao.class);
Log log = new Log();
log.setIp("127.0.0.1");
log.setMethod("insert");
log.setRegdate(new Date());
logDao.insert(log);
}
}
|
cs |
=====================================================================================
Service Layer 구현
*GuestbookService.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 |
package kr.or.connect.guestbook.service;
import java.util.List;
import kr.or.connect.guestbook.dto.Guestbook;
//어떤 비즈니스로직이 있을지 생각해본다.
public interface GuestbookService {
//필요한 서비스들 선언
//아래 선언한 것들을 ...impl 패키지에 구현하면 된다.
public static final Integer LIMIT = 5;
public List<Guestbook> getGuestbooks(Integer start);
public int deleteGuestbook(Long id, String ip);
public Guestbook addGuestbook(Guestbook guestbook, String ip);
public int getCount();
} |
cs |
*GuestbookServiceImpl.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
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 |
package kr.or.connect.guestbook.service.impl;
import java.util.Date;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import kr.or.connect.guestbook.dao.GuestbookDao;
import kr.or.connect.guestbook.dao.LogDao;
import kr.or.connect.guestbook.dto.Guestbook;
import kr.or.connect.guestbook.dto.Log;
import kr.or.connect.guestbook.service.GuestbookService;
@Service
public class GuestbookServiceImpl implements GuestbookService {
@Autowired // 알아서 생성해서 주입해준다.
GuestbookDao guestbookDao;
@Autowired
LogDao logDao;
@Override
@Transactional//읽기만 하는 메서드에 이 어노테이션을 넣어주면 좋다. readOnly라는 형태로 connection을 사용하게 됨
public List<Guestbook> getGuestbooks(Integer start) {
List<Guestbook> list = guestbookDao.selectAll(start, GuestbookService.LIMIT);//selectAll(시작지점, 끝지점(GuestbookService에서 상수로 지정해놓음))
return list;
}
@Override
@Transactional(readOnly = false) //이 로직은 readOnly로 수행되면 안됨. 그래서 false로 지정
public int deleteGuestbook(Long id, String ip) {
int deleteCount = guestbookDao.deleteById(id); //삭제 성공하면 1 리턴하게됨
Log log = new Log(); //삭제 로그 남기기
log.setIp(ip);
log.setMethod("delete");
log.setRegdate(new Date());
logDao.insert(log);
return deleteCount;
}
@Override
@Transactional(readOnly = false) //이 로직은 readOnly로 수행되면 안됨. 그래서 false로 지정
public Guestbook addGuestbook(Guestbook guestbook, String ip) {
guestbook.setRegdate(new Date());
Long id = guestbookDao.insert(guestbook);
guestbook.setId(id);
// if(1 == 1)
// throw new RuntimeException("test exception"); // 여기서 부터 오류가 발생하면, 위에 guestbook 넣는 과정은 취소되게 된다.(트랜잭션, 원자성)
//
Log log = new Log();
log.setIp(ip);
log.setMethod("insert");
log.setRegdate(new Date());
logDao.insert(log);
return guestbook;
}
@Override
public int getCount() {
return guestbookDao.selectCount();
}
}
|
cs |
*GuestbookServiceTest.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 |
package kr.or.connect.guestbook.service.impl;
import java.util.Date;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import kr.or.connect.guestbook.config.ApplicationConfig;
import kr.or.connect.guestbook.dto.Guestbook;
import kr.or.connect.guestbook.service.GuestbookService;
public class GuestbookServiceTest {
public static void main(String[] args) {
ApplicationContext ac = new AnnotationConfigApplicationContext(ApplicationConfig.class);
GuestbookService guestbookService = ac.getBean(GuestbookService.class);
Guestbook guestbook = new Guestbook();
guestbook.setName("kang kyungmi22");
guestbook.setContent("Hello hello heeeeelo^^22");
guestbook.setRegdate(new Date());
Guestbook result = guestbookService.addGuestbook(guestbook, "127.0.0.1");
System.out.println(result);
}
} |
cs |
컨트롤러, jsp 작성하기
*GuestbookController.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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59 |
package kr.or.connect.guestbook.controller;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import kr.or.connect.guestbook.dto.Guestbook;
import kr.or.connect.guestbook.service.GuestbookService;
@Controller
public class GuestbookController {
@Autowired //Service 가져오기
GuestbookService guestbookService;
@GetMapping(path = "/list")
public String list(@RequestParam(name = "start", required = false, defaultValue = "0") int start, ModelMap model) {
// start로 시작하는 방명록 목록 구하기
List<Guestbook> list = guestbookService.getGuestbooks(start);
// 전체 페이지수 구하기
int count = guestbookService.getCount();
int pageCount = count / GuestbookService.LIMIT;
if (count % GuestbookService.LIMIT > 0)
pageCount++;
// 페이지 수만큼 start의 값을 리스트로 저장
// 예를 들면 페이지수가 3이면
// 0, 5, 10 이렇게 저장된다.
// list?start=0 , list?start=5, list?start=10 으로 링크가 걸린다.
List<Integer> pageStartList = new ArrayList<>();
for (int i = 0; i < pageCount; i++) {
pageStartList.add(i * GuestbookService.LIMIT);
}
model.addAttribute("list", list);
model.addAttribute("count", count);
model.addAttribute("pageStartList", pageStartList);
return "list";
}
@PostMapping(path = "/write")
public String write(@ModelAttribute Guestbook guestbook, HttpServletRequest request) {
String clientIp = request.getRemoteAddr();
System.out.println("clientIp : " + clientIp);
guestbookService.addGuestbook(guestbook, clientIp);
return "redirect:list";
}
} |
cs |
*list.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
37
38
39 |
<%@ 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>방명록 목록</title>
</head>
<body>
<h1>방명록</h1>
<br> 방명록 전체 수 : ${count }
<br>
<br>
<c:forEach items="${list}" var="guestbook">
${guestbook.id }<br>
${guestbook.name }<br>
${guestbook.content }<br>
${guestbook.regdate }<br>
</c:forEach>
<br>
<c:forEach items="${pageStartList}" var="pageIndex" varStatus="status">
<a href="list?start=${pageIndex}">${status.index +1 }</a>
</c:forEach>
<br>
<br>
<form method="post" action="write">
name : <input type="text" name="name"><br>
<textarea name="content" cols="60" rows="6"></textarea>
<br> <input type="submit" value="등록">
</form>
</body>
</html> |
cs |
참고 사이트 : http://www.edwith.org/
※
본 게시물은 개인적인 용도로 작성된 게시물입니다. 이후 포트폴리오로 사용될 정리 자료이니 불펌과 무단도용은 하지 말아주시고 개인 공부 목적으로만 이용해주시기 바랍니다.
※
'웹 > 부스트코스' 카테고리의 다른 글
[WEB]쿠키란?,쿠키를 이용한 상태정보 유지하기 (2) | 2018.09.03 |
---|---|
[WEB]상태정보 (0) | 2018.09.03 |
[WEB] 레이어드 아키텍쳐(Layerd Architecture) (0) | 2018.08.04 |
[Spring]Spring MVC를 이용한 웹 페이지 작성 실습 (0) | 2018.08.03 |
[Spring]Spring MVC (0) | 2018.08.02 |
- Total
- Today
- Yesterday
- 파이썬 while
- 파이썬 연산자
- 자바스크립트 그래프
- 파이썬 단계적 개선
- 파이썬 선택문
- 명품 c++ 실습
- 자바스크립트 자료구조
- 버츄어박스
- 파이썬 예제
- css 박스
- 백준 10451
- 파이썬 문자열
- 파이썬 if문
- 백준 1874
- 파이썬 터틀
- 파이썬 객체
- 자료구조
- 파이썬 for
- 자바
- 파이썬 리스트
- 파이썬
- 자바 에센셜 실습문제
- 웹
- 파이썬 함수
- css 그리드
- 파이썬 진수 변환
- 백준
- css
- 백준 11501
- 파이썬 클래스
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |