Spring CURD 게시판(소스코드만 정리)
부트캠프(END)/-Spring2022. 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 |
댓글()