<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html>
<head>
<title>레시피 등록</title>
<link
href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css"
rel="stylesheet"
integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3"
crossorigin="anonymous">
<script
src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"
integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p"
crossorigin="anonymous"></script>
<style>
body{
margin: 0 auto;
}
</style>
</head>
<body>
<form action="/recipe/regist.do" method="post"
enctype="multipart/form-data">
<div class="container align-items-center">
<div class="container row align-items-center p-0" >
<div class="col-lg-7 container" >
<div class="form-floating">
<input type="text" class="form-control" id="" name="recipeName">
<label for="floatingInput">레시피 제목</label>
</div>
<br>
<div class="form-floating">
<input type="text" class="form-control" id="" name="recipeVideo">
<label for="floatingInput">유튜브 링크</label>
</div>
<div class="mt-5">
<label for="validationCustom04" class="form-label"><h5>카테고리</h5></label> <select
class="form-select" id="" name="recipeCategory" required>
<option selected disabled value="">카테고리 선택</option>
<option value="mael">식사</option>
<option value="relish">술안주</option>
<option value="dessert">간식</option>
<option value="drink">술/음료</option>
</select>
<div class="invalid-feedback">카테고리를 선택하세요</div>
<br>
<div class="col-lg-12 ">
<h5>해시태그</h5>
<div class="overflow-hidden">
<label class="w-25 float-start"><input class="form-check-input" type="checkbox" name="jmt" value="true"> JMT</label>
<label class="w-25 float-start"><input class="form-check-input" type="checkbox" name="healthy" value="true"> 건강한</label>
<label class="w-25 float-start"><input class="form-check-input" type="checkbox" name="goodSpicy" value="true"> 맛있게 매운</label>
<label class="w-25 float-start"><input class="form-check-input" type="checkbox" name="soSpicy" value="true"> 아주매운</label>
<label class="w-25 float-start"><input class="form-check-input" type="checkbox" name="sweet" value="true"> 달콤한</label>
<label class="w-25 float-start"><input class="form-check-input" type="checkbox" name="easy" value="true"> 간편한</label>
<label class="w-25 float-start"><input class="form-check-input" type="checkbox" name="full" value="true"> 든든한</label>
<label class="w-25 float-start"><input class="form-check-input" type="checkbox" name="party" value="true"> 파티용</label>
</div>
</div>
</div>
</div>
<div class="col-lg-5 container">
<div class="row col-lg-4 m-4">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-x-circle-fill float-end" onclick="mainPicDel()">
<path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM5.354 4.646a.5.5 0 1 0-.708.708L7.293 8l-2.647 2.646a.5.5 0 0 0 .708.708L8 8.707l2.646 2.647a.5.5 0 0 0 .708-.708L8.707 8l2.647-2.646a.5.5 0 0 0-.708-.708L8 7.293 5.354 4.646z"/>
</svg>
<label class="input-file-button float-start" for="input-file">
<img id="output" class="mx-auto " width="400px" height="270px" style="background-color: gray; border-radius: 10px;">
</label>
<input type="file" id="input-file" style="display: none"
accept="image/jpeg, image/png, image/jpg" name="mainPicture"
class="isFile" onchange="loadFile(event)" required="required" />
</div>
<div class="form-floating align-items-center">
<input type="text" class="form-control" id="" name="recipeTime">
<label for="floatingInput">소요시간</label>
</div>
</div>
<br>
<div class=" row m-0 mt-3 mb-3 p-0">
<div class="form-floating">
<input type="text" class="form-control" id="" maxlength="30"
name="recipeInfo" required="required"> <label
for="floatingInput"> 간단한소개 (30자 미만)</label>
</div>
</div>
<div class="row row-cols-lg-auto col-lg-12">
<div class="form-floating col-lg-3">
<input type="text" class="form-control" id="" maxlength="10"
name="material"> <label for="floatingInput">재료명</label>
</div>
<div class="form-floating col-lg-3">
<input type="text" class="form-control" id="" maxlength="10"
name="amount"> <label for="floatingInput">재료수량</label>
</div>
<div class="form-floating col-lg-3">
<input type="text" class="form-control" id="" maxlength="10"
name="material"> <label for="floatingInput">재료명</label>
</div>
<div class="form-floating col-lg-3">
<input type="text" class="form-control" id="" maxlength="10"
name="amount"> <label for="floatingInput">재료수량</label>
</div>
</div>
<div class="row row-cols-lg-auto col-lg-12 ">
<div class="form-floating col-lg-3">
<input type="text" class="form-control" id="" maxlength="10"
name="material"> <label for="floatingInput">재료명</label>
</div>
<div class="form-floating col-lg-3">
<input type="text" class="form-control" id="" maxlength="10"
name="amount"> <label for="floatingInput">재료수량</label>
</div>
<div class="form-floating col-lg-3">
<input type="text" class="form-control" id="" maxlength="10"
name="material"> <label for="floatingInput">재료명</label>
</div>
<div class="form-floating col-lg-3">
<input type="text" class="form-control" id="" maxlength="10"
name="amount"> <label for="floatingInput">재료수량</label>
</div>
</div>
<div class="row row-cols-lg-auto col-lg-12 ">
<div class="form-floating col-lg-3">
<input type="text" class="form-control" id="" maxlength="10"
name="material"> <label for="floatingInput">재료명</label>
</div>
<div class="form-floating col-lg-3">
<input type="text" class="form-control" id="" maxlength="10"
name="amount"> <label for="floatingInput">재료수량</label>
</div>
<div class="form-floating col-lg-3">
<input type="text" class="form-control" id="" maxlength="10"
name="material"> <label for="floatingInput">재료명
</label>
</div>
<div class="form-floating col-lg-3">
<input type="text" class="form-control" id="" maxlength="10"
name="amount"> <label for="floatingInput">재료수량</label>
</div>
</div>
</div>
<hr>
<div class="row container">
<div class="form-floating col-lg-6">
<input type="text" class="form-control" id="" maxlength="10"
name="recipeDescription" required="required"> <label
for="floatingInput">레시피 설명</label>
<!-- 설명에 쉼표를 넣었을때 배열로 만들지 않기위한 더미 value -->
<input type="text" name="recipeDescription" value="ab22bb" style="display:none">
</div>
<div class="row col-lg-6">
<input type="file" name="recipePicture" class="isFile"
accept="image/jpeg, image/png, image/jpg" onchange="imgCheck();">
</div>
<div class="form-floating col-lg-6">
<input type="text" class="form-control" id="" maxlength="10"
name="recipeDescription"> <label for="floatingInput">레시피
설명</label>
<!-- 설명에 쉼표를 넣었을때 배열로 만들지 않기위한 더미 value -->
<input type="text" name="recipeDescription" value="ab22bb" style="display:none">
</div>
<div class="row col-lg-6">
<input type="file" name="recipePicture" class="isFile"
accept="image/jpeg, image/png, image/jpg" onchange="imgCheck();">
</div>
<div class="form-floating col-lg-6">
<input type="text" class="form-control" id="" maxlength="10"
name="recipeDescription"> <label for="floatingInput">레시피
설명</label>
<!-- 설명에 쉼표를 넣었을때 배열로 만들지 않기위한 더미 value -->
<input type="text" name="recipeDescription" value="ab22bb" style="display:none">
</div>
<div class="row col-lg-6">
<input type="file" name="recipePicture" class="isFile"
accept="image/jpeg, image/png, image/jpg" onchange="imgCheck();">
</div>
<input type="submit" value="등록" onclick="checkMainPic();">
</div>
</form>
</div>
<script>
var loadFile = function(event) {
var output = document.getElementById('output');
output.src = URL.createObjectURL(event.target.files[0]);
output.onload = function() {
URL.revokeObjectURL(output.src) // free memory
};
imgCheck()
};
///// 이미지파일 체크 시작 ////
var imgFile = document.querySelectorAll('.isFile');
var fileForm = /(.*?)\.(jpg|jpeg|png|gif|bmp)$/i;
var fileSize;
function checkMainPic() {
if (imgFile[0].value == "") {
alert("대표사진은 필수입니다!");
}
};
function imgCheck() {
for (var i = 0; i < imgFile.length; i++) {
if (imgFile[i].value != "") {
if (!imgFile[i].value.match(fileForm)) {
alert("이미지 파일만 업로드 가능");
imgFile[i].value = "";
}
}
}
};
/////이미지 확장자 체크 종료///
function mainPicDel(){
imgFile[0].value = "";
output.removeAttribute('src');
}
</script>
</body>
</html>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>레시피 리스트</title>
</head>
<body>
<table>
<tr>
<td>레시피번호</td>
<td>레시피이름</td>
<td>레시피사진</td>
<td>레시피설명</td>
</tr>
<c:forEach items="${rList}" var="recipe" varStatus="i">
<tr>
<td>${recipe.recipeNo }</td>
<td><a href="/recipe/detail.do?recipeNo=${recipe.recipeNo }">${recipe.recipeName }</a></td>
<td><img src="/resources/recipeImg/${recipe.mainPicRename }"></td>
<td>${recipe.recipeInfo }</td>
</tr>
</c:forEach>
</table>
</body>
</html>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>${recipe.recipeName }</title>
</head>
<body>
<h1>${recipe.recipeName }</h1>
<img src="/resources/recipeImg/${recipe.mainPicRename }">
<br>
<c:if test="${rTag.jmt }">
#jmt
</c:if>
<c:if test="${rTag.healthy }">
#건강한
</c:if>
<c:if test="${rTag.goodSpicy }">
#맛있게 매운
</c:if>
<c:if test="${rTag.full }">
#든든한
</c:if>
<c:if test="${rTag.soSpicy }">
#아주 매운
</c:if>
<c:if test="${rTag.sweet }">
#달콤한
</c:if>
<c:if test="${rTag.easy }">
#간편한
</c:if>
<c:if test="${rTag.party }">
#파티용
</c:if>
<br> 작성자 : ${recipe.memberEmail } ${recipe.recipeInfo }
<c:forEach items="${rmList}" var="rmList">
재료: ${rmList.material}, 수량 : ${rmList.amount}
조리 시간 ${recipe.recipeTime }
<br>
</c:forEach>
<c:forEach items="${rsList }" var="rsList">
<c:if test="${rsList.recipePicRename ne null }">
<img src="/resources/recipeImg/${rsList.recipePicRename }">
<br>
</c:if>
${rsList.recipeDescription }
<br>
</c:forEach>
<!-- 비디오 주소를 입력했을때만 : 비디오 출력이 안되서 입력시에 유효성 검사 필요-->
<c:if test="${recipe.recipeVideo ne null }">
<iframe width="560" height="315" src="${recipe.recipeVideo}" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
</c:if>
</body>
</html>
/**
* 레시피 등록 컨트롤러
* @param recipe
* @param rStep
* @param rMaterial
* @param rTag
* @param mv
* @param mainPicture
* @param recipePicture
* @param session
* @param request
* @return
*/
@RequestMapping(value = "/recipe/regist.do", method = RequestMethod.POST)
public ModelAndView registRecipe(@ModelAttribute Recipe recipe, @ModelAttribute RecipeStep rStep,
@ModelAttribute RecipeMaterial rMaterial, @ModelAttribute RecipeTag rTag, ModelAndView mv,
@RequestParam(value = "mainPicture", required = false) MultipartFile mainPicture,
@RequestParam(value = "recipePicture", required = false) List<MultipartFile> recipePicture,
HttpSession session, HttpServletRequest request) {
try {
// 레시피 전달
// 사진 저장코드
String mainPic = mainPicture.getOriginalFilename();
if (!mainPic.equals("")) {
String root = request.getSession().getServletContext().getRealPath("resources");
String savePath = root + "\\recipeImg"; // 내가 저장할 폴더
File file = new File(savePath); // 파일 객체 만들기
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
String mainPicRename = sdf.format(new Date(System.currentTimeMillis())) + "."
+ mainPic.substring(mainPic.lastIndexOf(".") + 1);
if (!file.exists()) { // 경로에 savePath가 없을땐
file.mkdir(); // 경로 만들기
}
mainPicture.transferTo(new File(savePath + "\\" + mainPicRename));// 파일을 buploadFile경로에 저장
recipe.setMainPic(mainPic);
recipe.setMainPicRename(mainPicRename);
}
// 사진 저장 코드 종료
int result = rService.registRecipe(recipe);
// 레시피 재료 리스트 만들어서 전달하기
ArrayList<RecipeMaterial> rmList = new ArrayList<RecipeMaterial>();
String amount[] = rMaterial.getAmount().split(",");
String material[] = rMaterial.getMaterial().split(",");
for (int i = 0; i < material.length; i++) {
// 재료나 수량이 비어있지 않을때만 List에 저장
if (!amount[i].equals("") && !material[i].equals("")) {
RecipeMaterial rMaterialOne = new RecipeMaterial();
rMaterialOne.setAmount(amount[i]);
rMaterialOne.setMaterial(material[i]);
rMaterialOne.setMaterialOrder(i + 1);
rmList.add(rMaterialOne);
}
}
int result1 = rService.registMaterial(rmList);
// 레시피 순서 리스트 만들어서 전달하기
ArrayList<RecipeStep> rsList = new ArrayList<RecipeStep>();
String arrDescription[] = rStep.getRecipeDescription().split(",ab22bb,");
//더미 value까지 배열을 나누는것으로 인식해서 사용자가 ,를 입력했을때 정상적으로 table에 저장되게 한다
arrDescription[arrDescription.length-1] = arrDescription[arrDescription.length-1].replace(",ab22bb", "");
//배열의 마지막은 ,가 안들어가기때문에 더미vlaue 배열값으로 인식한다, ,가 없는 더미value를 삭제 해주는 코드
///// 레시피 순서 사진 저장코드
for (int i = 0; i < recipePicture.size(); i++) {
String recipePic = recipePicture.get(i).getOriginalFilename();
String recipePicRename = "";
if (!recipePic.equals("")) {
String root = request.getSession().getServletContext().getRealPath("resources");
String savePath = root + "\\recipeImg"; // 내가 저장할 폴더
File file = new File(savePath); // 파일 객체 만들기
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
recipePicRename = sdf.format(new Date(System.currentTimeMillis())) + "stepImg" + i + "."
+ recipePic.substring(recipePic.lastIndexOf(".") + 1);// 동시에여러사진이올라가기에 이름에 순서추가해줌
if (!file.exists()) { // 경로에 savePath가 없을땐
file.mkdir(); // 경로 만들기
}
recipePicture.get(i).transferTo(new File(savePath + "\\" + recipePicRename));// 파일을 buploadFile경로에 저장
///// 여기까지 사진 저장코드/////
}
// 여기서부터 레시피 step 테이블에 저장할 값 List화 시키는 코드
RecipeStep rStepOne = new RecipeStep();
if (i < arrDescription.length) {
if (!arrDescription[i].equals("")) {
rStepOne.setRecipeDescription(arrDescription[i]);
}
}
rStepOne.setRecipePic(recipePic);
rStepOne.setRecipePicRename(recipePicRename);
rStepOne.setRecipeOrder(i + 1);
rsList.add(rStepOne);
System.out.println(i);
}
int result2 = rService.registStep(rsList); // 레시피 순서저장 코드 종료
// 레시피 태그 true false로 받음
int result3 = rService.registTag(rTag);
mv.setViewName("redirect:/recipe/recipeList.do");
} catch (Exception e) {
mv.addObject("msg", e.getMessage());
mv.setViewName("common/error");
}
return mv;
}
// 레시피 순서 리스트 만들어서 전달하기
ArrayList<RecipeStep> rsList = new ArrayList<RecipeStep>();
String arrDescription[] = rStep.getRecipeDescription().split(",ab22bb,");
//더미 value까지 배열을 나누는것으로 인식해서 사용자가 ,를 입력했을때 정상적으로 table에 저장되게 한다
arrDescription[arrDescription.length-1] = arrDescription[arrDescription.length-1].replace(",ab22bb", "");
//배열의 마지막은 ,가 안들어가기때문에 더미vlaue 배열값으로 인식한다, ,가 없는 더미value를 삭제 해주는 코드
/**
* 레시피 리스트 전체 불러오기(임시)
* @param mv
* @param page
* @return
*/
@RequestMapping(value="/recipe/recipeList.do", method = RequestMethod.GET)
public ModelAndView RecipeList(ModelAndView mv) {
try {
List<Recipe> rList = rService.printRecipeList(0,0);
mv.addObject("rList", rList);
mv.setViewName("/recipe/recipeList");
}catch (Exception e) {
mv.addObject("msg", e.getMessage());
mv.setViewName("common/error");
}
return mv;
}
/**
* 디테일 레시피 보기
* @param recipeNo
* @param session
* @param mv
* @return
*/
@RequestMapping(value="/recipe/detail.do", method = RequestMethod.GET)
public ModelAndView viewRecipeStep(int recipeNo, HttpSession session, ModelAndView mv) {
try {
Recipe recipe = rService.printOneRecipe(recipeNo);
List<RecipeMaterial> rmList = rService.printOneRecipeMaterial(recipeNo);
List<RecipeStep> rsList = rService.printOneRecipeStep(recipeNo);
RecipeTag rTag = rService.printOneRecipeTag(recipeNo);
mv.addObject("recipe", recipe);
mv.addObject("rmList", rmList);
mv.addObject("rsList", rsList);
mv.addObject("rTag", rTag);
mv.setViewName("/recipe/recipeDetail");
}catch (Exception e) {
mv.addObject("msg", e.getMessage());
mv.setViewName("common/error");
}
return mv;
}
/**
* 레시피 리스트 출력
*/
@Override
public List<Recipe> printRecipeList(int currentPage, int limit) {
List<Recipe> rList = rStore.selectAllRecipe(currentPage, limit, session);
return rList;
}
/**
* 전체 레시피 출력
*/
@Override
public List<Recipe> selectAllRecipe(int currentPage, int limit, SqlSessionTemplate session) {
List<Recipe> rList = session.selectList("RecipeMapper.selectAllRecipe");
return rList;
}
<resultMap type="Recipe" id="recipeResultMap">
<id property="recipeNo" column="RECIPE_NO" />
<result property="recipeName" column="RECIPE_NAME" />
<result property="recipeInfo" column="RECIPE_INFO" />
<result property="mainPic" column="MAIN_PICTURE" />
<result property="insertDate" column="INCERT_DATE" />
<result property="recipeCategory" column="RECIPE_CATEGORY" />
<result property="recipeVideo" column="RECIPE_VIDEO" />
<result property="viewCount" column="VIEW_COUNT" />
<result property="memberEmail" column="MEMBER_EMAIL" />
<result property="updateDate" column="UPDATE_DATE" />
<result property="recipeStatus" column="RECIPE_STATUS" />
<result property="recommandCount" column="RECOMMAND_COUNT" />
<result property="mainPicRename" column="MAIN_PIC_RENAME" />
<result property="recipeTime" column="RECIPE_TIME" />
</resultMap>
<select id="selectAllRecipe" resultMap="recipeResultMap">
select * from recipe_tbl where RECIPE_STATUS = 'Y'
</select>
/**
* 상세 레시피, 레시피
*/
@Override
public Recipe printOneRecipe(int recipeNo) {
Recipe recipe = rStore.selectOneRecipe(recipeNo, session);
return recipe;
}
/**상세레시피 순서*/
@Override
public List<RecipeStep> printOneRecipeStep(int recipeNo) {
List<RecipeStep> rsList = rStore.selectOneRecipeDetail(recipeNo, session);
return rsList;
}
/**
* 상세 레시피 레시피 재료
*/
@Override
public List<RecipeMaterial> printOneRecipeMaterial(int recipeNo) {
List<RecipeMaterial> rmList = rStore.selectOneRecipeMaterial(recipeNo, session);
return rmList;
}
/**상세 레시피 태그*/
@Override
public RecipeTag printOneRecipeTag(int recipeNo) {
RecipeTag rTag = rStore.selectOneRecipeTag(recipeNo, session);
return rTag;
}
/**상세레시피*/
@Override
public Recipe selectOneRecipe(int recipeNo, SqlSessionTemplate session) {
Recipe recipe=session.selectOne("RecipeMapper.selectOneRecipe", recipeNo);
return recipe;
}
/**상세 레시피 순서*/
@Override
public List<RecipeStep> selectOneRecipeDetail(int recipeNo, SqlSessionTemplate session) {
List<RecipeStep> rsList = session.selectList("RecipeMapper.selectOneRStep", recipeNo);
return rsList;
}
/**상세재료*/
@Override
public List<RecipeMaterial> selectOneRecipeMaterial(int recipeNo, SqlSessionTemplate session) {
List<RecipeMaterial> rmList = session.selectList("RecipeMapper.selectOneRMaterial",recipeNo);
return rmList;
}
/**상세 태그*/
@Override
public RecipeTag selectOneRecipeTag(int recipeNo, SqlSessionTemplate session) {
RecipeTag rTag = session.selectOne("RecipeMapper.selectOneRTag", recipeNo);
return rTag;
}
<select id="selectOneRecipe" resultMap="recipeResultMap">
select * from recipe_tbl where RECIPE_NO = #{recipeNo} and RECIPE_STATUS = 'Y'
</select>
<resultMap type="RecipeMaterial" id="RecipeMaterialResultMap">
<id property="recipeNo" column="RECIPE_NO" />
<result property="materialOrder" column="MATERIAL_ORDER" />
<result property="material" column="MATERIAL" />
<result property="amount" column="AMOUNT" />
</resultMap>
<select id="selectOneRMaterial" resultMap="RecipeMaterialResultMap">
select * from recipe_material where RECIPE_NO = #{recipeNo}order by MATERIAL_ORDER
</select>
<resultMap type="RecipeTag" id="RecipeTagResultMap">
<id property="recipeNo" column="recipeNo" />
<result property="jmt" column="JMT" />
<result property="healthy" column="HEALTHY" />
<result property="goodSpicy" column="GOODSPICY" />
<result property="full" column="FULL" />
<result property="soSpicy" column="SOSPICY" />
<result property="sweet" column="SWEET" />
<result property="easy" column="EASY" />
<result property="party" column="PARTY" />
</resultMap>
<select id="selectOneRTag" resultMap="RecipeTagResultMap">
select * from recipe_tag where RECIPE_NO = #{recipeNo}
</select>
<resultMap type="RecipeStep" id="RecipeStepResultMap">
<id property="recipeNo" column="recipeNo" />
<result property="recipeOrder" column="RECiPE_ORDER" />
<result property="recipeDescription" column="RECIPE_DESCRIPTION" />
<result property="recipePic" column="RECIPE_PICTURE" />
<result property="recipePicRename" column="RECIPE_PIC_RENAME" />
</resultMap>
<select id="selectOneRStep" resultMap="RecipeStepResultMap">
select * from recipe_Step where recipe_no = #{recipeNo} order by RECIPE_ORDER
</select>
레시피 등록 폼은 절반정도 수정했다. 조금만 더 손보면 될것 같다.