냥쟝
반응형

스프링은 설정이 너무 빡세다.. crud는 서블릿이나 스프링이랑 별다르지 않지만..

프레임워크는 잘익혀두는것이 중요하다

 

 

 

0.1. Model 객체란

  • Model 객체는 Controller 에서 생성된 데이터를 담아 View 로 전달할 때 사용하는 객체.
  • Model 객체는 스프링이 제공하는 모델을 사용하는 것이므로 따로 반환을 해주지 않아도 된다.
  • 생명주기: ModelAndViewContainer가 생성될 때 함께 만들어진다. Model은 Map이라고 보면 된다.
  • 이미 만들어져있는 model을 가져와서 컨트롤러의 파라미터에 전달해주기 때문에 런타임에서는 model 객체를 사용하게 됩니다.

Model 객체 : 속성 값을 담아두는 객체ModelAndView 객체 : 속성 값 뿐만 아니라 View 이름도 담아둘 수 있는 객체

0.1.1. 사용방법

addAttribute("key", "value") 메서드를 이용해 view에 전달할 데이터를 key, value형식으로 전달할 수 있다.

addAttribute는 Map의 put과 같은 기능과 같아서 이를 통해 해당 모델에 원하는 속성과 그것에 대한 값을 주어 전달할 뷰에 데이터를 전달할 수 있습니다.

Spring에서 Controller의 메서드를 작성할 때는 특별하게 Model이라는 타입을 파라미터로 지정할 수 있습니다.

0.1.2. 사용 예시

<code />
@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에 데이터를 전달 했습니다.

<code />
<%@ 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가 출력되었습니다.

0.2. @ModelAttribute

요청 파라미터를 받아서 필요한 객체를 만들고 그 객체에 값을 넣어주어야 한다.

보통 @RequestParam을 사용해서 값을 받고, set을 사용해서 값을 넣어주곤 하지만 이 과정을 자동화시켜주는 것이 @ModelAttribute이다.

@ModelAttribute를 사용하지 않을 때 (model도 같이 사용해보기)

<code />
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 사용

<code />
public void modelAttributeEx(@ModelAttribute Item item, Model model){ model.addAttribute("item", item); }

이렇게 간결하게 사용 가능하다.

@ModelAttribute가 실행되는 원리를 설명하자면 요청 파라미터의 이름으로 Item 객체의 프로퍼티를 찾는다.

그리고 해당 프로퍼티의 setter를 호출해서 파라미터 값을 입력한다.

하지만 저기에서 model.addAttribute도 생략 가능하다. @ModelAttribute를 사용함으로써 model에도 자동적으로 객체가 추가 되기 때문이다.

@ModelAttribute 어노테이션도 생략가능하다.

<code />
public void ModelAttributeEx(Item item, Model model){}

최종적으로 위와 같이 쓸 수 있다.

<code />
// 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")으로 하여 자동으로 모델에 담긴다.

0.2.1. @ModelAttribute

@ModelAttribute는 HTTP 요청의 파라미터를 객체로 바인딩하기 위해 사용된다.

컨트롤러 메서드의 파라미터 앞에 @ModelAttribute를 사용하여 해당 파라미터를 객체로 변환하고, 이를 컨트롤러 메서드 내에서 사용할 수 있다.

또한, 이 어노테이션을 사용하면 해당 객체를 자동으로 뷰로 전달된다.

주로 HTML 폼 데이터를 처리할 때 사용된다.

객체 클래스에 @Setter 어노테이션이나 Setter가 필요하다.

예시

<code />
@PostMapping("/user") public String createUser(@ModelAttribute User user) { // user 객체를 사용하여 사용자 생성 로직 수행return "userCreated";// 뷰 이름 반환 }

0.2.2. @RequestBody

@RequestBody는 HTTP 요청의 본문(body)에 담긴 데이터를 객체로 바인딩하기 위해 사용된다.

컨트롤러 메서드의 파라미터 앞에 @RequestBody를 사용하여 해당 파라미터를 요청 본문의 데이터를 변환하여 객체로 받아올 수 있다.

주로 JSON, XML, 또는 기타 데이터 형식의 요청을 처리할 때 사용된다.

예시

<code />
@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. 1. @RequestParam

1개의 HTT 요청 파라미터를 받기 위해서 사용한다.

1.0.1. 예제

<code />
@GetMapping("/api/foos") @ResponseBody public String getFoos(@RequestParam String id) { return "ID: " + id; }
  • @RequestParam을 이용해서 id 쿼리 매개변수를 추출한다.

1.0.2. 속성

1.0.3. 1. name

  • 위의 예제에서는 변수 이름과 매개변수 이름이 동일한데, 이를 다르게 설정할 수도 있다.
<code />
@PostMapping("/api/foos") @ResponseBody public String addFoo(@RequestParam(name = "id") String fooId, @RequestParam String name) { return "ID: " + fooId + " Name: " + name; }
  • 매개변수 앞에 @RequestParam(name = "id")를 추가해주면 된다.

1.0.4. 2. required & defaultValue

  • @RequestParam은 요청에 매개변수가 필수적이다. → @RequestParam(required = true)가 기본 설정이다.
    • 해당 파라미터가 전송되지 않으면 400 Error을 반환한다.
  • @RequestParam(required = false)로 설정하면 파라미터가 없어도 된다. → 이 경우 매개변수가 null로 바인딩된다.
  • defaultValue를 통해 기본값을 설정할 수도 있다.
<code />
@GetMapping("/api/foos") @ResponseBody public String getFoos(@RequestParam(required = false, defaultValue = "0") String id) { return "ID: " + id; }

2. 2. @RequestBody

클라이언트가 전송하는 Json(application/json) 형태의 HTTP Body 내용을 Java Object로 변환해준다.

  • 그렇기 때문에 Body가 존재하지 않는 Get 메소드에서 사용하면 에러가 발생한다.
  • HTTP 요청 본문 데이터는 Spring에서 제공하는 HttpMessageConverter를 통해 타입에 맞는 객체로 변환된다.
  • @RequestBody를 사용할 객체는 필드를 바인딩할 생성자나 setter 메서드가 필요 없다.

3. 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

<code />
<!-- 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 인터페이스 구현

 

 

<java />
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 />
```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> ```
<java />
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); }
<java />
<?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>
<java />
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); }
<java />
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; } }
<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); } }
<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); } }
<java />
```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); } } ```
<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>
<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> <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
profile

냥쟝

@냥쟝

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!