1. 유효성 검사
- 메이븐 레파지토리 → 추가 한 다음에 refresh gradle
* VaildController, ex01, ex01_result, validVO
- VaildController
package com.simple.basic.controller;
import java.util.List;
import javax.validation.Valid;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.Errors;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import com.simple.basic.command.ValidVO;
@Controller
@RequestMapping("/valid")
public class ValidController {
@GetMapping("/ex01")
public String ex01() {
return "valid/ex01";
}
//@Valid - 유효성 검사를 진행, Errors - 유효성 검사에 실패하면 에러 객체로 바인딩
@PostMapping("/actionForm")
public String actionForm(@Valid ValidVO vo, Errors error, Model model) {
//에러 발생하면 숫자료 표현 됨
System.out.println(error.getErrorCount());
//error가 있다면 true, 에러가 없다면 false
if(error.hasErrors()) {
List<FieldError> list= error.getFieldErrors(); //에러가 발생된 목록
for(FieldError err : list) {
// System.out.println(err.getField()); //에러 필드명
// System.out.println(err.getDefaultMessage()); //에러 메시지
if(err.isBindingFailure()) { //유효성 검사의 실패가 아니라, 자바 내부의 에러라면 true
model.addAttribute( "valid_" + err.getField(), "형식이 올바르지 않습니다" );
} else { //유효성 검사에 실패한 목록들이 들어옴(목록의 메세지 추출)
model.addAttribute( "valid_" + err.getField(), err.getDefaultMessage() );
}
} //end
model.addAttribute("vo", vo); //사용자가 작성한 값을 화면으로
return "valid/ex01";
}
return "valid/ex01_result";
}
}
- ex01
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h3>서버측 유효성 검사</h3>
<form action="actionForm" method="post">
<!-- null인 경우 에러가 발생하기 때문에 null 처리를 진행해야 합니다. -->
이름: <input type="text" name="name" th:value="${vo != null ? vo.name : ''}">[[${valid_name}]]<br/>
급여: <input type="text" name="salary" th:value="${vo != null ? vo.salary : ''}">[[${valid_salary}]]<br/>
전화번호: <input type="text" name="phone" th:value="${vo != null ? vo.phone : ''}">[[${valid_phone}]]<br/>
이메일: <input type="text" name="email" th:value="${vo != null ? vo.email : ''}">[[${valid_email}]]<br/>
<input type="submit" value="확인">
</form>
</body>
</html>
- ex01_result
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h3>결과 화면</h3>
</body>
</html>
- validVO: int는 기본값이 0이고, 문자열을 받을 수 없음
package com.simple.basic.command;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class ValidVO {
/*
* @NotNull - null값만 허용하지 않음(wrapper의 Integer, Long, String 등등)
* @NotBlack - 좀 더 강력한 제약 조건, null값과 공백을 허용하지 않음(String에만 적용)
* @Pattern - 정규 표현식에 맞는 문자열을 정의할 수 있음(String에만 적용)
* @NotEmpty - null값을 허용하지 않음(Array, list에 적용)
* @Email - 이메일 형식 검증(공백은 통과)
* @Min - 최소값
* @Max - 최대값
*/
//@NotNull
@NotBlank(message = "이름은 필수 입니다!")
private String name;
//무조건 Integer라고 작성하라고 하는건 아니지만 Integer 기본값은 null, int 기본값은 0
//숫자, 실수형의 원시 타입은 기본값이 0이라서 공백 맵핑이 불가능 하기 때문에 래퍼 타입으로 선언하는 편이 좋습니다.
@NotNull(message = "급여는 필수 입니다!") //숫자형
private int salary;
@Pattern(regexp = "[0-9]{3}-[0-9]{4}-[0-9]{4}", message = "전화번호 형식은 000-0000-0000입니다") //정규 표현식
private String phone;
@NotBlank //동시에 적용이 가능함
@Email(message = "email 형식이어야 합니다.") //email 형식이어야 합니다. 단, 공백은 통과시킵니다.
private String email;
}
2. DB 연결
- 메이븐 레파지토리: build gradle에 넣을 것
- application.properties
server.port=8383
################# 데이터베이스 연결, 커넥션 풀 자동 연결 ###########
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/spring?serverTimezone=Asia/Seoul
spring.datasource.username=spring
spring.datasource.password=spring
##jsp를 뷰로 사용하려면 리졸버 뷰를 선언합니다.
#spring.mvc.view.prefix=/WEB-INF/views/
#spring.mvc.view.suffix=.jsp
############ 마이 바티스 관련 설정 ################
# 매퍼 xml의 위치 - classpath:/ 리소스 폴더의 하위를 나타냅니다.
mybatis.mapper-locations=classpath:/mapper/*.xml
#단축명으로 사용할 클래스의 패키지명(여기에 있는 클래스들은 클래스 명을 따라갑니다-클래스명 대문자)
mybatis.type-aliases-package=com.simple.basic.command
* TestMapper.java, TestMapper.xml, MybatisTest
- 에러 나면 버전 맞춰주고, 경로 확인하고, 어노테이션 mapper 확인, namespace에 인터페이스 위치 확인해볼 것!
- TestMapper.java
package com.simple.basic.mapper;
import org.apache.ibatis.annotations.Mapper;
@Mapper //스트링 부트에서는 매퍼 인터페이스 꼭 붙이세요.
public interface TestMapper {
public String getTime();
}
- TestMapper.xml: 선언부에 mapper 넣기
<?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="com.simple.basic.mapper.TestMapper">
<select id= "getTime" resultType="string">
select now()
</select>
</mapper>
- MybatisTest
package com.simple.basic;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import com.simple.basic.mapper.TestMapper;
@SpringBootTest
public class MybatisTest {
@Autowired
TestMapper testMapper;
@Test
public void testCode01() {
System.out.println(testMapper.getTime());
}
}
- 추가 교안 참고: SQL문 실행 로그 기능 더하기
* logback.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{yyyyMMdd HH:mm:ss.SSS} [%thread] %-3level %logger{5} - %msg %n</pattern>
</encoder>
</appender>
<logger name="jdbc" level="OFF"/>
<logger name="jdbc.sqlonly" level="OFF"/>
<logger name="jdbc.sqltiming" level="DEBUG"/>
<logger name="jdbc.audit" level="OFF"/>
<logger name="jdbc.resultset" level="OFF"/>
<logger name="jdbc.resultsettable" level="DEBUG"/>
<logger name="jdbc.connection" level="OFF"/>
<root level="INFO">
<appender-ref ref="STDOUT" />
</root>
</configuration>
3. 추후에 공부하면 좋은 것! (일부분의 회사들만 추가적으로 대입하는 단계임)
4. 판매자 매니저 프로젝트(스프링 보다 좀 더 난이도 있는 모형)
1) 구현 순서
- build-gradle에서 sql 실행 로그 복사해서 붙이고 application.propterties는 그대로 복사
- 3번째 사진 로그 파일 2개 복사해서 resource에 넣을 것: 그 다음에 refresh gradle
- mapper 폴더 생성, command 패키지 생성해서 application.properties 패키지 명 변경해줄 것
- home 화면 지우고 main을 template 아래에 넣을 것
* HomeController, productController
- HomeController
package com.coding404.myweb.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class HomeController {
@GetMapping("/")
public String home() {
return "main";
}
}
- productController
package com.coding404.myweb.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping("/product")
public class ProductController {
@GetMapping("/productReg")
public String reg() {
return "product/productReg";
}
@GetMapping("/productList")
public String list() {
return "product/productList";
}
@GetMapping("/productDetail")
public String detail() {
return "product/productDetail";
}
}
* 실습(main.html, basicLayout)
- main.html
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<th:block th:replace="~{ /include/basicLayout :: 함수( ~{:: .wrap } ) }">
<div class="wrap">
<div class="warp_inner">
<!-- left_menu end -->
<div class="right_content">
<div class="midiaq">
<div class="mainWrapper">
<div class="ipssGiudeBlock">
<span>판매자매니저가 더 쉽고 편하게 개편되었습니다.</span>
</div>
</div>
<div class="mainWrapper">
<div class="currentStatusBlock">
<div class="statusBoard">
<div class="section">
<a href="#">
<h3>주문확인지연</h3>
<span>0</span>
</a>
</div>
<div class="section">
<a href="#">
<h3>발송처리지연</h3>
<span>0</span>
</a>
</div>
<div class="section">
<a href="#">
<h3>취소지연</h3>
<span>0</span>
</a>
</div>
<div class="section">
<a href="#">
<h3>반품지연</h3>
<span>0</span>
</a>
</div>
<div class="section">
<a href="#">
<h3>교환지연</h3>
<span>0</span>
</a>
</div>
<div class="section">
<a href="#">
<h3>교환반품</h3>
<span>0</span>
</a>
</div>
</div>
</div>
</div>
<div class="mainWrapper">
<div class="mBlockWrap col1 sales">
<div class="mainBlock">
<div class="mTitle">
<h2>판매현황</h2>
</div>
<div class="mContent">
<div class="statusBox">
<dl>
<a href="#"><dt>입금대기</dt></a>
<dd>0</dd>
</dl>
<dl>
<a href="#"><dt>입금대기</dt></a>
<dd>0</dd>
</dl>
<dl>
<a href="#"><dt>입금대기</dt></a>
<dd>0</dd>
</dl>
<dl>
<a href="#"><dt>입금대기</dt></a>
<dd>0</dd>
</dl>
<dl>
<a href="#"><dt>입금대기</dt></a>
<dd>0</dd>
</dl>
</div>
<div class="statusBox">
<dl>
<a href="#"><dt>배송중</dt></a>
<dd>0</dd>
</dl>
<dl>
<a href="#"><dt>배송완료</dt></a>
<dd>0</dd>
</dl>
<dl>
<a href="#"><dt>구매확정</dt></a>
<dd>0</dd>
</dl>
<dl>
<a href="#"><dt>보류중</dt></a>
<dd>0</dd>
</dl>
<dl>
<a href="#"><dt>....</dt></a>
<dd>0</dd>
</dl>
</div>
</div>
</div>
</div>
<div class="mBlockWrap col2 sales">
<div class="mainBlock">
<div class="mTitle">
<h2>상품현황</h2>
</div>
<div class="mContent">
<div class="statusBox">
<dl>
<a href="#"><dt>판매중상품</dt></a>
<dd>0</dd>
</dl>
<dl>
<a href="#"><dt>판매종료상품</dt></a>
<dd>0</dd>
</dl>
<dl>
<a href="#"><dt>판매가능상품</dt></a>
<dd>0</dd>
</dl>
<dl>
<a href="#"><dt>판매종료예정</dt></a>
<dd>0</dd>
</dl>
</div>
<div class="statusBox">
<dl>
<a href="#"><dt>...</dt></a>
<dd>0</dd>
</dl>
<dl>
<a href="#"><dt>...</dt></a>
<dd>0</dd>
</dl>
<dl>
<a href="#"><dt>...</dt></a>
<dd>0</dd>
</dl>
<dl>
<a href="#"><dt>...</dt></a>
<dd>0</dd>
</dl>
<dl>
<a href="#"><dt>....</dt></a>
<dd>0</dd>
</dl>
</div>
</div>
</div>
</div>
<div class="mBlockWrap col3 sales">
<div class="mainBlock">
<div class="mTitle">
<h2>공지사항</h2>
</div>
<div class="mContent">
<div class="statusBox">
<ul>
<li>
<a href="#">
<span class="tag_point">일반</span>
<span class="txt">[오픈공지] 판매자 스토어 서비스 오픈 안내 (11/9)</span>
</a>
<span class="date">20.10.10</span>
</li>
<li>
<a href="#">
<span class="tag_point">일반</span>
<span class="txt">[오픈공지] 판매자 스토어 서비스 오픈 안내 (11/9)</span>
</a>
<span class="date">20.10.10</span>
</li>
<li>
<a href="#">
<span class="tag_point">일반</span>
<span class="txt">[오픈공지] 판매자 스토어 서비스 오픈 안내 (11/9)</span>
</a>
<span class="date">20.10.10</span>
</li>
<li>
<a href="#">
<span class="tag_point">일반</span>
<span class="txt">[오픈공지] 판매자 스토어 서비스 오픈 안내 (11/9)</span>
</a>
<span class="date">20.10.10</span>
</li>
<li>
<a href="#">
<span class="tag_point">일반</span>
<span class="txt">[오픈공지] 판매자 스토어 서비스 오픈 안내 (11/9)</span>
</a>
<span class="date">20.10.10</span>
</li>
</ul>
</div>
</div>
</div>
</div>
<div class="mBlockWrap col3 sales">
<div class="mainBlock">
<div class="mTitle">
<h2>문의현황</h2>
</div>
<div class="mContent">
<div class="statusBox">
<ul>
<li>
<a href="#">
<span class="tag_point">일반</span>
<span class="txt">[오픈공지] 판매자 스토어 서비스 오픈 안내 (11/9)</span>
</a>
<span class="date">20.10.10</span>
</li>
<li>
<a href="#">
<span class="tag_point">일반</span>
<span class="txt">[오픈공지] 판매자 스토어 서비스 오픈 안내 (11/9)</span>
</a>
<span class="date">20.10.10</span>
</li>
<li>
<a href="#">
<span class="tag_point">일반</span>
<span class="txt">[오픈공지] 판매자 스토어 서비스 오픈 안내 (11/9)</span>
</a>
<span class="date">20.10.10</span>
</li>
<li>
<a href="#">
<span class="tag_point">일반</span>
<span class="txt">[오픈공지] 판매자 스토어 서비스 오픈 안내 (11/9)</span>
</a>
<span class="date">20.10.10</span>
</li>
<li>
<a href="#">
<span class="tag_point">일반</span>
<span class="txt">[오픈공지] 판매자 스토어 서비스 오픈 안내 (11/9)</span>
</a>
<span class="date">20.10.10</span>
</li>
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</th:block>
</html>
- basicLayout
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<th:block th:fragment="함수(section)">
<head>
<meta charset="UTF-8" />
<meta charset="EUC-KR" />
<title>연습용</title>
<link rel="stylesheet" type="text/css" href="../css/index.css" />
<link rel="stylesheet" type="text/css" href="../css/footer.css" />
<link rel="stylesheet" type="text/css" href="../css/main.css" />
<link rel="stylesheet" type="text/css" href="../css/loading.css" />
<link rel="stylesheet" type="text/css" href="../css/jquery-ui.min.css" />
<link rel="stylesheet"
href="https://use.fontawesome.com/releases/v5.0.13/css/all.css"
integrity="sha384-DNOHZ68U8hZfKXOrtjWvjxusGo9WQnrNx2sqG0tfsghAvtVlRW3tvkXWZh58N9jp"
crossorigin="anonymous">
<script src="../js/jquery-1.12.1.min.js"></script>
<script src="../js/jquery-ui.min.js"></script>
<script src="../js/style.js"></script>
<!--개인 -->
<link rel="stylesheet" type="text/css" href="/css/modal.css" />
<script src="/js/modal.js"></script>
</head>
<!-- 공통적인 부분들을 layout에 넣고 변경되는 부분을 main에다가 넣어줄 것 -->
<body>
<!-- 실습 main 페이지 템플릿 화 -->
<header class="header">
<div class="header">
<h3 style="color: #fff; position: absolute; left: 20px; top: 27px;">coding404
- 연습용 입니다. 이에 대한 무단 복제 및 배포를 원칙적으로 금합니다. 원본파일 및 핸드폰 촬영, 동영상강좌 녹화를
통한 무단 복제 · 배포하는 경우 저작권법 제136조에 의한 저작재산권 침해 죄에 해당될 수 있으니 각별한 주의
바랍니다.</h3>
<span class="admin_id"><b style="color: #7866c9;">관리자</b>홍길동
님</span>
</div>
</header>
<aside class="aside">
<span class="menuBtn">버튼</span>
<ul class="sidenav">
<li class="sub_menu_toggle"><a href="#">- 상품관리(예제)</a>
<ul class="sub_menu ">
<li><a href="#">-상품등록</a></li>
<li><a href="#">-상품조회 / 수정</a></li>
<li><a href="#">-하단메뉴</a></li>
</ul></li>
<li class="sub_menu_toggle"><a href="#">- 게시글 연습(초급)</a>
<ul class="sub_menu">
<li><a href="#">-전체 글목록</a></li>
<li><a href="#">-글 등록</a></li>
<li><a href="#">-내글 목록</a></li>
</ul></li>
<li class="sub_menu_toggle"><a href="#">- 판매자 공지관리(중급)</a>
<ul class="sub_menu">
<li><a href="#">-판매자공지목록</a></li>
<li><a href="#">-판매자공지등록</a></li>
<li><a href="#">-판매자공지보기</a></li>
</ul></li>
<li class="sub_menu_toggle"><a href="#">- 예시메뉴</a>
<ul class="sub_menu">
<li><a href="#">-예시메뉴</a></li>
<li><a href="#">-예시메뉴</a></li>
<li><a href="#">-예시메뉴</a></li>
</ul></li>
</ul>
</aside>
<th:block th:replace=${section}></th:block>
<footer id="footer">
<div class="footer_wrap">
<div class="footer_top">
<!-- 상위 -->
<ul class="fl_right">
<li><a href="#"><span>Coding404 둘러보기</span></a></li>
<li><a href="#"><span>상품등록</span></a></li>
<li><a href="#"><span>상품관리</span></a></li>
<li><a href="#"><span>상품수정</span></a></li>
<li><a href="#"><span>회원</span></a></li>
<li><a href="#"><span>고객센터</span></a></li>
</ul>
</div>
</div>
<div class="footer_wrap2">
<div class="footer_bot">
<!-- 하위 -->
<ul class="fl_left">
<li><a href="#">이용약관</a></li>
<li><a href="#">위치기반서비스 이용약관</a></li>
<li><a href="#">개인정보처리방침</a></li>
<li><a href="#">청소년보호정책</a></li>
<li><a href="#">제휴/프로모션문의</a></li>
<li><a href="#">이메일주소무단수집거부</a></li>
<li><a href="#">파트너센터</a></li>
</ul>
<p>
<strong>(주)Coding404</strong> <span>(주소는 비밀)</span> <span>대표이사
: Coding404(PARK)</span> <span>사업자등록번호 : 비밀</span> <span>통신판매업신고번호
: 2018-성남분당B-0004</span> <span>사업자정보확인</span> <br /> <span>문의전화
: 비밀 (평일 09:00-18:00, 유료)</span> <span>이메일 : yopy0817@gmail.com</span> <span>호스팅서비스사업자
: (주)AWS</span> <span>© Coding404 Entertainment Corp.</span>
</p>
</div>
</div>
</footer>
</body>
</th:block>
</html>
- 이런식으로 productList, productReg, productDetail wrap만 냅두고 다 지울 것(예시 밑에 사진 참고 할 것)
- productList의 모달은 레이아웃 창으로 옮겨둘 것!
- a th:href 경로 걸어주기 : <a th:href="@{/product/productReg}">
- 쌤이 준 프로젝트 폴더 참고해서 다시 해볼 것!
- gradle import 하는 법
'TIL > Spring boot' 카테고리의 다른 글
day88-spring boot (0) | 2023.02.17 |
---|---|
day86-spring boot (0) | 2023.02.16 |
day85-spring boot (0) | 2023.02.15 |
day83-spring boot (0) | 2023.02.13 |
day82-spring boot (0) | 2023.02.09 |