스프링은 설정이 너무 빡세다.. crud는 서블릿이나 스프링이랑 별다르지 않지만..
프레임워크는 잘익혀두는것이 중요하다
Model 객체란
- Model 객체는 Controller 에서 생성된 데이터를 담아 View 로 전달할 때 사용하는 객체.
- Model 객체는 스프링이 제공하는 모델을 사용하는 것이므로 따로 반환을 해주지 않아도 된다.
- 생명주기: ModelAndViewContainer가 생성될 때 함께 만들어진다. Model은 Map이라고 보면 된다.
- 이미 만들어져있는 model을 가져와서 컨트롤러의 파라미터에 전달해주기 때문에 런타임에서는 model 객체를 사용하게 됩니다.
Model 객체 : 속성 값을 담아두는 객체ModelAndView 객체 : 속성 값 뿐만 아니라 View 이름도 담아둘 수 있는 객체
사용방법
addAttribute("key", "value") 메서드를 이용해 view에 전달할 데이터를 key, value형식으로 전달할 수 있다.
addAttribute는 Map의 put과 같은 기능과 같아서 이를 통해 해당 모델에 원하는 속성과 그것에 대한 값을 주어 전달할 뷰에 데이터를 전달할 수 있습니다.
Spring에서 Controller의 메서드를 작성할 때는 특별하게 Model이라는 타입을 파라미터로 지정할 수 있습니다.
사용 예시
@Controller
public class TestController {
@GetMapping("/test")
public void testMethod(Model model) {
String test = "model interface";
model.addAttribute("test", test);
}
}
Controller이노테이션을 생성한후에 @GetMapping하여 url을 "/test/"로, 메서드에 매개변수를 Model 타입의 model변수를 선언했습니다.
String 타입의 변수 test를 선언하고, model.addAttribute를 통해 view에 데이터를 전달 했습니다.
<%@ page language="java" contentType="text/html; charset=EUC-KR"
pageEncoding="EUC-KR"%>
<!DOCTYPE html>
<html><head><meta charset="EUC-KR"><title>Insert title here</title></head><body><h1>Test</h1>
<h2>${test}</h2></body></html>
처음 Controller에 Model타입의 model의 변수 선언을 통해 ${test}부분의 test는 model.addAttribute("test", test)로 인해 치환되어 model interface가 출력되었습니다.
@ModelAttribute
요청 파라미터를 받아서 필요한 객체를 만들고 그 객체에 값을 넣어주어야 한다.
보통 @RequestParam을 사용해서 값을 받고, set을 사용해서 값을 넣어주곤 하지만 이 과정을 자동화시켜주는 것이 @ModelAttribute이다.
@ModelAttribute를 사용하지 않을 때 (model도 같이 사용해보기)
public void item(@RequestParam String name,
@RequestParam int price,
Model model){
Item item = new Item();
item.setName(name);
item.setPrice(price);
model.addAttribute("item", item);
}
이렇게 @RequestParam으로 일일이 받아서 set을 해줘야 값이 저장된다. 하지만 @ModelAttribute를 사용하면 간단해진다.
modelAttribute 사용
public void modelAttributeEx(@ModelAttribute Item item, Model model){
model.addAttribute("item", item);
}
이렇게 간결하게 사용 가능하다.
@ModelAttribute가 실행되는 원리를 설명하자면 요청 파라미터의 이름으로 Item 객체의 프로퍼티를 찾는다.
그리고 해당 프로퍼티의 setter를 호출해서 파라미터 값을 입력한다.
하지만 저기에서 model.addAttribute도 생략 가능하다. @ModelAttribute를 사용함으로써 model에도 자동적으로 객체가 추가 되기 때문이다.
@ModelAttribute 어노테이션도 생략가능하다.
public void ModelAttributeEx(Item item, Model model){}
최종적으로 위와 같이 쓸 수 있다.
// FormItemController - 추가
@ModelAttribute("regions")
public Map<String, String> regions() {
Map<String, String> regions = new LinkedHashMap<>();
regions.put("SEOUL", "서울");
regions.put("BUSAN", "부산");
regions.put("JEJU", "제주");
return regions;
}
@ModelAttribute의 특별한 사용법
등록 폼, 상세화면, 수정 폼에서 모두 서울, 부산, 제주라는 체크 박스를 반복해서 보여주어야 한다. 이렇게 하려면 각각의 컨트롤러에서 model.addAttribute(...) 을 사용해서 체크 박스를 구성하는 데이터를 반복해서 넣어주어야 한다.
@ModelAttribute 는 이렇게 컨트롤러에 있는 별도의 메서드에 적용할 수 있다.
이렇게하면 해당 컨트롤러를 요청할 때 regions 에서 반환한 값이 자동으로 모델( model )에 담기게 된다.
물론 이렇게 사용하지 않고, 각각의 컨트롤러 메서드에서 모델에 직접 데이터를 담아서 처리해도 된다
@ModelAttribute("regions") 가 있는 컨트롤러를 호출할때 이 표시가 붙은 메서드가 model.addAttribute()로 이름은 ""안에 있는 것("regions")으로 하여 자동으로 모델에 담긴다.
@ModelAttribute
@ModelAttribute는 HTTP 요청의 파라미터를 객체로 바인딩하기 위해 사용된다.
컨트롤러 메서드의 파라미터 앞에 @ModelAttribute를 사용하여 해당 파라미터를 객체로 변환하고, 이를 컨트롤러 메서드 내에서 사용할 수 있다.
또한, 이 어노테이션을 사용하면 해당 객체를 자동으로 뷰로 전달된다.
주로 HTML 폼 데이터를 처리할 때 사용된다.
객체 클래스에 @Setter 어노테이션이나 Setter가 필요하다.
예시
@PostMapping("/user")
public String createUser(@ModelAttribute User user) {
// user 객체를 사용하여 사용자 생성 로직 수행return "userCreated";// 뷰 이름 반환
}
@RequestBody
@RequestBody는 HTTP 요청의 본문(body)에 담긴 데이터를 객체로 바인딩하기 위해 사용된다.
컨트롤러 메서드의 파라미터 앞에 @RequestBody를 사용하여 해당 파라미터를 요청 본문의 데이터를 변환하여 객체로 받아올 수 있다.
주로 JSON, XML, 또는 기타 데이터 형식의 요청을 처리할 때 사용된다.
예시
@PostMapping("/user")
public String createUser(@RequestBody User user) {
// user 객체를 사용하여 사용자 생성 로직 수행return "userCreated";// 뷰 이름 반환
}
바인딩 종류 특징
@ModelAttribute | - 변환이 아닌 바인딩을 시키기 때문에 변수들의 Setter 함수가 없으면 저장되지 않는다.- @ModelAttribute를 사용하여 HTTP Body에 내용을 담기 위해서는 multipart/form-data 형식으로 전송해야 한다.- HTTP 파라미터들은 Setter를 통해 일대일 객체에 바인딩하기 위해 사용된다.- @ModelAttribute에는 매핑시키는 파라미터의 타입이 객체의 타입과 일치하는지를 포함한 다양한 검증(Validation) 작업이 추가적으로 진행된다. | |||
@RequestParam | - @RequestParam은 1개의 HTTP 요청 파라미터를 받기 위해서 사용된다. | |||
@RequestBody | - @RequestBody로 받은 데이터는 Spring에서 관리하는 MessageConverter들 중 하나인 MappingJackson2 HttpMessageConverter를 통해 Java 객체로 변환된다.- Spring은 메시지를 변환하는 과정에서 객체의 기본 생성자를 통해 객체를 생성하고 내부적으로 Reflection을 사용해 값을 할당하므로 @RequestBody에는 값을 주입하기 위한 생성자나 Setter가 필요 없다. |
1. @RequestParam
1개의 HTT 요청 파라미터를 받기 위해서 사용한다.
예제
@GetMapping("/api/foos")
@ResponseBody
public String getFoos(@RequestParam String id) {
return "ID: " + id;
}
- @RequestParam을 이용해서 id 쿼리 매개변수를 추출한다.
속성
1. name
- 위의 예제에서는 변수 이름과 매개변수 이름이 동일한데, 이를 다르게 설정할 수도 있다.
@PostMapping("/api/foos")
@ResponseBody
public String addFoo(@RequestParam(name = "id") String fooId, @RequestParam String name) {
return "ID: " + fooId + " Name: " + name;
}
- 매개변수 앞에 @RequestParam(name = "id")를 추가해주면 된다.
2. required & defaultValue
- @RequestParam은 요청에 매개변수가 필수적이다. → @RequestParam(required = true)가 기본 설정이다.
- 해당 파라미터가 전송되지 않으면 400 Error을 반환한다.
- @RequestParam(required = false)로 설정하면 파라미터가 없어도 된다. → 이 경우 매개변수가 null로 바인딩된다.
- defaultValue를 통해 기본값을 설정할 수도 있다.
@GetMapping("/api/foos")
@ResponseBody
public String getFoos(@RequestParam(required = false, defaultValue = "0") String id) {
return "ID: " + id;
}
2. @RequestBody
클라이언트가 전송하는 Json(application/json) 형태의 HTTP Body 내용을 Java Object로 변환해준다.
- 그렇기 때문에 Body가 존재하지 않는 Get 메소드에서 사용하면 에러가 발생한다.
- HTTP 요청 본문 데이터는 Spring에서 제공하는 HttpMessageConverter를 통해 타입에 맞는 객체로 변환된다.
- @RequestBody를 사용할 객체는 필드를 바인딩할 생성자나 setter 메서드가 필요 없다.
3. @ModelAttribute
클라이언트가 전송하는 multipart/form-data 형태의 HTTP Body 내용과 HTTP 파라미터 데이터를 Setter를 통해 Java 객체에 매핑한다.
- 객체의 필드에 접근해서 데이터를 바인딩할 수 있는 생성자 혹은 setter 메서드가 필요하다.
- Query String 및 Form 형식이 아닌 데이터는 처리할 수 없다.
📌 정리
- RequestParam
- 1개의 HTTP 파라미터를 얻기 위해 사용한다.
- 매개변수가 필수적으로 필요하다.
- 매개변수가 전달되지 않은 경우 400 에러가 발생한다.
- 설정을 통해 바꿀 수 있다.
- RequestBody
- Json으로 받은 HTTP Body 데이터를 HttpMessageConverter를 통해 변환한다.
- setter가 없어도 된다.
- ModelAttribute
- multipart/form-data 형태의 HTTP Body 내용과 HTTP 파라미터들을 Setter를 통해 1대 1로 객체에 바인딩시킨다.
- 매개변수의 바인딩을 받는 필드는 setter 함수가 있어야 한다.
터셉터 ( Interceptor )
Interceptor란 컨트롤러에 들어오는 요청 HttpRequest와 컨트롤러가 응답하는 HttpResponse를 가로채는 역할을 합니다.
인터셉터는 관리자만 접근할 수 있는 관리자 페이지에 접근하기 전에 관리자 인증을 하는 용도로 활용될 수 있습니다.
이번 주제에서는 컨트롤러에서 인터셉터를 활용하여 접근 권한을 해보고, 기술 침투적인 HttpSession을 제거하여 세션을 처리하려 합니다.
인터셉터는 Servlet의 앞, 뒤에서 HttpRequest, HttpResponse을 가로채는 Filter와 그 역할이 유사한데, Filter와 Interceptor는 분명히 다릅니다.
https://t1.daumcdn.net/cfile/tistory/992590395ABF406F18
Filter와 Interceptor의 차이
1. 호출 시점
Filter는 DispatcherServlet이 실행되기 전 , Interceptor는 DispatcherServlet이 실행된 후
2. 설정 위치
Filter는 web.xml , Interceptor는 spring-servlet.xml
3. 구현 방식
Filter는 web.xml에서 설정을 하면 구현이 가능하지만, Interceptor는 설정은 물론 메서드 구현이 필요합니다.
이 글에서는 인터셉터 환경 설정 및 기본적인 사용 방법과 인터셉터를 활용하여 로그인을 처리하는 예제를 구현하도록 하겠습니다.
환경 설정
spring-servlet.xml
<!-- Interceptors --><mvc:interceptors> <mvc:interceptor> <mvc:mapping path="/**"/> <bean class="com.victolee.interceptor.MyInterceptor"/> </mvc:interceptor></mvc:interceptors>
모든 요청을 가로채서( Interceptor ) com.victolee.interceptor 패키지에 있는 MyInterceptor 객체를 실행하겠다는 의미입니다.
테스트
Interceptor를 구현하는 방법은 2가지가 있는데, HandlerInterceptor 인터페이스를 구현하는 방법과 HandlerInterceptorAdapter 클래스를 상속 받는 방법이 있습니다.
HandlerInterceptor 인터페이스 구현
public class MyInterceptor implements HandlerInterceptor
{ // controller로 보내기 전에 처리하는 인터셉터 // 반환이 false라면 controller로 요청을 안함
// 매개변수 Object는 핸들러 정보를 의미한다. ( RequestMapping , DefaultServletHandler )
@Override public boolean preHandle( HttpServletRequest request, HttpServletResponse response,
Object obj) throws Exception { System.out.println("MyInterCeptor - preHandle"); return false; } // controller의 handler가 끝나면 처리됨 @Override public void postHandle( HttpServletRequest request, HttpServletResponse response, Object obj, ModelAndView mav) throws Exception { } // view까지 처리가 끝난 후에 처리됨 @Override public void afterCompletion( HttpServletRequest request, HttpServletResponse response, Object obj, Exception e) throws Exception { } }
```java
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<style>
body {
font-family: Arial, sans-serif;
margin: 20px;
}
h1 {
text-align: center;
}
table {
width: 100%;
border-collapse: collapse;
margin-top: 20px;
}
th, td {
border: 1px solid #ddd;
padding: 8px;
text-align: left;
}
th {
background-color: #f2f2f2;
}
tr:nth-child(even) {
background-color: #f2f2f2;
}
tr:hover {
background-color: #ddd;
}
</style>
</head>
<body>
<form method="post" action="/myboard/updateProcess">
<table border="1">
<thead>
<tr>
<th>번호</th>
<th>제목</th>
<th>작성자</th>
<th>내용</th>
<th>등록일자</th>
<th>수정일자</th>
</tr>
</thead>
<tbody>
<c:forEach items="${myBoarddetail}" var="result">
<tr>
<td>
<input type="hidden" name="atclSn" value="${result.atclSn}">
</td>
<td>
<input type="text" name="atclTitle" value="${result.atclTitle}">
</td>
<td>${result.regNm}</td>
<td>
<textarea name="atclCts" rows="4" cols="50">${result.atclCts}</textarea>
</td>
<td>${result.regDttm}</td>
<td>${result.modDttm}</td>
<td>
<button type="submit">수정</button>
</td>
</tr>
</c:forEach>
</tbody>
</table>
<a href="<c:url value='/myboard/list' />">목록으로 돌아가기</a>
</body>
</html>
```
package egovframework.edutrack.modules.myboard.service.impl;
import java.util.List;
import java.util.Map;
import org.apache.ibatis.annotations.Param;
import org.springframework.web.multipart.MultipartFile;
import egovframework.edutrack.modules.myboard.service.MyBoardVO;
import egovframework.rte.psl.dataaccess.mapper.Mapper;
@Mapper("myBoardMapper")
public interface MyBoardMapper {
public List<MyBoardVO> list(MyBoardVO vo);
public List<MyBoardVO> search(MyBoardVO myboardVO);
public void delete(String atclSn);
public void update(MyBoardVO myBoard);
public void create(MyBoardVO myBoard);
public List<MyBoardVO> getdetail(String atclSn);
}
<?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="egovframework.edutrack.modules.myboard.service.impl.MyBoardMapper">
<select id="list" parameterType="myBoardVO" resultType="myBoardVO">
SELECT ATCL_SN
, ATCL_TITLE
, REG_NM
, REG_DTTM
FROM tb_my_board
</select>
<select id="search" parameterType="myBoardVO" resultType="myBoardVO">
SELECT ATCL_SN, ATCL_TITLE, REG_NM, REG_DTTM
FROM tb_my_board
WHERE
<choose>
<when test="searchType == 'title'">
ATCL_TITLE LIKE '%' #{keyword} '%'
</when>
<when test="searchType == 'writer'">
REG_NM LIKE '%' #{keyword} '%'
</when>
<otherwise>
ATCL_TITLE LIKE '%' #{keyword} '%' OR REG_NM LIKE '%' #{keyword} '%'
</otherwise>
</choose>
ORDER BY ATCL_SN DESC
</select>
<insert id="create" parameterType="myBoardVO">
INSERT INTO tb_my_board (ATCL_SN, ATCL_TITLE, ATCL_CTS)
VALUES (#{atclSn}, #{atclTitle}, #{atclCts})
</insert>
<select id="getdetail" parameterType="String" resultType="myBoardVO">
SELECT ATCL_SN, ATCL_TITLE, ATCL_CTS, REG_NM, REG_DTTM, MOD_DTTM
FROM tb_my_board
WHERE ATCL_SN = #{atclSn}
</select>
<update id="update" parameterType="myBoardVO">
UPDATE tb_my_board
SET ATCL_TITLE = #{atclTitle},
ATCL_CTS = #{atclCts}
WHERE ATCL_SN = #{atclSn}
</update>
<delete id="delete" parameterType="String">
DELETE FROM tb_my_board
WHERE ATCL_SN = #{atclSn}
</delete>
</mapper>
package egovframework.edutrack.modules.myboard.service;
import java.util.List;
import org.springframework.web.multipart.MultipartFile;
public interface MyBoardService {
public List<MyBoardVO> list(MyBoardVO vo) throws Exception;
public void delete(String atclSn);
public void update(MyBoardVO myBoard);
public void create(MyBoardVO myBoard);
public List<MyBoardVO> search(MyBoardVO vo);
public List<MyBoardVO> getdetail(String atclSn);
}
package egovframework.edutrack.modules.myboard.service;
import egovframework.edutrack.comm.service.DefaultVO;
public class MyBoardVO extends DefaultVO {
private String atclSn;
private String atclTitle;
private String atclCts;
private String regNo;
private String regNm;
private String regDttm;
private String modNo;
private String modNm;
private String modDttm;
private String keyword;
public String getAtclSn() {
return atclSn;
}
public void setAtclSn(String atclSn) {
this.atclSn = atclSn;
}
public String getAtclTitle() {
return atclTitle;
}
public void setAtclTitle(String atclTitle) {
this.atclTitle = atclTitle;
}
public String getAtclCts() {
return atclCts;
}
public void setAtclCts(String atclCts) {
this.atclCts = atclCts;
}
public String getRegNo() {
return regNo;
}
public void setRegNo(String regNo) {
this.regNo = regNo;
}
public String getRegNm() {
return regNm;
}
public void setRegNm(String regNm) {
this.regNm = regNm;
}
public String getRegDttm() {
return regDttm;
}
public void setRegDttm(String regDttm) {
this.regDttm = regDttm;
}
public String getModNo() {
return modNo;
}
public void setModNo(String modNo) {
this.modNo = modNo;
}
public String getModNm() {
return modNm;
}
public void setModNm(String modNm) {
this.modNm = modNm;
}
public String getModDttm() {
return modDttm;
}
public void setModDttm(String modDttm) {
this.modDttm = modDttm;
}
public String getKeyword() {
return keyword;
}
public void setKeyword(String keyword) {
this.keyword = keyword;
}
}
package egovframework.edutrack.modules.myboard.service.impl;
import java.io.File;
import java.io.IOException;
import java.util.List;
import javax.annotation.Resource;
import javax.transaction.Transactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import egovframework.edutrack.modules.myboard.service.MyBoardService;
import egovframework.edutrack.modules.myboard.service.MyBoardVO;
import egovframework.rte.fdl.cmmn.EgovAbstractServiceImpl;
@Service("myBoardService")
public class MyBoardServiceImpl extends EgovAbstractServiceImpl implements MyBoardService {
@Resource(name="myBoardMapper")
private MyBoardMapper myBoardMapper;
@Override
public List<MyBoardVO> list(MyBoardVO vo) throws Exception {
return myBoardMapper.list(vo);
}
@Override
public void update(MyBoardVO myBoard) {
myBoardMapper.update(myBoard);
}
@Override
public void create(MyBoardVO myBoard) {
myBoardMapper.create(myBoard);
}
@Override
public List<MyBoardVO> getdetail(String atclSn) {
return myBoardMapper.getdetail(atclSn);
}
@Override
public void delete(String atclSn) {
myBoardMapper.delete(atclSn);
}
@Override
public List<MyBoardVO> search(MyBoardVO vo) {
return myBoardMapper.search(vo);
}
}
package egovframework.edutrack.modules.myboard.service.impl;
import java.io.File;
import java.io.IOException;
import java.util.List;
import javax.annotation.Resource;
import javax.transaction.Transactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import egovframework.edutrack.modules.myboard.service.MyBoardService;
import egovframework.edutrack.modules.myboard.service.MyBoardVO;
import egovframework.rte.fdl.cmmn.EgovAbstractServiceImpl;
@Service("myBoardService")
public class MyBoardServiceImpl extends EgovAbstractServiceImpl implements MyBoardService {
@Resource(name="myBoardMapper")
private MyBoardMapper myBoardMapper;
@Override
public List<MyBoardVO> list(MyBoardVO vo) throws Exception {
return myBoardMapper.list(vo);
}
@Override
public void update(MyBoardVO myBoard) {
myBoardMapper.update(myBoard);
}
@Override
public void create(MyBoardVO myBoard) {
myBoardMapper.create(myBoard);
}
@Override
public List<MyBoardVO> getdetail(String atclSn) {
return myBoardMapper.getdetail(atclSn);
}
@Override
public void delete(String atclSn) {
myBoardMapper.delete(atclSn);
}
@Override
public List<MyBoardVO> search(MyBoardVO vo) {
return myBoardMapper.search(vo);
}
}
```java
package egovframework.edutrack.modules.myboard.service.impl;
import java.io.File;
import java.io.IOException;
import java.util.List;
import javax.annotation.Resource;
import javax.transaction.Transactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import egovframework.edutrack.modules.myboard.service.MyBoardService;
import egovframework.edutrack.modules.myboard.service.MyBoardVO;
import egovframework.rte.fdl.cmmn.EgovAbstractServiceImpl;
@Service("myBoardService")
public class MyBoardServiceImpl extends EgovAbstractServiceImpl implements MyBoardService {
@Resource(name="myBoardMapper")
private MyBoardMapper myBoardMapper;
@Override
public List<MyBoardVO> list(MyBoardVO vo) throws Exception {
return myBoardMapper.list(vo);
}
@Override
public void update(MyBoardVO myBoard) {
myBoardMapper.update(myBoard);
}
@Override
public void create(MyBoardVO myBoard) {
myBoardMapper.create(myBoard);
}
@Override
public List<MyBoardVO> getdetail(String atclSn) {
return myBoardMapper.getdetail(atclSn);
}
@Override
public void delete(String atclSn) {
myBoardMapper.delete(atclSn);
}
@Override
public List<MyBoardVO> search(MyBoardVO vo) {
return myBoardMapper.search(vo);
}
}
```
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<style>
body {
font-family: Arial, sans-serif;
margin: 20px;
}
h1 {
text-align: center;
}
table {
width: 100%;
border-collapse: collapse;
margin-top: 20px;
}
th, td {
border: 1px solid #ddd;
padding: 8px;
text-align: left;
}
th {
background-color: #f2f2f2;
}
tr:nth-child(even) {
background-color: #f2f2f2;
}
tr:hover {
background-color: #ddd;
}
</style>
</head>
<body>
<form method="post" action="/myboard/updateProcess">
<table border="1">
<thead>
<tr>
<th>번호</th>
<th>제목</th>
<th>작성자</th>
<th>내용</th>
<th>등록일자</th>
<th>수정일자</th>
</tr>
</thead>
<tbody>
<c:forEach items="${myBoarddetail}" var="result">
<tr>
<td>
<input type="hidden" name="atclSn" value="${result.atclSn}">
</td>
<td>
<input type="text" name="atclTitle" value="${result.atclTitle}">
</td>
<td>${result.regNm}</td>
<td>
<textarea name="atclCts" rows="4" cols="50">${result.atclCts}</textarea>
</td>
<td>${result.regDttm}</td>
<td>${result.modDttm}</td>
<td>
<button type="submit">수정</button>
</td>
</tr>
</c:forEach>
</tbody>
</table>
<a href="<c:url value='/myboard/list' />">목록으로 돌아가기</a>
</body>
</html>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<style>
body {
font-family: Arial, sans-serif;
margin: 20px;
}
h1 {
text-align: center;
}
table {
width: 100%;
border-collapse: collapse;
margin-top: 20px;
}
th, td {
border: 1px solid #ddd;
padding: 8px;
text-align: left;
}
th {
background-color: #f2f2f2;
}
tr:nth-child(even) {
background-color: #f2f2f2;
}
tr:hover {
background-color: #ddd;
}
</style>
</head>
<form method="post" action="/myboard/createProcess">
<form method="post" action="/myboard/delete/{atclSn}">
<body>
<table border="1">
<thead>
<tr>
<th>번호</th>
<th>제목</th>
<th>작성자</th>
<th>내용</th>
<th>등록일자</th>
<th>수정일자</th>
<th>수정</th>
<th>삭제</th>
</tr>
</thead>
<tbody>
<c:forEach items="${myBoarddetail}" var="result">
<tr>
<td>${result.atclSn}</td>
<td>${result.atclTitle}</td>
<td>${result.regNm}</td>
<td>${result.atclCts}</td>
<td>${result.regDttm}</td>
<td>${result.modDttm}</td>
<td>
<a href="<c:url value='/myboard/edit/${result.atclSn}' />">수정</a>
</td>
<td>
<a href="<c:url value='/myboard/delete/${result.atclSn}' />">삭제</a>
</td>
</tr>
</c:forEach>
</tbody>
</table>
<a href="<c:url value='/myboard/list' />">목록으로 돌아가기</a>
</body>
</html>
'취준 note 2023 > spring' 카테고리의 다른 글
스프링 트랜젝션+pagenation (0) | 2023.08.12 |
---|---|
스프링AOP (0) | 2023.08.12 |
스프링 di (0) | 2023.08.12 |
스프링 시큐리티 (0) | 2023.08.11 |
spring master - chap2 스프링빈 의존성 주입(IOC) (0) | 2023.01.23 |