티스토리 뷰

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(20unsigned NOT NULL AUTO_INCREMENT, name varchar(255NOT NULL, content text, regdate datetimePRIMARY KEY (id));
cs

 

*log Table

1
CREATE TABLE log(id bigint(20unsigned NOT NULL AUTO_INCREMENT, ip varchar(255NOT NULL, method varchar(10NOT NULL, regdate datetimePRIMARY 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>&nbsp; &nbsp;
</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/



본 게시물은 개인적인 용도로 작성된 게시물입니다. 이후 포트폴리오로 사용될 정리 자료이니 불펌과 무단도용은 하지 말아주시고 개인 공부 목적으로만 이용해주시기 바랍니다.

댓글