2024. 8. 6. 13:58ㆍSpringboot-React
mysql
CREATE TABLE IF NOT EXISTS posts (
id INT AUTO_INCREMENT PRIMARY KEY,
title VARCHAR(255) NOT NULL,
content VARCHAR(255) NOT NULL,
image_url VARCHAR(255),
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
Post-Mapper.xml
<?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.kh.mapper.PostMapper">
<!-- 전체 게시글 보기 -->
<select id="findAll" resultType="com.kh.dto.Post">
select * from posts
</select>
<!-- post 게시글 테이블에 title = 제목 content = 내용 작성 -->
<insert id="insertPost" parameterType="com.kh.dto.Post">
insert into posts (title, content, image_url) values (#{title}, #{content}, #{imageUrl})
</insert>
</mapper>
PostService + PostServiceImpl
//PostService.java
package com.kh.service;
import java.util.List;
import org.springframework.web.multipart.MultipartFile;
import com.kh.dto.Post;
public interface PostService {
List<Post> findAll();
void insertPost(Post post);
//이미지 업로드를 도와주는 기능 목록 설정
void uploadImages(MultipartFile[] files, String title, String content);
}
//PostServiceImpl.java
package com.kh.service;
import java.io.File;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import com.kh.dto.Post;
import com.kh.mapper.PostMapper;
@Service
public class PostServiceImpl implements PostService{
@Autowired
private PostMapper mapper;
@Value("${file.upload-dir}")//application.properties에서 설정 가져와서 사용
private String uploadDir; // = C:/Users/user1/Desktop/saveImage
@Override
public List<Post> findAll(){
return mapper.findAll();
}
@Override
public void insertPost(Post post) {
mapper.insertPost(post);
}
@Override
public void uploadImages(MultipartFile[] files, String title, String content) {
//바탕화면에 이미지를 저장하고 불러올 폴더가 존재하는지 확인
File uploadDirFile = new File(uploadDir);
// 만약에 폴더가 존재하지 않을 경우
if(!uploadDirFile.exists()) {
System.out.println("폴더가 없으므로 폴더 새로 생성");
//mkdirs = 하위 폴더 모두 생성
if(!uploadDirFile.mkdirs()) {
throw new RuntimeException("폴더 생성 실패");
}
}
//이미지 이름 중복없이 저장할 수 있도록 설정
List<String> fileNames = null; //파일명이 여러개일 수 있기 때문에 fileNames = 파일이름들 리스트로 글자목록을 작성
try {
fileNames = List.of(files).stream().map(file -> {
//파일을 저장 폴더에 저장할 때 이미지에 랜덤으로 이름을 부여해서 저장
//UUID : 파일 이름이 겹치지 않도록 랜덤으로 이름 생성
String fileName1 = UUID.randomUUID().toString();
//랜덤으로 작성한 이름 뒤에 원본 이름을 붙이고 싶을 때 -> getOriginalFilename()
String fileName2 = UUID.randomUUID().toString() + file.getOriginalFilename();
//랜덤으로 작성한 이름과 원본 이름을 '_'로 구분짓고 싶을 때
String fileName3 = UUID.randomUUID().toString() + "_" + file.getOriginalFilename();
//폴더 안에 이미지들 저장하기
File df = new File(uploadDir + File.separator + fileName3);
//File.separator : 파일 경로 구분. window(\, /)랑 맥북(/) 모두 경로를 알아서 잡아줌
try {
file.transferTo(df);
}
catch (Exception e) {
throw new RuntimeException("파일 업로드 실패", e);
}
return fileName3;
}).collect(Collectors.toList());
}
catch(Exception e) {
e.printStackTrace();
}
//이미지 이름, 경로 설정울 바탕으로 DB에 넣어주기
Post post = new Post();
post.setTitle(title);
post.setContent(content);
post.setImageUrl(String.join(",", fileNames));
insertPost(post);
}
}
** UUID : 파일 이름이 겹치지 않도록 랜덤으로 이름 생성
** List.of(files).stream().map(file -> { }).collect(Collectors.toList());
- MultipartFile[] files : array 배열로 파일들 담기
- List.of(files) : 파일들 배열을 리스트(목록)로 변환
- stream() : 리스트나 배열같은 데이터를 하나씩 처리하는 기능
- collect(Collectors.toList()) : stream으로 가져온 이미지 데이터를 리스트로 정렬
이미지들(files) 에서 이미지를 한 개씩 담아오기(map) -> 이미지를 하나씩 가져옴(stream)
-> stream을 이용해서 가져온 이미지를 리스트로 모음(collect) -> 한번 더 리스트로 목록 변환(toList())
PostController
package com.kh.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import com.kh.dto.Post;
import com.kh.service.PostService;
@RestController
public class PostController {
@Autowired
private PostService postService;
//ResponseEntity = 데이터가 무사히 전달되는지 체크
//db에 저장된 게시글 내용, 이미지 가져오기
@GetMapping("/posts")
public ResponseEntity<List<Post>> findAll(){
List<Post> posts = postService.findAll();
return ResponseEntity.ok(posts);
}
//이미지 저장
@PostMapping("/gallery/upload")
public ResponseEntity<String> uploadImages(
@RequestParam("files") MultipartFile[] files,
@RequestParam("title") String title,
@RequestParam("content") String content) {
postService.uploadImages(files, title, content);
return ResponseEntity.ok("이미지 db 업로드 성공");
}
}
WebConfig
리액트 포트와 백엔드 포트가 제대로 연결될 수 있도록 설정
WebSocket 프론트와 백엔드가 서로 상호작용을 주기적으로 진행할 때 좀 더 안전하게 연결을 계속함을 설정
package com.kh.common.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebConfig implements WebMvcConfigurer{
//react가 이미지폴더 경로를 가져갈 수 있도록 허용
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/images/**")
.addResourceLocations("C:/Users/user1/Desktop/saveImage/"); //바탕화면에 지정한 이미지 경로
}
@Override
public void addCorsMappings(CorsRegistry registry) {
registry
.addMapping("/**")
.allowedOrigins("http://localhost:3000")
//.allowedOrigins("*")
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
.allowedHeaders("*");
}
}
.addMapping("/**")
.allowedOrigins("http://localhost:3000")
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
.allowedHeaders("*");
.allowedOrigins("http://localhost:3000") -> 해당 주소의
.addMapping("/**") -> 뒤에 오는 url api 주소를 모두 허용
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
-> http://localhost:3000/**로 들어오는 모든 요청 허용
.allowedHeaders("*") <head>정보에 들어갈 모든 요청 허용
'Springboot-React' 카테고리의 다른 글
프로필 사진 올리기 1 (0) | 2024.08.09 |
---|---|
이미지 여러개 올리기 2 (0) | 2024.08.06 |
네이버 로그인 2 (0) | 2024.07.30 |
네이버 로그인 1 (0) | 2024.07.30 |
mysql-react-springboot 연결하기 2 (0) | 2024.07.26 |