Spring CURD 게시판(소스코드만 정리)

부트캠프(END)/-Spring|2022. 8. 31. 16:48

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://java.sun.com/xml/ns/javaee https://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

  <!-- The definition of the Root Spring Container shared by all Servlets and Filters -->
  <servlet>
    <servlet-name>appServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <!-- XML사용시 환경설정 파일을 읽어오는 부분. WebApplicationContext 가 번역해 줄 것 -->
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>/WEB-INF/config/application-*.xml</param-value>
    </init-param>
  </servlet>
    
  <servlet-mapping>
    <servlet-name>appServlet</servlet-name>
    <url-pattern>*.do</url-pattern>
  </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>

BoardVO.java

package doo.doo.dao;
import java.util.*;

import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
public class BoardVO {
  private int no, hit;
  private String name, subject, content, pwd, dbday;
  private Date regdate;
}

BoardMapper.java (Interface)

package doo.doo.mapper;

import java.util.*;
import doo.doo.dao.BoardVO;

import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.SelectKey;
import org.apache.ibatis.annotations.Update;

public interface BoardMapper {
  //목록 출력
  @Select("SELECT no, subject, name, TO_CHAR(regdate,'YYYY-MM-DD') as dbday,hit, num " +
    "FROM (SELECT no, subject, name, regdate, hit, rownum as num " +
    "FROM (SELECT no, subject, name, regdate, hit " +
    "FROM spring_board ORDER BY no DESC)) " +
    "WHERE num BETWEEN #{start} AND #{end}")
  public List < BoardVO > boardListData(Map map);

  //총 페이지
  @Select("SELECT CEIL(COUNT(*)/10.0) FROM spring_board")
  public int boardTotalPage();

  //상세보기
  @Select("SELECT no,name,subject,content,TO_CHAR(regdate,'YYYY-MM-DD') as dbday, hit " +
    "FROM spring_board WHERE no=#{no}")
  public BoardVO boardDetailData(int no);

  //게시물 추가
  //시퀀스 자동증가번호. 얘를 먼저 수행하고 결과값을 int로 달라는 뜻임
  @SelectKey(keyProperty = "no", resultType = int.class, before = true,
    statement = "SELECT NVL(MAX(no)+1,1) as no FROM spring_board")
  @Insert("INSERT INTO spring_board VALUES(" +
    "#{no},#{name},#{subject},#{content},#{pwd},SYSDATE,0)")
  public void boardInsert(BoardVO vo);

  //게시물 삭제
  @Delete("DELETE FROM spring_board WHERE no=#{no}")
  public void boardDelete(BoardVO vo);

  //게시물 수정 - 비밀번호 검색
  @Select("SELECT pwd FROM spring_board " +
    "WHERE no=#{no}")
  public String boardGetPwd(int no);
  //게시글 수정 - 수정처리
  @Update("UPDATE spring_board SET " +
    "name=#{name}, subject=#{subject}, content=#{content} " +
    "WHERE no=#{no}")
  public void boardUpdate(BoardVO vo);

  //조회수 증가
  @Update("UPDATE spring_board SET " +
    "hit=hit+1 WHERE no=#{no}")
  public void boardHitIncrement(int no);

  //게시물 찾기(복잡한 쿼리는 XMl로 처리)
  public List < BoardVO > boardFindData(Map map);

  /* 아님 이렇게해야됨
   * @Select("<script>"
   		+ "SELECT no, subject, name, TO_CHAR(regdate, 'YYYY-MM-DD') as dbday\r\n" + 
   		"    FROM spring_board\r\n" + 
   		"    WHERE \r\n" + 
   		"    <trim prefix=\"(\" suffix=\")\" prefixOverrides=\"OR\">\r\n" + 
   		"      <foreach collection=\"fsArr\" item=\"fd\">\r\n" + 
   		"        <trim prefix=\"OR\">\r\n" + 
   		"          <choose>\r\n" + 
   		"            <when test=\"fd=='N'.toString()\">\r\n" + 
   		"              name LIKE '%'||#{ss}||'%'\r\n" + 
   		"            </when>\r\n" + 
   		"            <when test=\"fd=='S'.toString()\">\r\n" + 
   		"              subject LIKE '%'||#{ss}||'%'\r\n" + 
   		"            </when>\r\n" + 
   		"            <when test=\"fd=='C'.toString()\">\r\n" + 
   		"              content LIKE '%'||#{ss}||'%'\r\n" + 
   		"            </when>\r\n" + 
   		"          </choose>\r\n" + 
   		"        </trim>\r\n" + 
   		"      </foreach>\r\n" + 
   		"    </trim>" +
   		+"</script>")
   */

}

board-mapper.xml

<?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="doo.doo.mapper.BoardMapper">
  <select id="boardFindData" resultType="BoardVO" parameterType="hashmap">
    SELECT no, subject, name, TO_CHAR(regdate, 'YYYY-MM-DD') as dbday
    FROM spring_board
    WHERE 
    <trim prefix="(" suffix=")" prefixOverrides="OR">
      <foreach collection="fsArr" item="fd">
        <trim prefix="OR">
          <choose>
            <when test="fd=='N'.toString()">
              name LIKE '%'||#{ss}||'%'
            </when>
            <when test="fd=='S'.toString()">
              subject LIKE '%'||#{ss}||'%'
            </when>
            <when test="fd=='C'.toString()">
              content LIKE '%'||#{ss}||'%'
            </when>
          </choose>
        </trim>
      </foreach>
    </trim>
  </select>
</mapper>

 

BoardDAO.java

package doo.doo.dao;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import java.util.*;
import doo.doo.mapper.BoardMapper;

@Repository
public class BoardDAO {
  //인터페이스를 구현한 클래스의 주소값을 스프링에 요청
  @Autowired
  private BoardMapper mapper;
  //글목록 불러오기
  public List < BoardVO > boardListData(Map map) {
    return mapper.boardListData(map);
  }
  //글 전체 페이지수 불러오기
  public int boardTotalPage() {
    return mapper.boardTotalPage();
  }
  //글쓰기
  public void boardInsert(BoardVO vo) {
    mapper.boardInsert(vo);
  }

  //상세보기
  public BoardVO boardDetailData(int no) {
    mapper.boardHitIncrement(no); //조회수 증가
    return mapper.boardDetailData(no);
  }

  //글 삭제하기 화면
  public BoardVO boardDeleteData(int no) {
    return mapper.boardDetailData(no);
  }
  //글 삭제하기
  public boolean boardDelete(BoardVO vo) {
    boolean bCheck = false;
    String db_pwd = mapper.boardGetPwd(vo.getNo());
    if (db_pwd.equals(vo.getPwd())) {
      bCheck = true;
      mapper.boardDelete(vo);
    } else {
      bCheck = false;
    }
    return bCheck;
  }

  //글 수정하기 화면
  public BoardVO boardUpdateData(int no) {
    return mapper.boardDetailData(no);
  }
  //글 수정하기-비밀번호 체크
  public String boardGetPwd(int no) {
    return mapper.boardGetPwd(no);
  }
  //글 수정하기 처리
  public boolean boardUpdate(BoardVO vo) {
    boolean bCheck = false;
    String db_pwd = mapper.boardGetPwd(vo.getNo());
    if (db_pwd.equals(vo.getPwd())) {
      bCheck = true;
      mapper.boardUpdate(vo);
    } else {
      bCheck = false;
    }
    return bCheck;
  }

  //글 찾기
  public List < BoardVO > boardFindData(Map map) {
    return mapper.boardFindData(map);
  }
}

 

BoardController.java

package doo.doo.web;

import org.springframework.beans.factory.annotation.Autowired;
//request에 값을 담아 JSP로 전송할것임
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;

import java.util.*;
import doo.doo.dao.*;
@Controller
public class BoardController {
  @Autowired
  private BoardDAO dao;

  //목록
  @GetMapping("board/list.do")
  public String board_list(String page, Model model) {
    //null값으로 들어올 수 있는 부분은 String으로 받아야 한다.
    if (page == null)
      page = "1";
    int curPage = Integer.parseInt(page);
    Map map = new HashMap();
    map.put("start", ((curPage * 10) - 9));
    map.put("end", curPage * 10);
    List < BoardVO > list = dao.boardListData(map);
    int totalPage = dao.boardTotalPage();

    model.addAttribute("curPage", curPage);
    model.addAttribute("totalPage", totalPage);
    model.addAttribute("list", list);

    return "board/list";
  }

  //게시글 추가 화면(입력 폼 출력)
  @GetMapping("board/insert.do")
  public String board_insert() {
    return "board/insert";
  }
  //게시글 추가 처리
  @PostMapping("board/insert_ok.do")
  public String board_insert_ok(BoardVO vo) {
    dao.boardInsert(vo); //vo == 커맨드 객체
    return "redirect:list.do";
  }

  //게시글 상세보기
  @GetMapping("board/detail.do")
  public String board_detail(int no, Model model) {
    BoardVO vo = dao.boardDetailData(no);
    model.addAttribute("vo", vo);
    return "board/detail";
  }

  //게시글 수정 화면
  @GetMapping("board/update.do")
  public String board_update(int no, Model model) {
    BoardVO vo = dao.boardUpdateData(no);
    model.addAttribute("vo", vo);
    return "board/update";
  }

  //게시글 검색
  @PostMapping("board/find.do")
  public String board_find(String[] fd, String ss, Model model) {
    //체크박스는 배열로 잡아 줘야 한다
    Map map = new HashMap();
    map.put("fsArr", fd);
    map.put("ss", ss);
    List < BoardVO > list = dao.boardFindData(map);
    model.addAttribute("list", list);
    return "board/find";
  }

  //게시글 삭제화면으로 이동
  @GetMapping("board/delete.do")
  public String board_delete(int no, Model model) {
    BoardVO vo = dao.boardDeleteData(no);
    model.addAttribute("vo", vo);
    return "board/delete";
  }
}


BoardRestController.java

package doo.doo.web;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;

import doo.doo.dao.*;

//JavaScript, 일반 문자열, JSON 데이터 전송에 사용됨. JSP 지정에 사용되지 않음.
@RestController
public class BoardRestController {
  @Autowired
  private BoardDAO dao;

  //HTML : text/html , JSON : text/plain
  @PostMapping(value = "board/update_ok.do", produces = "text/html;charset=UTF-8") //한글깨짐방지
  public String board_update_ok(BoardVO vo) {
    String result = "";
    boolean bCheck = dao.boardUpdate(vo);
    if (bCheck == true) {
      result = "<script> " +
        "location.href=\"detail.do?no=" + vo.getNo() + "\";" +
        "</script>";
    } else {
      result = "<script> " +
        "alert(\"비밀번호가 틀려요!!!\");" +
        "history.back();" +
        "</script>";
    }
    return result;
  }

  @PostMapping(value = "board/delete_ok.do", produces = "text/html;charset=UTF-8")
  public String board_delete_ok(BoardVO vo) {
    String result = "";
    boolean bCheck = dao.boardDelete(vo);
    if (bCheck == true) {
      result = "<script> " +
        "location.href=\"list.do" + "\";" +
        "</script>";
    } else {
      result = "<script> " +
        "alert(\"비밀번호가 틀려요!!!\");" +
        "history.back();" +
        "</script>";
    }
    return result;
  }
}

BoardAspect.java

package doo.doo.aop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class BoardAspect {
  //시점 -> 메서드를 적용하는 위치를 지정한다. == JoinPoint
  //어떤 메서드를 호출할 건지? == PointCut
  //JoinPoint + PointCut = Weaving
  @Before("execution(* doo.doo.web.*Controller.*(..))") //메서드에 진입할 때
  public void before(JoinPoint jp) {
    //ProceedingJoinPoint 는 around에서만 사용한다.
    //무슨 Controller로 끝나는 모든 클래스 안의 메서드에 해당함.
    String name = jp.getSignature().getName(); //메서드이름 가져옴
    System.out.println(name + "/진입...");
  }
  @After("execution(* doo.doo.web.*Controller.*(..))") //메서드의 finally 위치 == 사이트에서 공통으로 출력하는 부분
  public void after(JoinPoint jp) {
    String name = jp.getSignature().getName(); //메서드이름 가져옴
    System.out.println(name + "/정상적으로 수행 완료...");
  }
  @AfterReturning(value = "execution(* doo.doo.web.*Controller.*(..))",
    returning = "obj") //메서드가 정상수행완료되었을 때 return값을 받아서 처리한다.
  public void afterReturning(String obj) {
    System.out.println(obj + ".jsp으로 이동이 완료...");
  }
}

 

Config.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
  PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
  <typeAliases>
    <typeAlias type="doo.doo.dao.BoardVO" alias="BoardVO"/>
  </typeAliases>
  <mappers>
    <mapper resource="doo/doo/mapper/board-mapper.xml"/>
  </mappers>
</configuration>

 

더보기

BoardConfig.java

package doo.doo.config;
//XML을 다 없애버리겠다.

import javax.sql.DataSource;

import org.apache.commons.dbcp.BasicDataSource;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.core.io.ClassPathResource;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.view.InternalResourceViewResolver;

@Configuration
/*
	<aop:aspectj-autoproxy/>
	<context:component-scan base-package="doo.doo.*" />
	<mybatis-spring::scan base-package="doo.doo.mapper"/>
 */
@EnableAspectJAutoProxy //aop대신
@ComponentScan(basePackages = {
  "doo.doo.*"
}) //component-scan 대신
@MapperScan(basePackages = {
  "doo.doo.mapper"
})
public class BoardConfig implements WebMvcConfigurer {

  @Override
  public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
    //HandlerMapping, HandlerAdapter 세팅함
    configurer.enable();
  }

  /*
	<bean id="viewResolver"
 	 class="org.springframework.web.servlet.view.InternalResourceViewResolver"
	 p:prefix="/"
	 p:suffix=".jsp"
	/>
	 */
  @Bean("viewResolver")
  public ViewResolver viewResolver() {
    InternalResourceViewResolver ir = new InternalResourceViewResolver();
    ir.setPrefix("/");
    ir.setSuffix(".jsp");
    return ir;
  }
  /*
   * <bean id="ds" 
  	class="org.apache.commons.dbcp.BasicDataSource"
  	p:driverClassName="oracle.jdbc.driver.OracleDriver"
  	p:url="jdbc:oracle:thin:@localhost:1521:XE"
  	p:username="hr"
  	p:password="happy"
  />
   */
  @Bean("ds")
  public DataSource dataSource() {
    BasicDataSource ds = new BasicDataSource();
    ds.setDriverClassName("oracle.jdbc.driver.OracleDriver");
    ds.setUrl("jdbc:oracle:thin:@localhost:1521:XE");
    ds.setUsername("hr");
    ds.setPassword("happy");
    return ds;
  }
  /*
   * <!-- MyBatis 설정 -->
  	<bean id="ssf"
  	class="org.mybatis.spring.SqlSessionFactoryBean"
  	p:dataSource-ref="ds"
  	p:configLocation="/WEB-INF/config/Config.xml"/>
   */
  @Bean("ssf")
  public SqlSessionFactory sqlSessionFactory() throws Exception {
    SqlSessionFactoryBean ssf = new SqlSessionFactoryBean();
    ssf.setDataSource(dataSource());
    ssf.setConfigLocation(new ClassPathResource("Config.xml"));
    return ssf.getObject();
  }
}

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://java.sun.com/xml/ns/javaee https://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

  <!-- The definition of the Root Spring Container shared by all Servlets and Filters -->
  <servlet>
    <servlet-name>appServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <!-- XML사용시 환경설정 파일을 읽어오는 부분. 지금은 자바로 할거니까 필요 없다.
    WebApplicationContext 가 번역해 줄 것
      <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/config/application-*.xml</param-value>
      </init-param>
     -->
     <!-- 환경 설정이 자바로 되어 있을 경우 아래처럼 진행한다.
     얘는 AnnotationConfigWebApplicationContext가 번역해줄 것임.(길어)-->
    <init-param>
      <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>doo.doo.config.BoardConfig</param-value>
    </init-param>
  </servlet>
    
  <servlet-mapping>
    <servlet-name>appServlet</servlet-name>
    <url-pattern>*.do</url-pattern>
  </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>

 

 

'부트캠프(END) > -Spring' 카테고리의 다른 글

Spring : session과 cookie (최근 본 상품, 장바구니)  (0) 2022.09.01
Spring Web 기초  (0) 2022.08.29
Spring 기초 : AOP  (0) 2022.08.25

댓글()