mjeongriver
article thumbnail
Published 2023. 2. 14. 18:16
day84-spring boot TIL/Spring boot

1. 유효성 검사

 

 

- 메이븐 레파지토리 → 추가 한 다음에 refresh gradle

 

build.gradle에 추가할 것

 

6번째 사진처럼 ${vo.name} 넣어놓고 다시 ex01로 들어가면 에러 뜸

 

* 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에 넣을 것

 

build.gradle에 넣고 refresh 실행

 

- 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

 

mapper는 패키지로 생성하고 xml 파일 생성, xml은 마이 바티스의 구현체가 될 파일

 

 

2번째 사진처럼 창 나눠놓고 볼 것! - 작성한 다음에 mybatisTest에서 test 실행 - 3번째 사진처럼 결과 나옴(히카리 안넣어도 자동으로 넣어줌)

 

* 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문 실행 로그 기능 더하기

 

1. bulid-gradle에 추가(가장 높은 버전) 하고 나서 refresh 2. application.properties에 강의 교안 내용 추가 3. 그냥 file로 리소스 폴더 아래 properties 파일 생성 해서 강의 교안에 있는 내용 추가해줄 것!

 

resource 폴더 하위에 xml 파일 생성

 

* 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) 구현 순서

new spring stater project에서 뉴 프로젝트 생성(6번째 사진이 정확한 경로임)

 

- build-gradle에서 sql 실행 로그 복사해서 붙이고 application.propterties는 그대로 복사

- 3번째 사진 로그 파일 2개 복사해서 resource에 넣을 것: 그 다음에 refresh gradle

- mapper 폴더 생성, command 패키지 생성해서 application.properties 패키지 명 변경해줄 것

 

선생님이 준 판매자 ui 폴더 경로(css~ 정적파일은 static), 2번째 사진은 template에 넣을 것!

 

- 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)

 

5번째 사진: 경로는 상대 경로로(리눅스에서 인식이 안되서 . 붙여줄 것!

 

더보기

- 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
profile

mjeongriver

@mjeongriver

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

검색 태그