# [Java] JSPとServletの学習ノート

> JSPとServlet このノートに対応する動画は 《【SiKi学院JavaEE视频教程】JavaWeb第一季基础》 《【SiKi学院JavaEE视频教程】JavaWeb第二季进阶》 前書き 個人的に把握しているところでは、JSPはすでに引退間近の状況ですので、皆さんは深く追究せず、軽く触れる程度でよいです。 Servletについては深く理解する必要があります。これは…

- 公開日: 2019-11-16
- タグ: Java, Servlet
- HTML版を見る: https://bilibili.cat/ja/posts/java-jsp-servlet
- 中文からAI翻訳: https://bilibili.cat/posts/java-jsp-servlet

---

# JSPとServlet

> #### このノートに対応する動画は次です
>
> > [《【SiKi学院JavaEE视频教程】JavaWeb第一季基础》](http://www.sikiedu.com/course/214)  
> > [《【SiKi学院JavaEE视频教程】JavaWeb第二季进阶》](http://www.sikiedu.com/course/218)

> #### 前書き
>
> > 個人的に把握しているところでは、JSPはすでに引退間近の状況ですので、皆さんは深く追究せず、軽く触れる程度でよいです。  
> > Servletについては深く理解する必要があります。これは今後多くのフレームワークの基礎となります。

## ***フローチャートのコードを含みますので、専門的なMarkdownエディタでの閲覧をおすすめします（印象笔记でも可能です）。***

---

## JSPの基本構文

#### 導入

```jsp
<%@page import=""%>
```

#### コメント

```jsp
<%-- code --%>
```

#### 記述

```jsp
<% code %>
```

#### 式の定義

```jsp
<%! 成员变量 %>
```

#### タグの導入

> 一般的に、複数のWebページで重複する部分をインポートする際に使用できます。
>
> または

```xml
<jsp:include page="xxx.jsp"></jsp:include>
```

## 内部クラスとその常用メソッド

> #### out (== sou)
>
> > println()  
> > println() は出力に使用され、「=」で代用することもできます。
>
> #### request（ライフサイクルは1回のHTTP内のみ）
>
> > 1.  getParameter()  
> >     パラメータを取得
> > 2.  getRequestDispatcher(url).forward(request, response)  
> >     リクエスト転送 request\_do->login->client（パスの問題に注意が必要です）
> > 3.  setAttribute(key, content)/getAttribute(key)  
> >     値の受け渡し
> > 4.  getSession()  
> >     sessionオブジェクトを取得
> > 5.  getContextPath()  
> >     プロジェクトパスを取得し、相対パスに使用
>
> #### response
>
> > 1.  getWriter().println()  
> >     HTMLの先頭に書き込む
> > 2.  getWriter().append()  
> >     追記
> > 3.  sendRedirect(url)  
> >     リダイレクト request\_do->client->login
>
> #### session
>
> > setAttribute(key, content)/getAttribute(key)  
> > 値の受け渡し
>
> #### application（唯一のオブジェクト）
>
> > setAttribute(key, content)/getAttribute(key)  
> > 値の受け渡し
>
> #### page
>
> > \== thisキーワード
>
> #### pageContext （コンテナ）
>
> > 1.  getOut()  
> >     outオブジェクトを取得
> > 2.  getRequest()  
> >     req
> > 3.  getResponse()  
> >     resp
> > 4.  getServletContext()  
> >     app
> > 5.  getSession()  
> >     session

## Servlet

> フロー処理のみを行い、JSPとは分離します。  
> extend HttpServlet throw ~Exception  
> doGet(req, resp) と doPost(req, resp) をオーバーライドして使用します
>
> アノテーション@WebServlet(“url”)で位置づけます  
> web.xmlを使用して位置づけることもできます（プロジェクト作成時にnextをチェックすると自動作成できます）

```xml
<servlet>
<servlet-name>LoginServlet</servlet-name>
<servlet-class>
com.sikiedu.servlet.LoginServlet
</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>LoginServlet</servlet-name>
<url-pattern>/login_ do</url-pattern><!-- 访问路径-->
</servlet-mapping>
</servlet>
```

---

> #### ライフサイクル

![フローチャート 1](https://cos2.endcloud.cn/legacy/halo/java-jsp-servlet/mermaid-1.svg)

## EL式

> JSPの記述を簡略化し、コード量を減らし、可読性を最適化するために使用します。

#### 変数の取得

> 1.  $
> 2.  $
>
> （~はreq、session、applicationです）  
> （scopeの優先順位はreq、session、applicationです）
>
> ***通常は最初の形式を使用すればよいです***

#### クラス変数の取得

> $

#### mapとコレクションの取得

> ${map.key} and $

#### 演算

> ${±\*/}  
> ${> \< == || !}  
> $

#### 内部クラス

> $

## JSTLタグ

> JSPの記述をさらに簡略化し、コードの可読性を最適化します。  
> 現代のデータ駆動型フロントエンドフレームワークの構文の原型を備えています。  
> たとえばVue.js、Angular.jsなどです。

#### jarパッケージのダウンロード

> [ダウンロードリンク -> mvnrepository](https://mvnrepository.com/artifact/javax.servlet/jstl/1.2)

#### 導入

```xml
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
```

#### 値の定義

```xml
<c:set var="" value="" scope=""></c:set>
```

#### 値の削除

```xml
<c:remove var=""/>
```

#### 値の出力

```xml
<c:out value=""/>
```

#### 条件判定

```xml
<c:choose>
<c:when test="${condition}">code</c:when>
<c:otherwise>code</c:otherwise>
</c:choose>
```

#### ループ

```xml
<c:foreach var="i" begin="index1" end="index2">
code
</c:foreach>
<c:foreach items="${list}" var="x">${x.var}</c:foreach>
```

## JSON

> 正式名称は"JavaScript Object Notation"、  
> 軽量なデータ交換形式で、原型はJavaScriptのデータオブジェクトです。  
> [詳細を見る](https://www.json.org/json-zh.html)

## fastjson

> Alibaba製のオープンソースJava向けJSON操作ライブラリです。  
> [fastjsonの公式GitHub](https://github.com/alibaba/fastjson)

#### jarパッケージのダウンロード

> [ダウンロードリンク->mvnrepository](https://mvnrepository.com/artifact/com.alibaba/fastjson/1.2.62)

#### 導入

```java
import com.alibaba.fastjson.JSON
```

#### シリアライズ

```java
JSON.toJSONString(object);
```

#### デシリアライズ

```java
JSON.parseObject(String, object.class);
```

#### 配列のシリアライズ

```java
JSON.parseArray(String, object.class);
```

## ajax

> 正式名称は"Asynchronous Javascript And XML"、  
> 非同期リクエストによってWebページを更新せずにデータを更新する技術です。  
> ***これはJavaScriptの技術であり、Javaのものではありません。***

#### JQueryによる実装

```JavaScript
setInterval("callAjax()", 2000);//定时调用方法，参数单位为毫秒
function callAjax() {
    $.ajax({
        url: "${pageContext.request.contextPath }/ajaxrequest" ,
        type:"get",
        success: function(msg){
            }
});
$("input").blur(callAjax); //失焦响应方法
```

#### ネイティブJSによる実装

```JavaScript
function callAjaxByJS(){
    var xmlhttp = new XMLHttpRequest();
    xmlhttpopen("GET", endcodeURI("${pageContext.request.contextPath}/ajaxRequest?data=我是数据&"+Math.random()), true)
    xmlhttp.send();
    xmlhttp.onreadystatechange = function(){
    if( xmlhttp.readyState==4 && xmlhttp.status==200 ){
     //得到了服务器端的响应，4代表ajax响应已完成，200是http正常状态码
            $("#msg").append(xmlhttp.responseText);
        }
    }
}
```

## Filter

> class implement Filter

#### ライフサイクル

> コンストラクタ->init()->doFilter()->destory()

#### doFilter()

> chain.doFilter()はフィルタチェーンを起動します。

```java
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException{
    // TODO Auto-generated method stub
    // place your code here
    System.out.println("test1 filter before");
    // pass the request along the filter chain
    chain.doFilter(request, response);
    System.out.println("test1 filter after");
}
```

> web.xmlでフィルタ条件と順序を設定します。  
> また、@WebFilter(“/\*”)を使用して条件を設定することもできます。

```xml
<filter>
<filter-name>Test1Filter</filter-name><!-- 名称 -->
<filter-class>com.sikiedu.filter.Test1Filter</filter-class><!-- 类名 -->
</filter>
<filter>
<filter-name>Test2Filter</filter-name>
<filter-class>com. sikiedu.filter.Test2Filter</filter-class>
</filter>
<filter-mapping>
<filter-name>Test2Filter</filter-name>
<url-pattern>/*</url-pattern><!-- 过滤目录 -->
</filter-mapping>
<filter-mapping>
<filter-name>Test1Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
```

> web.xmlで設定した順序はresponse時に逆転します。  
> すなわち、chain.doFilter()の後に書かれたコードが実行されます。  
> 通常は使用する必要はありません。

#### 権限管理フィルタ

```xml
<filter>
<filter-name>AdminFilter</filter -name>
<filter-class>com.sikiedu.filter.AdminFilter</filter-class>
<!-- 继承自Filter的类-->
</filter>
<filter-mapping>
<filter-name>AdminFilter</filter-name>
<url-pattern>/admin/*</url-pattern>
<!-- 此处为路径，*是通配符，代表所有 -->
</filter-mapping>
```

#### リクエストフィルタ

> clientからJSPに対して発行されるリクエストの種類をフィルタリングします。  
> ***このリクエストはgetとpostを指すのではなく、JSPで定義されたリクエスト種別を指します。***

```xml
<filter>
<filter-name>DispatcherFilter</filter-name>
<filter-class>com.sikiedu.filter.DispatcherFilter</filter-class><!-- 继承自Filter的类-->
</filter>
<filter-mapping>
<filter-name>DispatcherFilter</filter-name>
<url-pattern>/dispatcher1. jsp</url-pattern>
<dispatcher>ERROR</dispatcher>
</filter-mapping>
```

> dispatcherの種類は全部で5つあり、よく使うのは最初の4つです。
>
> > 1.  REQUEST 通常リクエスト
> > 2.  FORWARD リクエスト転送
> > 3.  INCLUDE \<jsp:include>
> > 4.  ERROR エラーリクエスト
> > 5.  ASYNC 非同期リクエスト???
> >
> > #### エラーページ設定

```xml
<error-page>
<error-code>404</error-code>
<location>/dispatcher1.jsp</location>
</error-page>
```

## リスナー

> 1.  リスナーは1つのクラスであり、クラスを作成します
> 2.  リスナーインターフェースを実装します
>
> > 作成・破棄状態の監視  
> > ~initialized() ~Destroyed()
> >
> > > javax.servlet.ServletContextListener  
> > > HttpSessionListener  
> > > ServletRequestListener
> >
> > 属性監視  
> > ~Added() ~Replaced() ~Removed()
> >
> > > ServletContextAttributeListener  
> > > HttpSessionAttributeListener  
> > > ServletRequestAttributeListener
> >
> > Sessionバインディング監視
> >
> > > 1.  modelにHttpSessionBindingListenerをimplementsさせます
> > > 2.  valueBound()とvalueunbound()メソッドをオーバーライドします

> 3.  設定

```xml
<listener>
<listener-class>package.Listen-name.class</listener-class>
</listener>
```

> 4.  sessionのタイムアウト時間を設定します

```xml
<session-contig>
<session-timeout>1</session-timeout><!-- 单位为分钟-->
</session-config>
```

# 特殊な知識ポイント

## MVCアーキテクチャ

![フローチャート 2](https://cos2.endcloud.cn/legacy/halo/java-jsp-servlet/mermaid-2.svg)

## J2EE階層アーキテクチャ

![フローチャート 3](https://cos2.endcloud.cn/legacy/halo/java-jsp-servlet/mermaid-3.svg)

## シングルトンパターン

> コンストラクタを非公開にして、instanceを生成します。  
> よく使うオブジェクトを何度もnewすることを避けます。

```java
public static JDBCUtil instance = new JDBCUtil();
private JDBCUtil() {

}
```

## 相対パスと絶対パス

#### クライアントパス

> クライアントのアドレスバーまたはソースコード内に表示され、リクエスト可能です。  
> たとえば[およびアクセスするURL。](URL)

> 相対パス
>
> > 現在のURLディレクトリが存在するパスによって決定されます。
>
> 絶対パス
>
> > ホスト（ドメイン名）のルートパスによって決定されます。  
> > ***通常はcontextPathを加えてパスを正しく保ちます。***  
> > <u>&lt;%=request.getContextPath()%&gt;</u>  
> > または<u>${pageContext.request.contextPath}</u>

#### サーバー側パス

> JSP内部でのみ実行されます。  
> たとえば\<jsp:include page=“xxx.jsp”>またはリクエスト転送です。

> 相対パス
>
> > 現在のJSPファイルが存在するパスによって決定され、"xxx.jsp"のような形式です。
>
> 絶対パス
>
> > プロジェクトパスによって決定され、"/folder/xxx.jsp"のような形式です。  
> > ***プロジェクト名を加える必要はありません。***

#### ***実際の使用ではいずれも<u>絶対パス</u>を使用し、誤りを避けることをおすすめします。***

## 中国語パラメータの文字化け解決

> Stringでエンコーディングを設定

```java
System.out.println(new String(sex.getBytes("iso-8859-1"), "utf-8"));
```

> requestでエンコーディングを設定

```java
request.setCharacterEncoding("utf-8");
```

> responseでエンコーディングを設定

```java
resp.setContentType("text/html; charset=utf-8");
```

> ***最終手段、doFilterでグローバルにエンコーディングを設定***

```java
encoding = fConfig.getInitParameter("Encoding");
```

```xml
<!-- 在web.xml配置Encoding参数和filter-->
<filter>
<filter-name>EncodeFilter</filter-name>
<filter-class>com.sikiedu.filter.EncodeFilter</filter-class>
<init-param>
<param-name>Encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>EncodeFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
```

## シングルサインオン

> 1.  sessionManagerクラスを作成し、sessionの集合（hashmap実装）を構築します。
> 2.  session-attributeのaddedリスナーを通じて制御します。

```java
if(arg0.getName().equals("user")) {
    User u = (User) arg0.getValue();
    //判断是否有其他客户端已经登录
    if(Sess ionManager . sess ionMppE containsKey(u. getUsername())) {
        //获得另外一一个客户端的session
        HttpSession session = SessionManager.sess ionMap. get(u.getUsername());
        //把登录信息从这个客户端抹除
        session. removeAttribute("user");
    }
    SessionManager.sessionMap.put(u.getUsername(), arg0.getSession());
}
```

## あとがき

#### 次の学習

> 個人的にはSSMフレームワークを学習の方向とすることをおすすめします。  
> siki学院にも同様の講座があります。  
> SSHフレームワークは一部の面でやや遅れているため、状況に応じて検討してください。

#### 就職を希望する場合

> 個人的には、SSMフレームワークを理解した後に戻ってJavaの基礎を復習することをおすすめします。  
> 主に《Java核心技术》第1巻・第2巻を参考書とします。  
> 同時に、データ構造とアルゴリズムに関する基礎知識も学習する必要があります。

## お問い合わせ

#### GitHub

このノートが少しでもお役に立つと感じられたら、Starをいただけると嬉しいです。  
ここがこのノートのプロジェクトアドレスです：[GitHub](https://github.com/endcloud/JavaWeb_learn_siki)  
今後もここで関連コードとノートを更新します。

個人的な学習にはまだ不足があるため、ここでprを提出して私の誤りを訂正していただくこともできます。感謝いたします。

#### e-mail

また、メールでも私に連絡できます。  
私のメールアドレスは：endcloud@qq.com
