7日目JSPサーブレット

41282 ワード

韓日

  • ライブラリ項目
  • プロジェクトのデフォルトページ設定
  • ページをヘッダー、ヘッダー、フッター
  • に分割
  • イメージの情報
  • をデータベースから取得する.
  • 逐行動表示画像
  • 個別の画像ページ-表示画像
  • 大文字画像名のみの最初の文字
  • DBに記憶するイメージスコア
  • イメージのスコアリング-オブジェクト(トランザクション)
  • を使用
  • 完全コード
  • 注意する。

  • jstlラベル<>の間にコメントを付けるとエラーが発生する可能性があります.注記するときに注意してください.
  • jstlを使用して現在のアイテムのアドレスを動的に入力すると<%=requestになります.getContextPath()%>ではなく${pageContext.request.contextPath}を使用します.
  • 」「内部書込み」「文字列」が必要な場合は、「外部」を「」に変更します.
    文字列は「」で囲まなければならないので、外部の「」を置き換える必要があります.
  • イメージセットアイテム


  • ファイル構造


  • データベース構造

  • プロジェクトのデフォルトページの設定


    web.xmlのwelcome-file-listタグの下にwelcome-fileタグを作成し、その間にページアドレスを入力します.
    WEB-INF/web.xml
    <welcome-file-list>
      <!-- 이미지 갤러리 프로젝트의 기본페이지를 controller.java(서블릿)로 설정 -->
      <welcome-file>gallery</welcome-file>
    </welcome-file-list>
    =>urlにhttp://localhost:ポート番号/プロジェクト名/と入力するとホームページのControllerとなります.servlet(このサーブレットのアドレスは「/Gallery」)
    Controller.java(servlet)
    @WebServlet("/gallery")
    public class Controller extends HttpServlet {
    	private static final long serialVersionUID = 1L;
    	
    	private Map<String, String> actionMap = new HashMap<>();
    	public Controller() {
    	// 컨트롤러 생성자 (처음 시작할 때 한번 실행). key-value로 한묶음
    		actionMap.put("home", "/home.jsp");
    		actionMap.put("image", "/image.jsp");
    		actionMap.put("rate", "/image.jsp");
    	// 여기서 넣어준 key값으로 아래 doGet메서드가 실행되었을 때 key값이 action에 저장되고, 그 action을 통해 value값을 조회해 해당 주소로 forward해주는거임
    	}
    
    	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    		// action parameter 불러오기
    		String action = request.getParameter("action");
    		// 만약 action이 없거나 actionMap에 초기값이 없으면 action에 home을 넣음
    		if(action == null || !actionMap.containsKey(action)) action = "home";
    		
    		// actionMap의 action값이 home이면 home.jsp페이지로, image면 image.jsp페이지로 이동
    		request.getRequestDispatcher(actionMap.get(action)).forward(request, response);
    	}
    
    	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    		// image.jsp에서 post방식으로 받은 parameter(action, image, rating 총 세 가지 속성의 각 값)를 doGet으로 처리
    		doGet(request, response);
    	}
    }
    「アドレス」ウィンドウにhttp://localhost:8090/ImageGallery/、すなわちwebと入力します.xmlで設定したように/galeryに移動します.アドレスウィンドウにはアドレスが表示されませんが、この移動もget方式です.
    したがって、/galeryで作成したジェネレータが実行されるとdoGet()メソッドも順次実行されます.
    1) private Map actionMap = new HashMap<>(); 作成キー値と値がStringのHashMapを使用します.
    2)コントローラ()メソッド(コントローラ作成者)は、最初に/ライブラリアドレスに移動したときに1回のみ実行し、1)作成した海図にkey-value値をペアで配置します.
    3−1)doGetメソッドは,要求と応答をパラメータとして実行する.
    request.getParameter(「アクション」)によって要求されたパラメータアクション属性の値を文字列アクション変数に格納します.
    3-2)if文を使用して、現在のactionの値がnull(最初の接続時にaction=null)である場合、またはactionMap内部にキーがない場合、actionを「home」に設定します.
    3-3)要求に格納されているアドレス(actionMap.get(action)=>actionに格納されているキー値、actionMapから一致する値を取得する)(要求と応答をパラメータとする)
    =>パラメータ付きで移動します.
    4)post方式でデータを受信するとdoPost()メソッドが実行され,現在作成されているメソッドはdoGetメソッドで受信したパラメータを直接処理する.

    ページをヘッダー、ホームページ、フッターに分割


    1つのページを必要な部分から別のjspファイルに切り取り、各ファイルを適切な場所にリンクします.
    たとえば、ヘッダー、ホームページ、フッターに分けると、ホームページの上部はヘッダーのimport、下部はフッターのimportになります.
    header.jsp
    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    <link rel="stylesheet" type="text/css" href="${pageContext.request.contextPath}/css/style.css">
    <title>${param.title}</title>
    </head>
    <body>
    
    <div class="headerWrapper">
    	<div class="header">
    		<!-- {}안의 코드는 현재 프로젝트의 경로를 의미함 -->
    		<img src="${pageContext.request.contextPath}/images/logo.png"/>
    		<span id="title"></span>
    	</div>
    </div>	
    <div class="content">
    =>parameterはtitleプロパティのvalue値をhomeとして受信します.jspで指定します.
    home.jsp
    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
    <%@ taglib uri="http://java.sun.com/jsp/jstl/sql" prefix="sql" %>
    <!-- JSTL로 import해줌 -->
    
    <!-- header.jsp의 title 값을 여기 value에 넣어서 지정해줌 -->
    <c:import url="header.jsp">	
    	<c:param name="title" value="Home"></c:param>
    </c:import>
    
    <!-- body태그 아래 들어갈 내용들. 자세한건 아래에 정리함. -->
    
    <!-- footer.jsp를 import해줌-->
    <c:import url="footer.jsp"></c:import>
    =>header importタグ間でjstlを使用してparameterのtitle属性にheaderとして値を設定します.jspがtitleプロパティをパラメータとしてロードできるようにする
    footer.jsp
    </div>
    <div id="footer">
    	<p>Copyright &copy; 2022 Busan_IT</p>
    </div>
    </body>
    </html>

    DBから画像情報を取得する


    ここで、アカウントidはroot、db名はwebshopである.
    1) context.xmlリソースの変更
    2)DBデータを使用するJSPファイルの上部
    <%@tagliburi="http://java.sun.com/jsp/jstl/sql"prefix="sql"%>を入力してsqlライブラリのリンクを保留
    META-INF/context.xml=>接続プール設定
    <?xml version="1.0" encoding="UTF-8"?>
    <Context>
    <Resource name="jdbc/webshop" auth="Container" type="javax.sql.DataSource"
                   maxActive="20" maxIdle="5" maxWait="10000"
                   username="계정id" password="계정비밀번호" driverClassName="com.mysql.jdbc.Driver"
                   url="jdbc:mysql://localhost:3306/webshop?useSSL=false"/>
    </Context>
    home.jsp
    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
    <%@ taglib uri="http://java.sun.com/jsp/jstl/sql" prefix="sql" %>
    <!-- header.jsp import하는 코드. 생략. -->
    
    <!-- dataSource의 값이 context.xml의 resource 와 같아야 함 -->
    <sql:setDataSource var="ds" dataSource="jdbc/webshop" />
    
    <!-- 여기에 sql로 DB에 쿼리를 날려 값을 받아온 후 이미지를 나열하는 코드 작성 -->

    画像を行単位で動的に表示


    home.jsp
    <!-- DB에서 전체이미지를 id순으로 검색해 이 결과를 results에 배열로 저장한다. -->
    <sql:query var="results" dataSource="${ds}" sql="select * from images order by id" />
    
    <!-- results에는 쿼리 실행결과가 저장되고 이것을 results.rows로 받아 한줄씩 row로 반복 -->
    
    <!-- 경로(contextPath)/pics/사진이름.jpg 를 동적(Dynamic)으로 생성 -->
    
    <!-- 한 행(8개)씩 변수 image에 저장. 갯수를 바꾸고싶으면 tablewidth의 value값 8을 다른 숫자로 바꿈 -->
    <!-- 변수 picName(사진이름.확장자)을 만들어 이미지의 경로지정에 활용 -->
    
    <table class="images">
    <c:set var="tablewidth" value="8"></c:set>
    <c:forEach var="image" items="${results.rows}" varStatus="row">
    	
    	<c:if test="${row.index % tablewidth == 0}"><tr></c:if>
    	<c:set var="picName" scope="page" value="${image.stem}.${image.image_extension}"/>
    	<td>
    		<c:url value="/gallery?action=image&image=${image.id}" />
    		<a href="<c:url value="/gallery?action=image&image=${image.id}" />">
    			<img src="${pageContext.request.contextPath}/pics/${picName}">
    		</a>
    	</td>
    	
    	<c:if test="${row.index+1 % tablewidth == 0}"></tr></c:if>
    </c:forEach>
    <!-- index번호가 8의 배수이면 tr이 열리고 td가 반복된 후 7의 배수가 되면 td의 반복을 멈추고 tr이 닫힘 => 한 행의 이미지가 8개가 됨 -->
    </table>
    =>picName変数の値は、動的に設定されたパスを介して「画像名.拡張子」をaラベルにリンクします.(jstlを使用してデータベースに格納された特定の属性を受信する値は${image.id}=>画像名,${image.image extension}=>画像拡張子である.

    排他画像ページ-画像を表示


    home.jsp
    <a href="<c:url value="/gallery?action=image&image=${image.id}" />">
    	<img src="${pageContext.request.contextPath}/pics/${picName}">
    </a>
    =>aタグのhrefを各画像のidに対応するリンクとして指定する.
    質問をする.なぜこのリンクでjspに移動しますよね?これは各画像へのリンクだけではありませんか?それはイメージを高めるしかないのではないでしょうか.
    答えurl valueは、aタグのhref値をgetで移動します.
    すなわち、現在クリックしている画像のid値を使用して、/ライブラリにナビゲートします.
    コントロールサーバの基本ジェネレータでactionMapに予め配置されている3つのキー値の同じ値を検索し、対応するvalueアドレスに移動するdoGetメソッドが作成されました.
    したがって,aタグからインポートしたパラメータはaction属性の値(image)を問合せ,対応する値/imageとする.jspで転送します.

    画像名の最初の文字のみを大文字で表す


    写真名を印刷するときは、最初の文字を大文字にし、残りの文字を小文字にします.
  • fn:toUpperCase()、fn:toLowerCase():各関数は大文字と小文字で表されます
  • fn:substring():関数
  • は、文字列を1つずつ遮断し、インデックスを確立するために使用されます.
  • fn:substring(属性名,0,1):インデックス0から最初の(最初の文字)
  • のみを選択
  • fn:substring(属性名,1,-1):インデックス1番文字から-1番(最後の文字)まで
  • を選択
    image.jsp
    <c:out value="${fn:toUpperCase(fn:substring(image.stem, 0, 1))}${fn:toLowerCase(fn:substring(image.stem, 1, -1))}" />
    
    =>ここでイメージ.stemは画像名の属性です.(データベース内の画像名のフィールド名はstem)

    データベースに格納されている画像のスコアを取得


    データベース内の各画像の平均順位値を取得しますが、小数点以下の位置のみを取得します.
    _image.jsp
    <div class="rating">Rated: <fmt:formatNumber value="${average_ranking}" maxFractionDigits="1"/> (점수)</div>

    画像のスコアリング-オブジェクトの使用(トランザクション)


    DBを更新すると、一度に1つのタスクしか実行しないように変更されます.
    2人以上が同時に採点した場合、データベース情報の変更異常を防止できます.

    取引

  • DBの状態を変更するために実行される動作の単位.
  • トランザクションは、同時に実行またはキャンセルする必要があります.
  • 特定のセッションで動作するデータは、トランザクションが完了する前にロックされ、他のセッションで動作できません.
  • トランザクションは一度に1つのデータ・ソースのみを使用するため、トランザクション・ラベルにオペレーション・コードを配置するには、受信データ・ソースの変数を作成し、その変数を使用する必要はありません.
  • 2人以上が同時に採点された場合は、更新にエラーが発生しないようにトランザクションを使用します.
    image.jsp
    <!-- 트랜젝션이 사용될때는 데이터소스가 하나밖에 없으므로 하나의 트랜젝션 안에 코드를 짜면 변수를 만들어 거기에 저장하고 사용하는 과정이 필요없음 -->
    <sql:transaction dataSource="jdbc/webshop">
    
    <!-- 여기서 param.image는 사진을 눌렀을 때 id가 넘어온 값임. 즉 ?에 id가 들어감 -->
    <!-- 질문. 근데 이러면 results에는 id에 해당하는 하나의 값만 들어가는거 아닌가?? => 맞음. 하나의 값만 변수 results에 저장됨 -->
    <sql:query var="results" sql="select * from images where id=?">
    	<sql:param>${param.image}</sql:param>
    </sql:query>
    <!-- id로 값을 찾기때문에 한 개만 선택됨 -->
    
    <!-- results는 위에서 클릭한 이미지의 id에 해당하는 하나의 값만 가졌지만 results가 원래 배열이기때문에 배열의 가장 첫번째 값인 하나만 변수 image에 저장됨 -->
    <c:set var="image" scope="page" value="${results.rows[0]}"></c:set>
    <c:set var="picName" scope="page" value="${image.stem}.${image.image_extension}"/>
    <c:set var="average_ranking" scope="page" value="${image.average_ranking}"/>
    <!-- 이미지의 이름과 점수를 각각 picName, average_ranking 변수에 저장함 -->
    
    <!-- /gallery에서 받아온 action이 "rate"이면 rankings와 average_ranking을 업데이트한다 -->
    <c:if test='${param.action == "rate"}'>
    	<c:set scope="page" var="newRating" value="${(image.average_ranking*image.rankings + param.rating)/(image.rankings + 1)}"/>
    	<c:set scope="page" var="average_ranking" value="${newRating}" />
    	<sql:update sql="update images set average_ranking=?, rankings=? where id=?" >
    		<sql:param>${newRating}</sql:param>
    		<sql:param>${image.rankings + 1}</sql:param>
    		<sql:param>${param.image}</sql:param>
    	</sql:update>
    </c:if>
    <!-- (image.average_ranking*image.rankings + param.rating)/(image.rankings + 1) => (매긴점수*매긴횟수)+내가방금매긴점수 / 점수를 매긴 총 횟수(방금 내가 매겼으니 +1해주는것) -->
    <!-- var="average_ranking" value="${newRating}"은 새로 바뀐 평균점수를 이전에 표시하던 평균점수변수에 덮어씌운것(덮어씌워 업데이트함) -->
    <!-- sql:update아래에 있는 sql:param들은 순서대로 sql문의 ?에 들어간다 -->
    
    </sql:transaction>
    採点を取引と書くと、同時に複数の人が採点しても、順次平均点が適用されます.

    =>未採点時の初期画面

    =>5分後、スコアが更新されました

    完全なコード


    後で追加します.