StudyServer
web, server, java, spring 등.. 공부한 것을 기록하는 장소 입니다. 공부하면서 정리하였기 때문에 틀린 내용이 있을 수 있습니다. 이야기 해주시면 수정하겠습니다.

게시판 만들기-회원탈퇴 및 게시판 삭제 플래그 추가

2019-04-25 00:00:00 +0000

회원 탈퇴

  • 회원 탈퇴 기능을 만들면 탈퇴한 회원여부를 flag로 기록해야한다
  • 데이터 보존을 위한 용도
    • 회원탈퇴 추가
    • 로그인 : 탈퇴한 회원 로그인 안되게.. 로그인 시 탈퇴한 회원이 아닌 회원의 비밀번호 체크 ( 0 )
    • 게시물 : 탈퇴한 회원 게시물 플래그 수정
    • 검색 : 탈퇴한 회원 id로 검색안되도록 수정
    • 회원가입 : 회원가입 시 탈퇴한 회원 id 체크 제외 ( 0)
회원 정보 아이콘 추가
  • bootstrap awesome font ‘fa-user’ icon을 추가한다
<c:when test="${not empty userVO.id}">
    ${userVO.name} 님 환영합니다
    <span id="user-logout-button">로그아웃</span>
    <span id="user-info-form"><i class="fas fa-user fa-2x"></i></span>    
</c:when>
회원 탈퇴 URL 정의
  • 회원정보 userInfoForm.jsp를 페이지를 추가한다
  • 회원정보 아이콘을 누른 뒤 회원이 존재한다면 페이지 이동을 하고 존재하지 않는다면 알람을 띄운다
url 설명 Method
/user/info 유저가 존재하는지 체크 POST
/user/info 유저 정보 페이지로 이동 GET
/user/leave 회원 탈퇴 GET
DB 수정
  • 유저 삭제 flag 추가
alter table user add USER_DEL boolean DEFAULT '0';
  • VO 수정
  • userVO에 userDel 멤버변수를 추가한다
private boolean userDel;        // userVO에 추가
  • 유저 정보를 가져올 때 유저가 삭제되었는지 여부도 조건으로 건다
  • 유저 탈퇴 플래그를 수정하는 쿼리를 만든다
<select id="getUserVO" parameterType="String"  resultType="UserVO">
     SELECT   user_seq as userSeq
              , id
              , password
              , name
              , user_del as userDel
     FROM user
     WHERE  id = #{id}
     AND    user_del != 1
</select>

<update id="updateUserDelFlag" parameterType="Long">
     UPDATE          user
     SET             user_del = 1
     WHERE      user_seq = #{userSeq}
</update>  

회원 탈퇴 처리

  • 회원 탈퇴 시 플래그를 수정하고 session 에서 삭제
@Override
public ResultMap updateUserDelFlag(final Long userSeq, HttpSession session) throws Exception {
    int result = dao.updateUserDelFlag(userSeq);
    if(0 == result) {
        throw new LogicException("609", "알 수 없는 에러로 회원탈퇴에 실패했습니다");    
    }
    
    session.invalidate();
    
    ResultMap resultMap = new ResultMap();
    resultMap.setStatus("200");
    resultMap.setMsg("");    
    
    return resultMap;
}

게시판 삭제 flag 추가

  • board 테이블에 삭제 플래그 추가
alter table board add BOARD_DEL boolean DEFAULT '0';
  • boardVO 에 삭제 플래그 추가
private boolean boardDel;    // boardVO에 추가
  • 삭제버튼 클릭 시 테이블 삭제 대신 flag 수정
  • 게시판 검색 시 삭제된 게시물은 검색되지 않도록 검색 조건 수정
<!-- 게시물 삭제 시 플래그 수정 -->
<delete id="updateBoardDelFlag" parameterType="Long">
    UPDATE        board
    SET            board_del = 1
    WHERE        board_seq = #{boardSeq}
</delete>

<!-- 검색 조건 수정 -->
<sql id="searchBoard">
<choose>
<when test="searchType != null and searchValue != null">
           <choose>
           <when test='searchType == "T"'>
                WHERE (TITLE LIKE CONCAT('%',#{searchValue},'%')
                AND BOARD_DEL = 0)
           </when>
           <when test='searchType == "C"'>
                WHERE (CONTENTS LIKE  CONCAT('%',#{searchValue},'%')
                AND BOARD_DEL = 0)
           </when>
           <when test='searchType == "W"'>
                WHERE (WRITER LIKE  CONCAT('%',#{searchValue},'%')
                AND BOARD_DEL = 0)
           </when>
           <when test='searchType == "A"'>
                WHERE (TITLE LIKE CONCAT('%',#{searchValue},'%')  OR CONTENTS LIKE CONCAT('%',#{searchValue},'%'))
                AND BOARD_DEL = 0
           </when>
           <otherwise>
                WHERE BOARD_DEL = 0
           </otherwise>
           </choose>
</when>
<otherwise>
     WHERE BOARD_DEL = 0
</otherwise>
</choose>
</sql>

  • dao 를 추가하고 삭제 dao 대신 updateBoardDelFlag 쿼리를 실행하도록 만든다
     public int updateBoardDelFlag(Long boardSeq) {
           return update("board.updateBoardDelFlag", boardSeq);
     }

footer 하단에 고정시키기

2019-04-24 00:00:00 +0000
  • footer를 하단에 고정시키지 않으면 contents의 내용이 끝나고 나서 바로 footer가 온다.
  • contents의 길이가 어느정도 있도록 보여야 한다.
  • footer에 absolute로 위치를 고정시키고 footer위 height 만큼 contents(본문)쪽에 bottom padding 을 준다
  • css
    html,
    body {
       margin:0;
       padding:0;
       height:100%;
    }
    .contents-wrap {
       min-height:100%;
       position:relative;
       padding-bottom:100px;/* footer height */
    }
    .footer {
       width:100%;
       height:100px;
       position:absolute;
       bottom:0;
       background:#5eaeff;
      text-align: center;
      color: white;
    }
    
  • html
<%@ page language="java" contentType="text/html; charset=utf-8"
     pageEncoding="utf-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
<!DOCTYPE html>
<html lang="ko">
<head>
<link rel="stylesheet" type="text/css"  href="/resources/css/common.css">
<script src="http://code.jquery.com/jquery-3.1.1.js"></script>
<sitemesh:write property='head' />
<!-- CSS -->
<link rel="stylesheet"  href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"  integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<link rel="stylesheet"  href="https://use.fontawesome.com/releases/v5.8.1/css/all.css"  integrity="sha384-50oBUHEmvpQ+1lW4y57PTFmhCaXp0ML5d60M1M7uH2+nqUivzIebhndOJK28anvf" crossorigin="anonymous">
</head>
<body>
     <div class="container contents-wrap">
           <div class="row">
                <div class="top-menu-list pull-right">
                     <c:choose>
                           <c:when test="${not empty  userVO.id}">
                                ${userVO.name} 님 환영합니다
                                <span  id="user-logout-button">로그아웃</span>
                                
                                
                           </c:when>
                           <c:otherwise>              
                                <a  href="/user/loginForm">로그인</a>
                                <a  href="/user/createUserForm">회원가입</a>
                           </c:otherwise>
                     </c:choose>
                </div>
           </div>
           
           <div class="row constants-top-menu">
                <div class="col-md-3 col-xs-3"><a  href="/main">메인화면</a></div>
                <div class="col-md-3 col-xs-3"><a  href="/board/list?page=1&count=10">게시판1</a></div>
                <div class="col-md-3 col-xs-3">게시판2</div>
                <div class="col-md-3 col-xs-3">게시판3</div>
           </div>
           
           <sitemesh:write property='body' />
           <footer class="footer">
                <div>Basic Board</div>
                <div>@ 2019 wonhui Park</div>
                <i class="fab fa-java fa-2x"></i><i class="fab  fa-html5 fa-2x"></i><i class="fab fa-github-alt fa-2x"></i>
           </footer>
     </div>
     <script type="text/javascript"  src="/resources/js/common.js"></script>
</body>
</html>

LoginForm 만들 때 팁

  • div로 배경화면에 색상을 넣어 LoginForm을 만들면 ui와 form의 여백이 없이 딱 맞게 만들어진다
  • 공간이 있어야 하는데 bootstrap을 사용하면 flex가 많아서 padding, margin이 잘 안먹는다.
  • 이럴 때 요소에 padding, margin 을 준다. 예를들어 button의 margin을 주면 margin만큼 여백이 들어선다

/**

  • RECOMMENDED CONFIGURATION VARIA*BLES: EDIT AND UNCOMMENT THE SECTION BELOW TO INSERT DYNAMIC VALUES FROM YOUR PLATFORM OR CMS.
  • LEARN WHY DEFINING THESE VARIABLES IS IMPORTANT: https://disqus.com/admin/universalcode/#configuration-variables/ / var disqus_config = function () { this.page.url = PAGE_URL; // Replace PAGE_URL with your page’s canonical URL variable this.page.identifier = PAGE_IDENTIFIER; // Replace PAGE_IDENTIFIER with your page’s unique identifier variable }; */ (function() { // DON’T EDIT BELOW THIS LINE var d = document, s = d.createElement(‘script’); s.src = ‘https://parkwonhui.disqus.com/embed.js’; s.setAttribute(‘data-timestamp’, +new Date()); (d.head || d.body).appendChild(s); })(); </script>

bootstrap4 사용법

2019-04-23 00:00:00 +0000

Bootstrap 정리

CDN

  • head에 bootstrap을 추가하는 소스코드를 추가한다
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script><script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>

모바일

  • 모바일 환경에서 ui가 변경되어야 한다. 적절히 변경될 수 있도록 viewport 메타 태그를 추가한다
  • viewport 태그는 모바일 폰에서의 크기 조절을 위해 만듬
  • PC의 viewport는 웹 브라우저 창과 같음(크기 조절 가능)
  • 모바일의 viewport는 웹 브라우저 창보다 작고 확대 축소로 뷰포트 배율 변경 가능
  • 데스크탑에서 같은 px를 보더라도 pc에선 알맞게 나오지만 모바일에선 작게 나온다. 그렇기 때문에 viewport로 적절한 화면 배율을 설정해야 한다
<meta name="viewport" content="width=device-width, initial-scale=1">    

Container

  • body에 있는 모든 태그요소는 ‘container’ 안에 존재해야 한다.
  • 만약 화면 너비 전체를 사용하고 싶다면 ‘.container-fluid’ class를 사용한다
<div class="container"></div>

Grid

  • 크기에 따라 4가지 class 로 나뉜다
  • 크기를 좀 더 늘리고 싶다면 맨 뒤의 숫자를 변경한다
col-lg-1 col-md-1 col-sm-1 col-xs-1
아주 큰 화면 중간 화면 작은 기기(태블릿) 모바일 폰
<div class="row">
    <div class="col-lg-1">큰 기기 테스크탑</div>
    <div class="col-md-1">중간 기기 데스크탑</div>
    <div class="col-xs-1">작은 기기 태블릿</div>
    <div class="col-sm-1">매우 작은 기기 모바일폰</div>
</div>
  • pc와 모바일의 요소의 비율을 다르게 하고 싶다면 각 각의 크기를 설정한다
  • 아래 소스코드를 보면 첫번째 요소는 보통 pc화면에서는 (md) 크기가 4이고 두번째 요소도 마찬가지로 크기가 4이다. 그러므로 pc에서 두 요소는 5:5 비율이다
  • 하지만 모바일에서 첫번째 요소는 크기가 12인데 두번째 요소2이다. 그래서 모바일로 보면 첫번째 요소와 두번째 요소의 크기가 다르다 ~~~
col-xs-12 col-md-8
col-xs-6 col-md-4

- 컬럼 오프셋 설정으로 몇 칸 띄어서 요소를 배치할 수 있다
- 예를 들어 <div class="col-md-4 col-md-offset-3">col-md-4</div> 라면 3칸 정도 띄운 후 해당 div 요소를 배치한다

col-md-4
col-md-4

### DataTable
- [DataTable](https://datatables.net/examples/styling/bootstrap4)
- DataTable 사용을 위해 아래 js를 추가한다

<script src="https://cdn.datatables.net/1.10.19/js/jquery.dataTables.min.js"></script>
<script src="https://cdn.datatables.net/1.10.19/js/dataTables.bootstrap.min.js"></script> ~~~
  • table 태그로 DataTable을 작성한다
  • colgroup으로 순서대로 필드의 크기 비율을 설정한다
  • thead 는 맨 위의 필드명을 뜻하고 tbody는 필드의 값을 뜻한다
<table id="board1-table" class="table table-striped table-bordred">
<colgroup>
    <col width="10%" />
    <col width="40%" />
    <col width="10%" />
</colgroup>
<thead>
    <tr>
        <td>게시물 번호</td>
        <td>게시물 제목</td>
        <td>날짜</td>
    </tr>
</thead>
<tbody>
    <tr>
        <td>1</td>
        <td>1번 게시물</td>
        <td>2019-4-12</td>
    </tr>
    <tr>
        <td>2</td>
        <td>2번 게시물</td>
        <td>2018-4-12</td>
    </tr>
    <tr>
        <td>3</td>
        <td>3번 게시물</td>
        <td>2018-4-13</td>
    </tr>
</tbody>
</table>

Pagination

  • pagination
  • nav 태그는 html5에 등장한 태그. 현재 페이지에서 다른 페이지로 이동(탐색)을 수행할 때 사용한다. 메뉴 뿐 아니라 페이지네이션도 네비게이션에 해당한다
  • li태그에 page-item 속성을 준다
  • a태그에 class로 “page-link” 속성을 준다
  • 현재 선택한 페이지 숫자와 동일하다면 태그에 active를 준다
<nav>
  <ul class="pagination">
    <li class="page-item"><a class="page-link" href="#">Previous</a></li>
    <li class="page-item active"><a class="page-link" href="#">1</a></li>
    <li class="page-item"><a class="page-link" href="#">2</a></li>
    <li class="page-item"><a class="page-link" href="#">3</a></li>
    <li class="page-item"><a class="page-link" href="#">Next</a></li>
  </ul>

selectForm

  • form-control class 를 사용한다
  • select box의 크기는 col-md-2, col-sm-1 등으로 정할 수 있다\
<select class="form-control col-sm-1 col-md-2 list-select-form" name="searchType">
    <option value="A">전체</option>
    <option value="T">제목</option>
    <option value="C">내용</option>
    <option value="W">작성자</option>
</select>

form 중앙정렬

  • text-align:-webkit-center
  • webkit 이란 크롬, 사파리 브라우저에 적용, -moz는 파이어폴스, -ms는 익스플로러를 뜻함

어썸 폰트

  • 어썸폰트란 부트스트랩의 text 아이콘을 뜻한다. text이므로 이미지보다 가공하기 쉽고 깨지지 않는다
  • 어썸폰트 공식 홈페이지
  • 아래 style 추가 ~~~
- 사용방법
- fa-spin은 아이콘을 돌린다
- fa-fw는 공백 포함 넓이는 고정하여 깔끔해보이도록 함
- fa-3x는 크기 변경

~~~

Spring 데이터 검증 @Valid, BindingResult

2019-04-22 00:00:00 +0000

Spring 데이터 검증 @Valid, BindingResult

데이터 검증

  • @Valid는 객체에 들어가는 값을 검증해주는 어노테이션이다
  • 유효한 값인지 검증은 소스코드 여러군데서 이루어지기 때문에 불필요한 중복코드가 늘어나고 복잡하다.
  • @Valid를 사용하면 @Min,@Max,@NotNull 등의 어노테이션으로 간단하게 값을 체크할 수 있다
  • @@Valid 어노테이션을 사용하는 방법, BindingResult를 사용하는 방법 두가지로 나뉜다.

@Valid 어노테이션 사용

  • validation-api 가 아닌 hibernate-validator 를 추가해야한다.
  • validation-api 라이브러리를 사용하게 되면 @Range, @NotNull, @Size 등.. 의 어노테이션으로 검증이 불가하다
  • validation-api 를 사용하면 Validator를 상속하는 유효검증 클래스를 만든 후 검증을 구현해야한다(아래에 설명)
<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>4.2.0.Final</version>
</dependency>

model 선언

  • @NotEmpty 은 null과 ““는 비허용하고 “ “ 띄어쓰기는 허용한다
  • @Size와 @Range 어노테이션은 값이 지정한 범위내로 들어올 때만 값을 넣어준다
  • @message는 에러가 발생할 시 defaultText로 지정할 수 있다
import javax.validation.constraints.Size;
import org.hibernate.validator.constraints.NotEmpty;
import org.hibernate.validator.constraints.Range;
public class UserInfo {
     @NotEmpty(message="name을 입력해주세요")
     private String  name;
     @NotEmpty(message="비밀번호를 입력해주세요")
     @Size(min = 6, max=10, message = "길이가 알맞지 않습니다")
     private String  password;
     @Range(min = 1, max = 5)
     private int     grade;
     
     public UserInfo() {}
     @Override
     public String toString() {
           return "User [name=" + name + ", password=" +  password + ", grade=" + grade + "]";
     }
     public String getName() {
           return name;
     }
     public void setName(String name) {
           this.name = name;
     }
     public String getPassword() {
           return password;
     }
     public void setPassword(String password) {
           this.password = password;
     }
     public int getGrade() {
           return grade;
     }
     public void setGrade(int grade) {
           this.grade = grade;
     }    
}

Contorller 선언

  • view에 전달받은 값에 @Valid나 @Validated 어노테이션을 붙인다.
  • 에러 체크는 hasErrors 함수를 사용한다
  • 에러 리스트는 getAllErrors() 함수로 가져온다
  • getDefaultMessage()함수로 defaultError 메시지를 가져올 수 있다
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import my.test.model.UserInfo;
@Controller
public class UserController {
     @RequestMapping(value="/joinForm",  method=RequestMethod.GET)
     public String joinForm(){
           return "join";
     }    
     
     @RequestMapping(value="/join", method=RequestMethod.POST)
     public String join(@Validated UserInfo userInfo,  BindingResult bindingResult){
           System.out.println("name:"+userInfo.getName());
           System.out.println("pass:"+userInfo.getPassword());
          System.out.println("error:"+bindingResult.hasErrors());
           
          if(bindingResult.hasErrors()){
                List<ObjectError> list =  bindingResult.getAllErrors();
                for(ObjectError e : list) {
                     System.out.println(e.getDefaultMessage());
                }
                return "join";
           }
           return "home";
     }
}

View 선언

  • UserInfo 에 들어갈 값을 전달하는 화면을 구성한다.
<%@ page language="java" contentType="text/html; charset=EUC-KR"
    pageEncoding="EUC-KR"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"  "http://www.w3.org/TR/html4/loose.dtd">
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;  charset=EUC-KR">
<title>Insert title here</title>
</head>
<body>
     <form action="/join" method="post">
           <label>이름:</label>
           <input name="name" type="text" id="name">

           <label>비밀번호:</label>
           <input name="password" type="password"  id="password">

           <input type="submit" value="전송">
     </form>
</body>
</html>

BindingResult를 사용

  • Validator를 상속받는 클래스에서 객체값을 검증하는 방식이다
  • hibernate-validator 가 아닌 validation-api 라이브러리를 사용한다
<dependency>
    <groupId>javax.validation</groupId>
    <artifactId>validation-api</artifactId>
    <version>2.0.1.Final</version>
</dependency>

model 선언

  • 검증 클래스를 따로 만들어서 거기서 유효값을 체크한다. 그래서 @Min, @Max 등의 어노테이션을 사용하지 않는다
public class UserInfo {
     private String name;
     private String password;
     
     public UserInfo() {
     }
     public String getName() {
           return name;
     }
     public void setName(String name) {
           this.name = name;
     }
     public String getPassword() {
           return password;
     }
     public void setPassword(String password) {
           this.password = password;
     }
}

validator 선언

  • 객체를 검증할 validator 클래스를 생성
  • Validator를 인터페이스 상속 후 supports, validate 함수를 재정의 한다.
  • validate 함수에서 값이 유효한지 체크한다.
package test.controller;
import org.springframework.validation.Errors;
import org.springframework.validation.Validator;
import test.VO.UserInfo;
public class UserInfoValidator implements Validator{
     public UserInfoValidator() {
     }
     @Override
     public boolean supports(Class<?> clazz) {
            return UserInfo.class.isAssignableFrom(clazz);
     }
     @Override
     public void validate(Object target, Errors errors) {
           UserInfo userInfo = (UserInfo) target;
           
           String mName = userInfo.getName();
           if(null == mName || mName.trim().isEmpty()) {
                System.out.println("회원이름을 이름하세요");
                errors.rejectValue("name", "공백");
           }
           
           String password = userInfo.getPassword();
           if(null == password || password.trim().isEmpty()) {
                System.out.println("회원 비밀번호를 입력하세요");
                errors.rejectValue("password", "공백");
           }
     }
}

Contorller 선언

  • UserInfo값을 받을 때 BindingResult 객체의 값도 받습니다.
  • join url에 호출될 때 마다 initBinder 함수가 호출되면서 UserInfoValidator 객체를 생성한 후 해당 객체의 validate 함수를 호출해서 값이 유효한지 체크한다
  • bindingResult.hasErrors() 함수로 값이 알맞은지 체크할 수 있다.
  • View는 위 예제와 동일하다
import java.text.DateFormat;
import java.util.Date;
import java.util.Locale;
import javax.validation.Valid;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import lombok.extern.log4j.Log4j;
import test.VO.UserInfo;

@Controller
public class HomeController {
     
     private static final Logger logger =  LoggerFactory.getLogger(HomeController.class);
     @RequestMapping(value = "/", method = RequestMethod.GET)
     public String home(Locale locale, Model model) {
           logger.info("Welcome home! The client locale is {}.",  locale);
           
           Date date = new Date();
           DateFormat dateFormat =  DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG,  locale);
           
           String formattedDate = dateFormat.format(date);
           
           model.addAttribute("serverTime", formattedDate );
           
           return "home";
     }
     
     @GetMapping(path = "/joinForm")
     public String joinForm(){
           
           return "join";
     }    
     
     @PostMapping(path = "/join")
     public String join(@Validated UserInfo userInfo,  BindingResult bindingResult){
           System.out.println("name:"+userInfo.getName());
           System.out.println("pass:"+userInfo.getPassword());
           
          System.out.println("error:"+bindingResult.hasErrors());
           
           if(bindingResult.hasErrors()){
                return "join";
           }
           
           return "home";
     }    
     
     
     @InitBinder
     protected void initBinder(WebDataBinder binder) {
           binder.setValidator(new UserInfoValidator());
     }
}

Valid방식과 BindingResult 방식

  • @Valid 방식을 사용하면 유효범위값을 쉽게 체크할 수 있다. BindingResult도 유효범위를 체크하지만 직접 유효범위 체크 코드를 추가해야하므로 @Valid 방식이 좀 더 사용하기 편했다. BindingResult는 일반적으로 유효값을 체크하는 방식보다는 더 간편하고 깔끔하다.

brackets 실시간 미리보기

2019-04-22 00:00:00 +0000

Brackets(브라켓) 실시간 미리보기

  • Brackets 에디터에서 실시간으로 변경된 사항이 적용되는 기능을 사용하고 싶어 설치하게 되었다.
  • f5를 누르지 않아도 화면 그대로 적용이 된다

Brackets 다운로드

에러발생

  • 파일을 저장하는 동안 에러가 발생했습니다
  • 파일…을 저장하던 와중에 에러가 발생했습니다. 파일을 수정할 수 있는 권한이 없습니다.
  • 파일의 이름을 변경하던 중에 에러가 발생했습니다
파일 /_brackets_88091691/제목없음의 이름을 변경하던 중에 에러가 발생했습니다. The file or directory is not part of the currently opened project.
Unfortunately, only project files can be renamed at this point.
  • 권한이 없어서 저장하지 못하는 에러가 발생했다. 이 에러는 관리자 권한으로 실행해서

Posts

subscribe via RSS