카테고리 없음

#102. React DB와 조회 작성 삭제, 서버 여러 개 관리

열하나요 2023. 11. 30. 10:52

Controller

package com.kh.spring.idol.controller;

import java.nio.charset.Charset;
import java.util.List;

import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import com.kh.spring.idol.model.service.IdolService;
import com.kh.spring.idol.model.vo.Idol;

import lombok.RequiredArgsConstructor;

@CrossOrigin("*")
@RestController
@RequiredArgsConstructor
public class IdolController {
	
	@GetMapping("/idols")
	public ResponseEntity<List<Idol>> selectIdols() {
		List<Idol> idolList = idolService.selectIdols();
		//System.out.println(idolList);
		HttpHeaders header = new HttpHeaders();
		header.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
		return new ResponseEntity<List<Idol>>(idolList, header, HttpStatus.OK);
	}
	
	// ResponseEntity => 반환할 때 쓰는 데이터 타입
	// produces에 담았던 아이들은 원래 header에 들어가는 것들
	// 이게 contentType 정하는 건데 HttpHeaders로 세팅할 수 있음
	
	// Post방식을 쓰면 헤더가 아닌 바디에 데이터가 들어옴 
	// RequestBody를 이용하여 커맨드객체 방식을 쓸 수 있음
	@PostMapping("/idol")
	public ResponseEntity<String> insertIdol(@RequestBody Idol idol) {
		//System.out.println(idol);
		String result = idolService.insertIdol(idol) != 0 ? "success" : "fail";
		HttpHeaders header = new HttpHeaders();
		header.setContentType(new MediaType("text", "html", Charset.forName("UTF-8")));
		return new ResponseEntity<String>(result, header, HttpStatus.OK);
	}
	
	// 업데이트 put매핑
	// 삭제 delete매핑
	@DeleteMapping("/idol/{id}")
	public ResponseEntity<String> deleteIdol(@PathVariable(name="id") String id) {
		System.out.println(id);
		String result = idolService.deleteIdol(id) != 0 ? "success" : "fail";
		HttpHeaders header = new HttpHeaders();
		header.setContentType(new MediaType("text", "html", Charset.forName("UTF-8")));
		return new ResponseEntity<String>(result, header, HttpStatus.OK);
	}

}

 

 

import { useEffect, useState } from "react";
import IdolDetail from "./IdolDetail";
import IdolMain from "./IdolMain";
import axios from 'axios';
import Button from "react-bootstrap/esm/Button";


const IdolInfo = props => {

    /*
    console.log(props);
    console.log(props.idolList[0]);
    const [idol1, idol2, idol3] = props.idolList;
    */

    // const idolList = props.idolList;
    // console.log(idolList);

    /*
    const idol1 = props.idolList[0];
    const idol2 = props.idolList[1];
    const idol3 = props.idolList[2];
    */

    const [idolList, setIdolList] = useState([]);

    const [nameValue, setNameValue] = useState('');
    const [memberValue, setMemberValue] = useState('');
    const [songValue, setSongValue] = useState('');
    const [imageValue, setImageValue] = useState('');
    // 초기값은 반드시 넣어준다 => 숫자는 0, 문자열은 '', 배열은 []
    // 안넣으면 undefined
    const [scriptValue, setScriptValue] = useState('');

    const inputName = e => {
        // console.log('진짜임?');
        setNameValue(e.target.value);
    }
    const inputMember = e => {
        setMemberValue(e.target.value);
    }
    const inputSong = e => {
        setSongValue(e.target.value);
    }
    const inputImage = e => {
        setImageValue(e.target.value);
    }
    const inputScript = e => {
        setScriptValue(e.target.value);
    }

    const [flag, isFlag] = useState(false);

    const addIdol = () => {

        // 빈문자열이면 Falsy한 값 => 조건으로 사용
        if(nameValue && memberValue && songValue && imageValue){

            //const ids = idolList.map(i => i.id); 

            //console.log(Math.max(...ids)); // ...은 스프레드문법 => 배열안의 요소들을 쫙 펼쳐줌

            const idol = {
                //id : Math.max(...ids) + 1,
                name : nameValue,
                member : memberValue,
                song : songValue,
                image : imageValue,
                description : scriptValue
            }
            // console.log(idol);
            // idolList.push(idol); => 스페이스라도 눌러야 뜸
            //let copyArr = [...idolList, idol];
            //console.log(copyArr);
            //setIdolList(copyArr);

            axios.post('/spring/idol', idol)
                 .then(result => {
                    //console.log(result); => data가 success
                    
                    if(result.data == 'success'){
                        isFlag(!flag);
                    }
                 });

            setNameValue('');
            setMemberValue('');
            setSongValue('');
            setImageValue('');
            setScriptValue('');



        }
        else{
            alert('모든 항목을 입력해 주세요!!');
        }
    }


    useEffect(() => {
        axios.get('/spring/idols')
             .then(result => {
                //console.log(result);
                let copyArr = [...result.data];
                setIdolList(copyArr);
             })
    }, [flag]); // flag가 변경될 때마다 useEffect실행

    return ( 
        <>
            <IdolMain />

            {
                /*
                    <IdolDetail idol={idol1} />
                    <IdolDetail idol={idol2} />
                    <IdolDetail idol={idol3} />
                */
                    // for문ㄴㄴ
                    idolList.map((idol, index) => {
                        // console.log(idol);
                        // console.log(index);
                        // key는 안넘겨주면 오류가 뜨기 때문에 index로 넘겨줌
                        return (
                            <IdolDetail idol={idol} key={index} setList={setIdolList} list={idolList} flag={flag} isFalg={isFlag} />
                        )
                    })
            }
            
            <br/>

            <div id="enroll-form">
                <div>
                    <h3>그룹명</h3>
                    <textarea onChange={inputName} value={nameValue}></textarea>
                </div>
                <div>
                    <h3>인원수</h3>
                    <textarea onChange={inputMember} value={memberValue}></textarea>
                </div>
                <div>
                    <h3>대표곡</h3>
                    <textarea onChange={inputSong} value={songValue}></textarea>
                </div>
                <div>
                    <h3>사진주소</h3>
                    <textarea onChange={inputImage} value={imageValue}></textarea>
                </div>
                <div>
                    <h3>그룹설명</h3>
                    <textarea onChange={inputScript} value={scriptValue}></textarea>
                </div>
                
            </div>
            
            <Button onClick={addIdol} >아이돌을 추가하자</Button>

            <br/><br/><br/><br/><br/>


            
        </>
    );




}

export default IdolInfo;

 

import Button from "react-bootstrap/esm/Button";
import { useNavigate } from "react-router-dom";
import axios from 'axios';


const IdolDetail = props => {

    // console.log(props);
    const idol = props.idol;
    const setList = props.setList;
    const list = props.list;

    function deleteIdol(e){
        /*
        if(list.length != 1){
            const newIdolList = list.filter(idol => { return idol.id != e.target.id });
            //console.log(newIdolList);
            setList(newIdolList);
        }
        else {
            alert('다 없앨 순 없어요');
        }
        */

        //e.target.id
        axios.delete('/spring/idol/' + e.target.id)
             .then(result => {
                if(result.data == 'success'){
                    props.isFlag(!props.flag);
                }
             })

    };

    const navigate = useNavigate();

    const detailPage = () => {
        navigate('/detailpage', {state : idol});
    }

    return(

        <div className="info">
            <div>
                <img src={idol.image} alt="아이돌사진" onClick={detailPage} />
            </div>
            <div>
                <p>그룹명</p>
                <p>{idol.name}</p>
            </div>
            <div>
                <p>인원</p>
                <p>{idol.member}</p>
            </div>
            <div>
                <p>대표곡</p>
                <p>{idol.song}</p>
            </div>
            <div>
                <Button onClick={deleteIdol} id={idol.id} variant="dark">삭제하기</Button>

            </div>
        </div>


    )


}

export default IdolDetail;

 

 

 

 

서버를 두개 키려면 빵!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

 

1. 서버를 멈춘다.

2. 프로젝트 우클릭

3. Run As > Maven install

이클립스에서 도는 게 아니라 나가서 

4. target폴더에 spring-1.0.0-BUILD-SNAPSHOT.war이 생김

5. 그 파일C:\spring-workspace\springProject\target을 직접 찾아가서 잘라내기

6. C:\development\apache-tomcat-8.5.93\webapps 에 가서 붙여넣기

7. 파일명 수정 (spring으로 변경했음)

8. C:\development\apache-tomcat-8.5.93\conf 에서 server.xml열기

9. <Connector port="8001" protocol="HTTP/1.1".... => 8080을 8001로 변경

10. C:\development\apache-tomcat-8.5.93\bin 에서 startup.bat 실행

11. 그러면 서버를 굳이 안켜도 됨

12. localhost:8001/spring도 잘 돌아감