요약정리
c -> s -> Repository JPA 현재 우리가 하고 있는 방식
나중에는 controller를 자동으로 만들음. 시큐리티 같은걸씀.
이거 우리가 안짬. 컨트롤러 만들어주면 자동적으로 만드는데
서비스에서 주는 것임. 서비스는 상속 받아서 옴.
c -> s -> db(jpa, mybatis(a,b)) 현재 jpa
(jpa는 서울권, 아랫지방은 mybatista,b 다 씀)
트렌드는 jpa
(원리 이해를 위해 우리는 이것들을 직접 해보고 있는 것)
(html에서 model로 받은 데이터를 사용하는 방법)
물품 등록 완료 알림을 위해
alert.html 만들어봄
물품 등록 완료시
model으로 msg, url을 담은
alert페이지로이동
alert에서는 위에서 받은 msg와 url을 토대로 출력및 페이지 이동
테이블에 수정, 삭제버튼 만들기
테이블에서 넘버, 타입 받아오기
script에서 컨트롤러로 정보 주는 방법
aop를 배움
html에서 controller로 넘어가기전,
한번 들리는 구간.
여기서 controller의 공통적인 코드를 넣어준다면
controller의 코드 효율성이 증대
현재 service, controller, repository의 이동을 등록해놓음.
오전일과
리스트에 게시글 하나 작성 a태그 추가
<a th:href="@{/item/insertone.do}">
<input type="button" value="추가하기" />
</a>
iteminsertone작성
@PostMapping(value = "/insertone.do")
public String insertOnePOST(Model model, @ModelAttribute Item item, @RequestParam(name="image") MultipartFile file) throws IOException{
if(!file.isEmpty()){
item.setFiledata(file.getBytes());
item.setFilename(file.getName());
item.setFilesize(file.getSize());
item.setFiletype(file.getContentType());
}
short ret = itemService.insertItem(item);
System.out.println("컨트롤러"+item.toString());
if(ret == 1){
model.addAttribute("msg", "물품이 등록되었습니다.");
model.addAttribute("url", "/ROOT/seller/selectlist.do");
return "alert";
}
return "redirect:/seller/insertone.do";
// a태그 역활
// return "redirect:/item/insertok.do";
// alert.html은 알림이 표시
// a태그를 동작시킴
// return "seller/insertok.do";
}
파일 확인 작없 해줌
file쓸때는
controller에서
@RequestParam(name="image") MultipartFile file
필요
그리고 파일이 유무 확인
if(!file.isEmpty()){
item.setFiledata(file.getBytes());
item.setFilename(file.getName());
item.setFilesize(file.getSize());
item.setFiletype(file.getContentType());
}
갑자기 insertok설명중
"redirect:/item/insertok.do"; 이건 a태그 역할이랑 같음.
(이미 아는 것)
post는 화면을 렌더링하는게 아님.
get으로 가야함.
(이미 아는 것. 화면 표기 get, post는 화면내에서 원하는 동작을 실행시키기 위해 쓰는 것)
c -> s -> Repository JPA 현재 우리가 하고 있는 방식
c -> s -> Mapper mybatis
나중에는 controller를 자동으로 만들음. 시큐리티 같은걸씀.
이거 우리가 안짬. 컨트롤러 만들어주면 자동적으로 만드는데
서비스에서 주는 것임. 서비스는 상속 받아서 옴.
c -> s -> db(jpa, mybatis(a,b)) 현재 jpa
alert html 만듬
중요중요중요중요중요중요중요중요중요중요중요중요중요
insertone에서 이미지도 했음.
alert도 함
alert.html
<!DOCTYPE html>
<html lang="ko" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script type="text/javascript">
const msg = "[[${msg}]]";
const url = "[[${url}]]";
alert(msg);
location.href = url;
</script>
</head>
</html>
물품 등록 완료 알림을 위해
alert.html 만들어봄
물품 등록 완료시
model으로 msg, url을 담은
alert페이지로이동
alert에서는 위에서 받은 msg와 url을 토대로 출력및 페이지 이동
(html에서 model로 받은 데이터를 사용하는 방법)
----------------------------------------------------------
테이블에 수정, 삭제버튼 만들기
itemlist a태그
table에 input
script에 폼 추가
script에 action 주소 쓸때
절대경로 만들기
form.setAttribute("action", "[[@{/item/deleteone.do}]]");
ROOT라는 프로젝트 경로 들고오기
선생님은 수정. 삭제 버튼 스크립트를 따로 줬지만 나는 스크립트를 하나로 합침.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>물품 목록</title>
</head>
<body>
<h3>물품 목록</h3>
<a th:href="@{/home.do}">홈으로(GET)</a>
<a th:href="@{/seller/seller.do}">판매자페이지로(GET)</a>
<!-- <a th:href="@{/seller/insertone.do">
<input type="button" value="추가하기">
</a> -->
<!-- <form id="form">
<button th:onclick="|javascript:deleteAction()|">일괄삭제</button>
</form> -->
<!-- onsubmit="return confirm('Do you really want to submit the form?');" -->
<!-- <form th:action="@{/item/updatedelete.do}" method="post" onsubmit="return confirm('Do you really want to submit the form?');"> -->
<form th:action="@{/item/updatedelete.do}" method="post">
<input type="submit" name="btn" value="일괄삭제" onclick='return confirm("삭제하시겠습니까?");'/>
<input type="submit" name="btn" value="일괄수정"/>
<a th:href="@{/item/insertone.do}">
<input type="button" value="추가하기" />
</a>
<div style="display: inline-block;">
</div>
<table border="1">
<tr>
<th>선택</th>
<th>물품 번호</th>
<th>물품명</th>
<th>내용</th>
<th>가격</th>
<th>수량</th>
<th>날짜</th>
<th>이미지</th>
<th>버튼</th>
</tr>
<!-- <p th:text="${list}"></p> -->
<!-- v-for= "(tmp,idx) of blist" -->
<tr th:each = "tmp,idx : ${list}">
<td><input type="checkbox" th:value="${tmp.no}" name="no"/></td>
<td th:text="${tmp.no}"></td>
<td th:text="${tmp.name}"></td>
<td th:text="${tmp.content}"></td>
<td th:text="${tmp.price}"></td>
<td th:text="${tmp.quantity}"></td>
<td th:text="${tmp.regdate}"></td>
<td><img th:src="${tmp.imageUrl}" style="width:30px" /></td>
<!-- <td th:text="${tmp.imageurl}"></td> -->
<!-- <td><img th:src="${tmp.imageUrl}" style="width:50px" /></td> -->
<td>
<input type="button"
th:onclick="|javascript:deleteupdateAction('1','${tmp.no}')|" value="수정" />
<input type="button"
th:onclick="|javascript:deleteupdateAction('2','${tmp.no}')|" value="삭제" />
</td>
</tr>
</table>
</form>
<script type="text/javascript">
const deleteupdateAction = ( i ,no ) => {
// console.log(typeof(i),i);
// console.log(typeof(no),no);
if(i == '1'){
confirm('수정할까요?')}
else if(i == '2'){
confirm('삭제할까요?')}
else{
console.log('i, no'+'오류')
return;
}
// <form action="" method="post">
const form = document.createElement("form");
form.setAttribute("action", "[[@{/item/deleteupdateone.do}]]");
form.setAttribute("method", "post");
const input1 = document.createElement("input");
input1.setAttribute("type", "text");
input1.setAttribute("name", "typeno");
input1.setAttribute("value", i);
// <input type="text" value="13" name="no"
const input2 = document.createElement("input");
input2.setAttribute("type", "text");
input2.setAttribute("name", "no");
input2.setAttribute("value", no);
form.appendChild(input1);
form.appendChild(input2);
document.body.appendChild(form);
form.submit();
}
</script>
</body>
</html>
controller
@PostMapping(value = "deleteupdateone.do")
public String UpdateDeletePOST(@RequestParam(name="no")Long no,
@RequestParam(name="typeno")Integer typeno){
// System.out.println("타입넘버"+typeno);
// System.out.println("딜리트넘버"+no);
Item item = new Item();
item.setNo(no);
if(typeno == 1){
// 수정페이지로 이동
// ArrayList<Long> noo = new ArrayList<>();
// noo.add(no);
List<Long> noo = new ArrayList<>();
noo.add(no);
httpSession.setAttribute("SESSION_NO", noo);
return "redirect:/item/update.do";
}
else if(typeno == 2){
// 삭제
itemService.deleteItemOne(item);
return "redirect:/item/itemlist.do";
}
return "redirect:/item/itemlist.do";
}
---------------------------------------------------------
홈화면 실시간 채팅
properties만들음
global.properties
mqtt.broker=ws://1.234.5.158:11884
mqtt.username=ds강의실
mqtt.password=ds강의실
board.pagenation.count=10
boot2022로 가서
// 사용자 정의 변수 속성값
@PropertySource("classpath:global.properties")
홈컨트롤러
@Value("${mqtt.broker}")
String broker;
@Value("${mqtt.username}")
String username;
@Value("${mqtt.password}")
String password;
화면 표기
// http://127.0.0.1:8080/ROOT/chat.do
@GetMapping(value = "/chat.do")
public String chatGET(Model model){
model.addAttribute("broker", broker);
model.addAttribute("username", username);
model.addAttribute("password", password);
return "chat";
}
chat.html작성
<!DOCTYPE html>
<html lang="ko" xmlns:th="http://www.thymeleaf.org"></html>
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>챗</title>
</head>
<body>
<div th:text="${broker}"></div>
<div th:text="${username}"></div>
<div th:text="${password}"></div>
<hr/>
<input type="text" placeholder="보낼내용입력" id="msg">
<input type="button" value="전송" th:onclick="|javascript:sendMessage()|"/>
<div id="output" style="width: 400px; border:1px solid #cccccc; padding:5px">
<div>
여기에 받은 내용 표시
</div>
</div>
<script src="https://unpkg.com/mqtt@4.3.7/dist/mqtt.min.js" type="text/javascript"></script>
<script type="text/javascript">
const state = {
// 자바 스크립트는 이렇게 변수를 씀
url : "[[${broker}]]",
client : '',
options : {
clean : true,
reconnectPeriod : 20000, // 20초
client : 'ds203_' + new Date().getTime(), // 고유값(로그인한 사람의 아이디)
username : "[[${username}]]",
password : "[[${password}]]",
},
qos : 0
}
try{
state.client = mqtt.connect(state.url, state.options);
// console.log(state.client);
state.client.on('connect', () =>{ // 콜백
console.log('connect success');
});
state.client.on('error', () =>{ // 콜백
console.log('connect error');
});
state.client.on('message', (topic, message) =>{ // 콜백
console.log(typeof(topic), topic);
console.log(typeof(message), JSON.parse(message));
// output.innerHTML += topic;
// output.outerHTML += ('<br/>'+topic+"=>"+JSON.parse(message).type + " " + JSON.parse(message).msg);
output.innerHTML = "<br/>" + topic + "=>" + message + output.innerHTML;
});
state.client.subscribe('ds606/#', {qos : state.qos}, (error, res)=> {
// 결과는 에러와 res 두개를 줌
if(error){
console.log('subscribe error', error);
return;
}
console.log('subscribe success', res);
})
}
catch(e){
console.log(e);
}
const sendMessage = () => {
const msg = document.getElementById('msg');
const payload = JSON.stringify({
type : 1,
msg : msg.value
});
if(state.client){
state.client.publish('ds606/ds203', payload, state.qos, error =>{
if(error){
console.error('sendmessage error', error);
return;
}
})
}
}
</script>
</body>
</html>
-mqtt용 라이브러리 src
<script src="https://unpkg.com/mqtt@4.3.7/dist/mqtt.min.js" type="text/javascript"></script>
javascript 전송 버튼 이제 제대로 알음
mqtt소통할때
//object -> string로 변경 => JSON.stringify(변경할오브젝트)
//string -> object로 변경 => JSON.parse(변경할문자)
parse를 쓰면 str -> obj 바뀜
stringify를 쓰면 obj -> str
변수 선언 다시 필요없이
JSON.parse(message) 이렇게 한번만 하면 바로 바뀌네
오후일과
aop
v - c - s
c앞에는 aop같은 것이 있음 크롬에서 aop를 통과한뒤 c로 들어옴
컨트롤러에 반복되는 많은 것들이 있는 것들을 aop로 필터해서 들어면
좋아짐
aop를 알아볼 것임
pom에 라이브러리 추가
<!-- aop -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
aop폴더 생성
LogAspect.java 생성
작성
package com.example.aop;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
import lombok.extern.slf4j.Slf4j;
@Component
@Aspect
@Slf4j
public class LogAspect {
// 방문하고자 하는 클래스 등록
// ex)com.example.controller패키지의 모든 Controller의 모든 메소드
// 를 가져와라
@Around( "execution(* com.example.controller.*Controller.*(..)) or execution(* com.example.service.*Service.*(..)) or execution(* com.example.repository.*Repository.*(..))" )
public Object printLog(ProceedingJoinPoint joinPoint) throws Throwable{
String name = joinPoint.getSignature().getDeclaringTypeName();
if(name.contains("Controller")){
log.info("Controller =>"+ name + "." +joinPoint.getSignature().getName() + "()");
}
else if(name.contains("Service")){
log.info("Controller =>"+ name + "." +joinPoint.getSignature().getName() + "()");
}
else if(name.contains("Repository")){
log.info("Controller =>"+ name + "." +joinPoint.getSignature().getName() + "()");
}
// 모든 컨트롤러, 서비스, 저장소의 공통적인 작업을 수행하는 곳!!
// 현재 페이지를 세션에 기록
// 세션 정보에 따라 이동하는 페이지를 설정
return joinPoint.proceed();
}
}
app에 추가
//컨트롤러, 서비스의 위치
@ComponentScan(basePackages = {
"com.example.controller", // view를 포함한 경우
"com.example.restcontroller", // vue.js
"com.example.service",
"com.example.aop"
} )
@EnableAspectJAutoProxy // aop사용
컨트롤러 이동시 나옴(log.info())
컨트롤러랑 서비스 같이 찍어봄(repository도 넣어줌) LogAspect.java
@Around( "execution(* com.example.controller.*Controller.*(..)) or execution(* com.example.service.*Service.*(..)) or execution(* com.example.repository.*Repository.*(..))" )
컨트롤러에 들어가는 공통적인 모듈
aop에서 다 처리해주고 controller로 넘아갈 수 있는게 큰 장점
생산성이 높아짐
로그인시 사용하기 좋음. 계속
중요중요중요중요중요중요중요중요중요중요중요중요중요중요중요중요중요중요중요중요중요중요중요중요중요중요중요중요중요중요중요중요중요중요중요중요중요중요중요중요중요중요중요중요중요중요중요중요중요중요중요중요중요중요중요중요
나중에 오류잡는거 다 이걸로 잡음
'spring boot' 카테고리의 다른 글
57일차 로그인 로그아웃 security활용 (0) | 2022.09.16 |
---|---|
56일차 시험친날, boot프로젝트 생성 (0) | 2022.09.16 |
49일차 생략 Multiple submit in Single Form confirm (0) | 2022.09.02 |
48일차 개판 세션사용, 조회수 중복 세션으로 처리, item 일괄등록(이미지), footer (0) | 2022.08.31 |
47일차 수업 빼먹은 날(웹보드 보며 혼자 보충) (0) | 2022.08.31 |