20211216投稿の削除
・投稿の削除
-昨日の投稿のアップロードと添付ファイルのアップロードに続いて、投稿を削除する機能を実現しました.
-まず昨日のビューです.jspセクションではjavaスクリプトで各ボタンを処理しました.もちろん、今日は何の修正もしていませんが、ボタンが押された時点で、どこまでメッセージを送信するかという程度は実現しています.
<script>
$(document).ready(function(){
<c:choose>
<c:when test="${empty hiBoard}">
alert("조회하신 게시물이 존재하지 않습니다.");
document.bbsForm.action = "/board/list";
document.bbsForm.submit();
</c:when>
<c:otherwise>
$("#btnList").on("click", function(){
document.bbsForm.action = "/board/list";
document.bbsForm.submit();
});
$("#btnReply").on("click", function(){
document.bbsForm.action = "/board/replyForm";
document.bbsForm.submit();
});
//수정 삭제 버튼은 boardMe가 Y일 때만 나타나야 함.
<c:if test="${boardMe eq 'Y'}">
$("#btnUpdate").on("click", function(){
document.bbsForm.action = "/board/updateForm";
document.bbsForm.submit();
});
$("#btnDelete").on("click", function(){
if(confirm("정말 삭제 하시겠습니까?") == true)
{
//정말 삭제하겠다고 했을 때, ajax 통신
$.ajax({
type:"POST",
url:"/board/delete",
data:
{
hiBbsSeq: <c:out value="${hiBoard.hiBbsSeq}" />
},
datatype:"JSON",
beforeSend:function(xhr){
xhr.setRequestHeader("AJAX", "true");
},
success:function(response){
if(response.code == 0)
{
alert("게시물이 삭제되었습니다.");
location.href = "/board/list";
}
else if(response.code == 400)
{
alert("파라미터 값이 올바르지 않습니다.");
//이동할 필요 없음
}
else if(response.code == 404)
{
alert("게시물을 찾을 수 없습니다.");
location.href = "/board/list";
}
else if(response.code == 405)
{
alert("사용자의 게시물이 아닙니다.");
location.href = "/board/list";
}
//메인글이 삭제되면 댓글은 어떻게 되냐를 설정해줘야 함.
else if(response.code == 999)
{
//댓글 존재하는 경우
alert("답변 게시물이 존재하여 삭제할 수 없습니다.");
//구현을 하는 방식에 따라 다름
}
else
{
alert("게시물 삭제 중 오류가 발생했습니다.");
}
},
complete:function(data){
icia.common.log(data);
},
error:function(xhr, status, error)
{
icia.common.error(error);
}
});
}
});
</c:if>
</c:otherwise>
</c:choose>
$("#btnUpdate").on("click",function(){
document.bbsForm.action = "/board/update";
document.bbsForm.submit();
});
});
</script>
-ここではif文ではなくJSTL+EL構文を用いて異なる状況に適した機能に分類しているが,実際にはif文を使用するのは不便である.まず,スクリプトタグ内の領域であるため,eclipseでは各タグの可視性が悪く,想像以上に言語が便利であるとは考えにくい.以前はjspのように<% %>
を使うほうが便利に見えます.deleteには表示するページがないので、非同期通信で削除したかどうかを判断するだけです.従って、ajax通信により、送信要求および受信応答のコード固有のalertメッセージが定義される.また、実装の方向は異なりますが、基本的には現在学習中のサイトで、投稿にコメントがあれば、投稿自体も削除されません.したがって,投稿にコメントが存在する場合,削除されないようにコメントを書く際に対応する部分をうまく処理してコメントを残す.-以前と同様に「/board/delete」を使用してコントローラを検索するため、コントローラを定義する必要があります.もちろん、実際には、クエリー文はコントローラよりも先に行われます.クエリーを行う前に、前述したように投稿にコメントがある場合は削除できないように処理されますので、まず投稿にコメントがあるかどうかを確認します.だから、まずこの部分に対するクエリーを書きました.
--댓글에 대한 쿼리 작성할 것.
--댓글이 있는데 삭제가 안되게 해야 함. 그런식으로 처리할 것임.
SELECT COUNT(HIBBS_SEQ) AS CNT
FROM TBL_HIBOARD
WHERE HIBBS_PARENT = 7;
-HIBBS PARENTの値が0ではなく1の場合、そのHIBBS SEQ番号の投稿、またはコメントにコメントや大きなコメントの意味があります.その場合、削除処理は避けるべきである.-対応するクエリ文が表示されます.xmlを定義します.
<!-- 게시물 삭제 시 답변 글 수 체크 시작 -->
<select id="boardAnswersCount" parameterType="long" resultType="int">
SELECT COUNT(HIBBS_SEQ) AS CNT
FROM TBL_HIBOARD
WHERE HIBBS_PARENT = #{value}
</select>
<!-- 게시물 삭제 시 답변 글 수 체크 종료 -->
-SQLdeveloperでは、ハードコーディング7の値は当然、クエリが正常に動作しているかどうかを判断するための値である.したがって、この値は#{value}
に変更される.-select文ですが、結果はcountが1つしかないため、クエリの値がいくらあるかが返されます.だから結果のタイプはintです.
-投稿を削除するクエリーを再作成します.
--게시물 삭제 쿼리 작성
DELETE FROM TBL_HIBOARD
WHERE
HIBBS_SEQ = 7;
-やっぱり.xmlで対応するクエリーを定義します.<!-- 게시물 삭제 시작 -->
<delete id="boardDelete" parameterType="long">
DELETE FROM TBL_HIBOARD
WHERE
HIBBS_SEQ = #{value}
</delete>
<!-- 게시물 삭제 종료 -->
-投稿を削除するには、添付ファイルを同時に削除する必要があります.もちろん、添付ファイルがなければ大丈夫ですが、添付ファイルがあれば一緒に削除するので、クエリー文を書きます.xmlファイルで定義します.--첨부파일도 같이 삭제해야됨
DELETE FROM TBL_HIBOARD_FILE
WHERE
HIBBS_SEQ = 7
;
-ここで疑問に思う部分は、添付ファイルがHIBBS SEQとFILE SEQの組み合わせキーのテーブルですが、なぜHIBBS SEQしか条件がないのですか?でも考えてみれば簡単です.FILE SEQは基本的に同じHIBBS SEQを持つもの(同じ投稿の添付ファイルに属する)を区別するために順番を与え、基本的にHIBBS SEQは同じ投稿であり、削除された場合、FILE SEQが何であれ、HIBBS SEQは同じ値を削除すべきである.そのため、HIBBS SEQに来れば良いのが条件です.<!-- 첨부 파일 삭제 시작 -->
<delete id="boardFileDelete" parameterType="long">
DELETE FROM TBL_HIBOARD_FILE
WHERE
HIBBS_SEQ = #{value}
</delete>
<!-- 첨부 파일 삭제 종료 -->
-添付ファイルを削除するクエリーが完了した場合、サービスで使用する抽象的な方法が定義されます. //게시물 삭제 시 답글 수 체크
public int boardAnswersCount(long hiBbsSeq);
//게시물 삭제
public int boardDelete(long hiBbsSeq);
//게시물 첨부파일 삭제
public int boardFileDelete(long hiBbsSeq);
-昨日、投稿添付ファイルを問い合わせる抽象的な方法を定義しましたが、サービスでは個別に定義されていません.BoardViewメソッドで使用したことがありますが、BoardViewではなく、添付ファイルを表示するためのサービスが別途作成されています.削除には不要な論理がたくさんあるからです.たとえば、クエリの数を増やすクエリ文.添付ファイルを問い合わせる必要がある場合は、後で添付ファイルをダウンロードする必要があります. //첨부파일 조회
public HiBoardFile boardFileSelect(long hiBbsSeq)
{
HiBoardFile hiBoardFile = null;
try
{
hiBoardFile = hiBoardDao.boardFileSelect(hiBbsSeq);
}
catch(Exception e)
{
logger.error("[HiBoardService] boardFileSelect Exception", e);
}
return hiBoardFile;
}
-投稿が存在するかどうかを確認するサービスと、投稿と添付ファイルをトランザクションするサービスを定義します. //게시물 삭제 시 답변 글 수 체크
public int boardAnswersCount(long hiBbsSeq)
{
int count = 0;
try
{
count = hiBoardDao.boardAnswersCount(hiBbsSeq);
}
catch(Exception e)
{
logger.error("[HiBoardService] boardAnswersCount Exception", e);
}
return count;
}
//게시물 삭제(첨부파일 있으면 함께 삭제)
@Transactional(propagation=Propagation.REQUIRED, rollbackFor=Exception.class)
public int boardDelete(long hiBbsSeq) throws Exception
{
int count = 0;
HiBoard hiBoard = hiBoardDao.boardSelect(hiBbsSeq);
//조회수 증가때문에 보드 뷰를 사용할 수 없음
if(hiBoard != null)
{
HiBoardFile hiBoardFile = hiBoardDao.boardFileSelect(hiBoard.getHiBbsSeq());
count = hiBoardDao.boardDelete(hiBoard.getHiBbsSeq());
if(hiBoardFile !=null)
{
//주소값 일치시키기
hiBoard.setHiBoardFile(hiBoardFile);
if(hiBoardDao.boardFileDelete(hiBbsSeq)> 0)
{
//FileUtil.getFileSeparator()얘는 역슬레시를 해주는 역할.
FileUtil.deleteFile(UPLOAD_SAVE_DIR + FileUtil.getFileSeparator()+hiBoardFile.getFileName());
}
}
}
return count;
}
-ここで重要なのは、トランザクションの部分です.添付ファイルが削除されていない場合は、投稿だけを削除することはできません.すべてロールバックします.それを一つのプロセスに組み合わせるので、こう書きます.さらに、FileUtil.getFileSeparator()
の部分は、/
または\
の機能を汎用モジュールによってファイルパスに組み込むことを少し理解していない可能性があります.各osには異なるファイルパス区切り記号があり、対応する汎用モジュールを介して現在のosに適したフォーマットで区切り記号を追加します.-コントローラがajax通信に対する応答を処理するために削除サービスを呼び出す.
@RequestMapping(value="/board/delete", method=RequestMethod.POST)
@ResponseBody
public Response<Object> delete(HttpServletRequest request, HttpServletResponse response)
{
Response<Object> ajaxResponse = new Response<Object>();
String cookieUserId = CookieUtil.getHexValue(request, AUTH_COOKIE_NAME);
long hiBbsSeq = HttpUtil.get(request, "hiBbsSeq", (long)0);
if(hiBbsSeq >0 )
{
//0보다 클 때가 게시물 존재
HiBoard hiBoard = hiBoardService.boardSelect(hiBbsSeq);
if(hiBoard != null)
{
if(StringUtil.equals(hiBoard.getUserId(), cookieUserId))
{
//쿠키 아이디랑 게시물 작성자와 같음.
try
{
if(hiBoardService.boardAnswersCount(hiBoard.getHiBbsSeq()) > 0)
{
//하이보드 객체에 있는 hiBbsSeq 값을 보냄. 근데 0보다 크면 게시물을 삭제하면 안됨. 댓글이 있다는 것.
ajaxResponse.setResponse(999, "Answer exist and cannot be deleted");
}
else
{
//댓글이 없음, 삭제 가능
if(hiBoardService.boardDelete(hiBoard.getHiBbsSeq()) >0)
{
//정상 삭제
ajaxResponse.setResponse(0, "Success");
}
else
{
//삭제 실패
ajaxResponse.setResponse(500, "Internal Server Error");
}
}
}
catch(Exception e)
{
logger.error("[HiBoardController] delete Exception", e);
ajaxResponse.setResponse(500, "Internal Server Error");
}
}
else
{
ajaxResponse.setResponse(405, "User Error");
}
}
else
{
ajaxResponse.setResponse(404, "Not Exist");
}
}
else
{
ajaxResponse.setResponse(400, "Bad Request");
}
return ajaxResponse;
}
-もちろん、前のページから来た場合、Cookie IDと投稿者のIDは同じだと判断できますが、最初から直接侵入してくる人を防ぐためには、Cookie IDと投稿者のIDが同じであることを確認してください.また,重要な部分はhiBoardService.boardAnswersCount(hiBoard.getHiBbsSeq())
であり,この部分は投稿にコメントがあるか否かを判断するクエリである.このセクションが0より大きい場合は、コメントが表示されるため、現在進行中のspringプロジェクトでは投稿を削除できません.・添付ファイルのダウンロード
-添付ファイルは、ボタンを単独で押したときに受け取るものではなく、添付ファイルを表示するaラベルをクリックしたときに受け取るものです.だからviewjspの添付ファイル部分ではget方式で要求が発行され、応答を受信する方式で実現される.
<!-- 첨부파일은 있을 때만 보여주면 됨 -->
<c:if test="${!empty hiBoard.hiBoardFile}">
<!-- GET방식으로 넘어감 -->
<a href="/board/download?hiBbsSeq=${hiBoard.hiBoardFile.hiBbsSeq}" style="color:#000;">[첨부파일]${hiBoard.hiBoardFile.fileOrgName}</a>
</c:if>
-href="/board/download?hiBbsSeq=${hiBoard.hiBoardFile.hiBbsSeq}"
のセクションを参照して、「/board/download」のコントローラを作成する必要があります. //첨부파일 다운로드
@RequestMapping("/board/download")
public ModelAndView download(HttpServletRequest request, HttpServletResponse response)
{
ModelAndView modelAndView = null;
long hiBbsSeq = HttpUtil.get(request, "hiBbsSeq", (long)0);
if(hiBbsSeq >0)
{
//값이 넘어왔다는 뜻
HiBoardFile hiBoardFile = hiBoardService.boardFileSelect(hiBbsSeq);
if(hiBoardFile != null && hiBoardFile.getFileSize() > 0)
{
//파일이 존재하면
//자바에서 제공하는 File객체라서 java.io임
File file = new File(UPLOAD_SAVE_DIR + FileUtil.getFileSeparator()+hiBoardFile.getFileName());
logger.debug("UPLOAD_SAVE_DIR : "+ UPLOAD_SAVE_DIR);
//os버전에 따라서 슬래쉬 혹은 역슬래쉬 해주는 기능이 getFIleSeparator()임
logger.debug("FileUtil.getFileSeparator() : "+ FileUtil.getFileSeparator());
logger.debug("hiBoardFile.getFileName() : "+ hiBoardFile.getFileName());
if(FileUtil.isFile(file))
{
//파일유틸에서 파일이 존재하는지 확인
modelAndView = new ModelAndView();
//어떤 클래스를 참조할 것이냐?
modelAndView.setViewName("fileDownloadView"); //servlet-context.xml 에서 정의한 것(fileDownloadView)
modelAndView.addObject("file", file);
modelAndView.addObject("fileName", hiBoardFile.getFileOrgName());
return modelAndView;
}
}
}
return modelAndView;
}
-実は、この部分はまだ100%理解しているとは言えないようです.まず、ModelAndViewオブジェクト、Fileオブジェクト、setView NameのFileDownloadViewを使用します.Javaファイル、Javaファイルを継承したAbstractView、FileDownloadView.JAvaで定義されているFileInputStreamオブジェクトやOutputStreamオブジェクトなどが突然現れ、まったく理解できません.-教授に単独で説明を求めたが、時間が迫っているため、基本的には提供されている機能なので、自分で探して、自分で探してほしいだけだ.まず、ModelAndViewは以前に使用したModelMapと似ています.ModelMapは、Viewでデータを使用するためにデータを持っているだけです.ただし、ModelAndViewはこれらのデータを格納し、どのビューに送信するかを決定します.上はFileDownloadViewです.Javaに送信され、環境変数のservlet-contextを設定します.xmlセクションは次のように定義されています.
<!-- 파일 다운로드 VIWE 시작 -->
<bean id="fileDownloadView" class="com.icia.web.view.FileDownloadView"/>
<!-- 파일 다운로드 VIWE 종료 -->
このパスに入ると、FileDownloadViewが表示されます.Javaが見つかります.-ファイル・オブジェクトを、ファイルを表すのではなく、ファイルへのパスまたは参照情報を持つ抽象オブジェクトと見なします.
ファイルをファイルオブジェクトから削除し、FileInputStreamオブジェクトとOutputStreamオブジェクトを介してファイルをバイト単位で出力できるようになりました.
FileInputStream : InputStream 클래스를 상속받은 자식 클래스, 하드 디스크 상에 있는 파일로부터 바이트 단위의 입력을 받는 클래스다. 출발 지점과 도착 지점을 연결하는 통로(스트림)을 생성한다.
FileOutputStream : OutputStream 클래스를 상속받은 자식 클래스, 파일로 바이트 단위의 출력을 내보내는 클래스.
출처: https://onlyfor-me-blog.tistory.com/193
-もう一つ、FileDownloadView.JAvaが引き継いだAbstractViewとは何ですか?-検索すると、viewResolverはコントローラの応答に応答するjspファイルを見つけ、AbstractViewと見なすことができます.
-だからそうです.jspを探しに行くのではなく、対応するビューでリクエストを処理するために中間で切り取ります.もちろん、まだ完全に理解していないので、このように言うのが正しいかどうか分かりません.
・明日は非睡眠授業です。
-この時間は毎日塾に通っていて、復習や整理運動をしていて、1時過ぎには寝ていて、また早く塾に行って勉強したいので、6時半に起きる強行軍をしていて、体力が少し落ちているようです.だからもともと明日も私たちのプロジェクトチームが出かける日ではありません.今日のチームプロジェクトの会議の結果も満足しています.体力の問題もあるので、明日は向こうで授業をしません.チームメンバーがいるので、エラーが発生しても一緒にデバッグできるので、一日も間違いがなければいいと信じています.
-また、プロジェクト会議と方向は、navigabarのメニューとサブメニューを整理し、表をある程度輪郭付けしているので、プロジェクトの開始は楽なようです.しかし、最も負担があるのはやはりプロジェクトで、私はこれがストレスの少ない始まりのようだと喜んでいます.整理が終わったら、今から復習して、プロジェクトに関することを整理して、運動してから寝なければなりません.今週はお疲れ様でした.明日また頑張りましょう.がんばれ!あ、もちろん、週末に遊ぶわけにはいきません.私自身!
Reference
この問題について(20211216投稿の削除), 我々は、より多くの情報をここで見つけました https://velog.io/@ysparkr841/20211216-게시글-삭제テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol