[Spring] Validations with Spring Boot Starter
Java Web Application with Spring and Hibernate (5)
/ @Size / @Valid / BindingResult / Validations
유효성 검사
- 현재 그냥 아무것도 없이 폼을 제출하면 빈 공간으로 제출이 되버린다.
- 유효성 검사를 스프링에서는 어떻게 할까?
<form method="post">
Description: <input type="text" name="description"/
required="required">
<input type="submit" class="btn btn-success"/>
</form>
- 단순히 input 태그 안에 required=”required” 를 추가하면 된다.
- 하지만 HTML 이나 자바스크립트에서 유효성 검사는 해커로부터 아주 쉽게 덮어쓸 수 있다고 한다.
Validations with Spring Boot
- 4 Steps
- Spring Boot Starter Validation
- pom.xml
- Command Bean (Form Backing Object)
- 2-way binding(todo.jsp & TodoController.java)
- Add Validations to Bean
- Todo.java
- Display Validation Errors in the View
- todo.jsp
- Spring Boot Starter Validation
1. Spring Boot Starter Validation
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
2. Command Bean (Form Backing Object)
Before TodoController.java
@RequestMapping(value="add-todo", method = RequestMethod.POST)
public String addNewTodo(@RequestParam String description, ModelMap model) {
String username = (String)model.get("name");
todoService.addTodo(username, description,
LocalDate.now().plusYears(1), false);
return "redirect:list-todos";
}
Afrer TodoController.java
@RequestMapping(value="add-todo", method = RequestMethod.POST)
public String addNewTodo(ModelMap model, Todo todo) {
String username = (String)model.get("name");
todoService.addTodo(username, todo.getDescription(),
LocalDate.now().plusYears(1), false);
return "redirect:list-todos";
}
- 해당 방법을 통해 직접적으로 Todo Bean과 연결시켜 준다.
Before todo.jsp
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<link href="webjars/bootstrap/5.1.3/css/bootstrap.min.css" rel="stylesheet" >
<title>Add Todo Page</title>
</head>
<body>
<div class="container">
<h1>Enter Todo Details</h1>
<form method="post">
Description: <input type="text" name="description"/
required="required">
<input type="submit" class="btn btn-success"/>
</form>
</div>
<script src="webjars/bootstrap/5.1.3/js/bootstrap.min.js"></script>
<script src="webjars/jquery/3.6.0/jquery.min.js"></script>
</body>
</html>
After todo.jsp
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<html>
<head>
<link href="webjars/bootstrap/5.1.3/css/bootstrap.min.css" rel="stylesheet" >
<title>Add Todo Page</title>
</head>
<body>
<div class="container">
<h1>Enter Todo Details</h1>
<form:form method="post" modelAttribute="todo">
Description: <form:input type="text" path="description"
required="required"/>
<form:input type="hidden" path="id"/>
<form:input type="hidden" path="done"/>
<input type="submit" class="btn btn-success"/>
</form:form>
</div>
<script src="webjars/bootstrap/5.1.3/js/bootstrap.min.js"></script>
<script src="webjars/jquery/3.6.0/jquery.min.js"></script>
</body>
</html>
- 스프링 폼 태그 라이브러리를 사용하기 위해 상단에 선언해준다.
- 형식에 맞게 폼을 변형해준다.
- modelAttribute=”todo” 등 매칭해줘야 될 것들을 맞춰준다.
- 원하는 정보는 Description 이지만 정보를 넘겨줄 때 id와 done 정보가 없으면 에러가난다.
- 이 부분을 처리하기 위해서 hidden으로 숨겨준다.
Problem is
이렇게 하고 나서도 문제가 생긴다.
Error message is
- Neither binding result nor plain target object for being to do available as request attribute
The problem is showNewTodoPage()
- That’s the one which is called when
add-todo
is called - This one is not setting an attribute called to do into the model
Before TodoController.java
//GET, POST
@RequestMapping(value="add-todo", method = RequestMethod.GET)
public String showNewTodoPage() {
return "todo";
}
After TodoController.java
//GET, POST
@RequestMapping(value="add-todo", method = RequestMethod.GET)
public String showNewTodoPage(ModelMap model) {
String username = (String)model.get("name");
Todo todo = new Todo(0, username, "Default Desc", LocalDate.now().plusYears(1), false);
model.put("todo", todo);
return "todo";
}
- One side binding ->
"Default Desc"
- Basically from your controller to the values which are shown in the form that one side
- The second side is whatever values you are entering in here
3. Add Validations to Bean
- Todo.java
TodoController.java
@RequestMapping(value="add-todo", method = RequestMethod.POST) public String addNewTodo(ModelMap model, @Valid Todo todo) { String username = (String)model.get("name"); todoService.addTodo(username, todo.getDescription(), LocalDate.now().plusYears(1), false); return "redirect:list-todos"; }
Todo.java
@Size(min=10, message="Enter at least 10 characters")
private String description;
- @Size 애너테이션을 이용해 유효성 검사를 한다.
- 컨트롤러에서 @Valid를 사용해서 Todo의 bean 유효성 검사
4. Display Validation Errors in the View
- VIew 에서 에러페이지가 나오도록 하기 위해 JSP 를 수정
todo.jsp
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<html>
<head>
<link href="webjars/bootstrap/5.1.3/css/bootstrap.min.css" rel="stylesheet" >
<title>Add Todo Page</title>
</head>
<body>
<div class="container">
<h1>Enter Todo Details</h1>
<form:form method="post" modelAttribute="todo">
Description: <form:input type="text" path="description"
required="required"/>
<form:errors path="description" cssClass="text-warning"/>
<form:input type="hidden" path="id"/>
<form:input type="hidden" path="done"/>
<input type="submit" class="btn btn-success"/>
</form:form>
</div>
<script src="webjars/bootstrap/5.1.3/js/bootstrap.min.js"></script>
<script src="webjars/jquery/3.6.0/jquery.min.js"></script>
</body>
</html>
<form:errors path="description" cssClass="text-warning"/>
추가- JSP를 수정하면 부트스트랩에서 제공하는 cssClass를 사용해 css를 컨트롤 할 수 있다.
TodoController.java
@RequestMapping(value="add-todo", method = RequestMethod.POST)
public String addNewTodo(ModelMap model, @Valid Todo todo, BindingResult result) {
if(result.hasErrors()){
return "todo";
}
String username = (String)model.get("name");
todoService.addTodo(username, todo.getDescription(),
LocalDate.now().plusYears(1), false);
return "redirect:list-todos";
}
- 스프링에서 제공하는 BindingResult 를 통해 오류 내용을 JSP로 보내줌
- 조건문을 활용해서 에러가 있으면 todo 페이지에 남아 있으면서 에러메세지를 뷰를 통해 브라우저에서 보여준다.
댓글남기기