【狂神はJavaを語る】JavaWeb実践戦闘入門詳細メモ(完)

@[toc]7

1. 基本的な考え方

1.1. 序文

ウェブ開発:

  • web、ウェブページを意味します、www.baidu.com·
  • 静的ウェブ
    • html、css
    • 誰もが閲覧できるデータは決して変わりません。
  • ダイナミックウェブ
    • タオバオ、ほぼすべてのウェブサイト。
    • 全員に提供されるデータは常に変化し、誰もが異なる時間、異なる場所で異なる情報を見ます。
    • テクノロジースタック: サーブレット/JSP、ASP、PHP

1.2. Web アプリケーション Web アプリケーション:

ブラウザアクセスを提供するプログラム。

  • a.html、b.html... 複数の Web リソース これらの Web リソースは外部の世界からアクセスでき、外部の世界にサービスを提供します。
  • あなたがアクセスできるページやリソースはすべて、世界のどこかのコンピュータ上に存在します。
  • URL
  • この統合 Web リソースは、同じフォルダー、Web アプリケーション > Tomcat: サーバーに配置されます。
  • Web アプリケーションは複数の部分 (静的 Web、動的 Web) で構成されます。
    • html、css、js
    • jsp、サーブレット
    • Javaプログラム
    • 瓶パッケージ
    • 設定ファイル(プロパティ)

Webアプリケーションプログラムを作成した後、外部アクセスに提供する場合には、サービスを利用して一元管理する必要があります。

1.3. 静的ウェブ

  • *.htm、*.html はネットワーク ユーザーの背景であり、これらが常にサーバー上に存在していれば、直接読み取ることができ、ネットワークを必要とします。
  • 画像.png
  • 静的ウェブの欠点
    • Web ページは動的に更新できず、すべてのユーザーに同じページが表示されます。
      • カルーセル画像、クリック特殊効果: 擬似動的
      • JavaScript 【実際の開発では最もよく使われます】
      • VBスクリプト
    • データベースと対話できません (データを永続化できず、ユーザーは対話できません)

1.4. ダイナミックウェブ

ページが動的に表示されるため、「Webページの表示効果が人によって異なる」
画像.png
デメリット:

  • 動的 Web リソースをサーバーに追加する際にエラーが発生しました。バックグラウンド プログラムを書き直して再公開する必要があります。
    • ダウンタイムメンテナンスの利点:
  • Web ページは動的に更新できるため、すべてのユーザーに同じページが表示されるわけではありません。
  • データベースと対話できます (データの永続性: 登録、製品情報、ユーザー情報など)。
    画像.png

2.ウェブサーバー

2.1. 技術的な説明

ASP:

  • Microsoft: 中国で最初に普及したのは ASP です。
  • ·埋め込みVBスクリプト、HTML内のASP+COM。
  • ・ASP開発では、基本的にどのページにも数行の業務コードがあり、ページが非常にわかりにくくなります。
  • ・維持費が高い!
  • C#
  • IIS

php:

  • PHP の開発速度は非常に速く、機能は非常に強力で、クロスプラットフォームで、コードは非常にシンプルです (70%、WP)
  • 大量のトラフィックを伝送できない (制限)

jSP/サーブレット:
B/S; ブラウジングおよびサーバー C/S: クライアントおよびサーバー

  • サン社が中心となって推進するB/Sアーキテクチャ
  • Java 言語に基づく (すべての大企業または一部のオープンソース コンポーネントは Java で書かれています)
  • 3 つの高い問題の影響に耐えることができます。
  • 構文は ASP、ASP->JSP に似ており、市場力を強化します。

2.2. ウェブサーバー

サーバーは受動的操作であり、ユーザーのリクエストの一部を処理し、ユーザーに応答情報を提供するために使用されます。Microsoft
です
。ASP。Windows に付属の
Tomcat
画像.png
はBaidu プログラミング向けです。Tomcat
は Apache Software Foundation (Apache Software)財団)jakartaプロジェクトの中核プロジェクトであり、常に最新のサーブレットやJSPの仕様をTomcatに反映することができ、先進的な技術と安定した性能、そして無料であることから、溶岩愛好家に深く愛され、一部のソフトウェアで愛用されています。開発者に認められ、人気のある Web アプリケーション サーバーになりました。
Tomcat サーバーは、無料のオープン ソース Web アプリケーション サーバーです。軽量のアプリケーション サーバーです。中小規模のシステムや、同時アクセス ユーザーがそれほど多くない状況でよく使用されます。JSP の開発とデバッグには、最初の選択肢です。プログラム。Java Web 初心者にとって、Tomcat は実際に JSP ページと Serlet を実行することが最良の選択です
最新バージョンの Tornct 9.0 が
3 ~ 5 年間動作した後は、Tomcat サーバーを手動で作成して、
Tomcat をダウンロードしてみることができます。

  1. インストールまたは解凍
  2. 設定ファイルとディレクトリ構造を理解する
  3. これは何をするのか

3、トムキャット

3.1 Tomcatのインストール Tomcat

公式ウェブサイト: http://tomcat.apache.org/
画像.png
画像.png

3.2. Tomcat の起動と設定

フォルダー機能:
画像.png
画像.png
アクセステスト: http://localhost:8080/
考えられる問題:

  1. Java環境変数が設定されていません
  2. クラッシュの問題: 互換性を構成する必要があります
  3. コードの文字化けの問題: 構成ファイルの設定

conf/logging.properties の java.util.logging.ConsoleHandler.encoding = GBK を変更して、文字化けの問題を解決できます (非推奨)

3.3. 設定

画像.png
設定可能な起動ポート番号

  • Tomcat のデフォルトのポート番号は 8080 です。
  • mysql:3306
  • http:80
  • https:443
<Connector port="8081" protocol="HTTP/1.1"
    connectionTimeout="20000"
    redirectPort="8443" />

設定可能なホスト名

  • デフォルトのホスト名は次のとおりです: localhost->127.0.0.1
  • デフォルトの Web サイト アプリケーションの保存場所は次のとおりです: webapps
<Host name="www.qinjiang.com"  appBase="webapps"
    unpackWARs="true" autoDeploy="true">
// name 默认是loaclhost, 改了之后,需要去host里面改DNS映射关系

面接での難しい質問:
Web サイトへのアクセス方法を教えてください。

  1. ドメイン名を入力し、Enter キーを押します
  2. このマシンの C:\Windows\System32\drivers\etc\hosts 構成ファイルにこのドメイン名のマッピングがあるかどうかを確認します。
    1. はい: 対応する IP アドレスを直接返します。このアドレスには、アクセスする必要がある Web プログラムがあり、直接アクセスできます。
    2. いいえ: DNS サーバーにアクセスして検索し、見つかった場合は返します。見つからない場合は返します。
      画像.png

4. 環境変数を設定できます (オプション)

3.4. Web ウェブサイトを公開する

知らないならまずは真似してみよう

  • サーバー(Tomcat)上の指定したWebアプリケーションフォルダ(webapps)に作成したWebサイトを置くとアクセスできるようになります。

ウェブサイトが持つべき構造

--webapps :Tomcat服务器的web目录
    -ROOT
    -kuangstudy :网站的目录名
    	-WEB-INF
    		-classes : java程序
        	-lib:web应用所依赖的jar包
        	-web.xml :网站配置文件
        -index.html 默认的首页
        -static 
        	-css
        	-js
        	-img
        	-.....

HTTP プロトコル:
Maven へのインタビュー: ビルド ツール

  • Maven インストール パッケージ

サーブレットの入門

  • こんにちは世界!
  • サーブレットの構成・原理

4、http

4.1. HTTPHTTP とは何ですか

(ハイパーテキスト転送プロトコル) は、通常 TCP 上で実行される単純な要求/応答プロトコルです。

  • テキスト: html、文字列、…
  • ハイパーテキスト: 写真、音楽、ビデオ、位置情報、地図...
  • ポート:80

HTTPS: 安全

4.2. 2 つの時代

  • http1.0
    • HTTP/1.0: クライアントが Web サーバーに接続できるようになった後は、1 つの Web リソースのみを取得して切断できます。
  • http2.0
    • HTTP/1.1: クライアントは Web サーバーに接続できると、複数の Web リソースを取得できます。

4.3. HTTPリクエスト

  • クライアント – リクエスト – サーバー

百度:

Request URL:https://www.baidu.com/   请求地址
Request Method:GET    get方法/post方法
Status Code:200 OK    状态码:200
Remote(远程) Address:14.215.177.39:443

Accept:text/html  
Accept-Encoding:gzip, deflate, br
Accept-Language:zh-CN,zh;q=0.9    语言
Cache-Control:max-age=0
Connection:keep-alive
1.リクエストライン
  • リクエストラインのリクエストメソッド: GET
  • リクエストメソッド: Get、Post、HEAD、DELETE、PUT、TRACT。
    • get: リクエストに含めることができるパラメータは比較的少なく、サイズは制限されており、データの内容はブラウザの URL アドレス バーに表示されます。安全ではありませんが、効率的です。
    • 投稿: リクエストで伝送できるパラメータやサイズに制限はありません。データの内容はブラウザの URL アドレス バーに表示されません。安全ですが、効率的ではありません。
2. メッセージヘッダー
Accept:告诉浏览器,它所支持的数据类型
Accept-Encoding:支持哪种编码格式  GBK   UTF-8   GB2312  ISO8859-1
Accept-Language:告诉浏览器,它的语言环境
Cache-Control:缓存控制
Connection:告诉浏览器,请求完成是断开还是保持连接
HOST:主机..../.

4.4. HTTPレスポンス

  • サーバー – 応答….クライアント

百度:

Cache-Control:private    缓存控制
Connection:Keep-Alive    连接
Content-Encoding:gzip    编码
Content-Type:text/html   类型  
1. レスポンスボディ
Accept:告诉浏览器,它所支持的数据类型
Accept-Encoding:支持哪种编码格式  GBK   UTF-8   GB2312  ISO8859-1
Accept-Language:告诉浏览器,它的语言环境
Cache-Control:缓存控制
Connection:告诉浏览器,请求完成是断开还是保持连接
HOST:主机..../.
Refresh:告诉客户端,多久刷新一次;
Location:让网页重新定位;
2. レスポンスステータスコード

200: リクエスト応答成功 200
3xx: リクエスト リダイレクト · リダイレクト: 私が指定した新しい場所に移動します;
4xx: リソースが見つかりません 404 · リソースが存在しません;
5xx: サーバー コード エラー 500 502: ゲートウェイ エラー
面接でよくある質問:
ブラウザのアドレス バーにアドレスを入力し、ページが表示されたときに Enter キーを押したとき、どのような経験をしましたか?

5、メイブン

なぜこのテクノロジーを学ぶ必要があるのですか?

  1. Java Web 開発では、多数の jar パッケージを使用する必要があるため、それらを手動でインポートします。
  2. この jar パッケージを自動的にインポートして構成するにはどうすればよいですか?

ここからMavenが誕生しました!

5.1 Maven プロジェクト アーキテクチャ管理ツール

現在、jar パッケージのインポートを容易にするためにこれを使用しています。
Maven の核となる考え方:合意は構成よりも重要です

  • 制限がありますので、違反しないでください。

Maven は Java コードの記述方法を規定しており、この仕様に従う必要があります。

5.2 Maven をダウンロードしてインストールする

公式ウェブサイト:
画像.png
ダウンロード後、解凍します。

5.3 環境変数の構成

システム環境変数で次の構成を構成します。

  • M2_HOME maven ディレクトリの下の bin ディレクトリ
  • MAVEN_HOME Maven ディレクトリ
  • システム パスに %MAVEN_HOME%\bin を構成します。

画像.png
画像.png
Maven が正常にインストールされているかどうかをテストし、構成する必要があることを確認してください。

5.4 アリババクラウドイメージ

  • ミラー: ミラー
  • 機能: ダウンロードを高速化します。
  • 中国ではAlibaba Cloudのイメージを使用することを推奨します
<mirror>
  <id>nexus-aliyun</id>  
  <mirrorOf>*,!jeecg,!jeecg-snapshots</mirrorOf>  
  <name>Nexus aliyun</name>  
  <url>http://maven.aliyun.com/nexus/content/groups/public</url> 
</mirror>

5.5 現地倉庫

ローカル ウェアハウス、リモート ウェアハウス; ローカル ウェアハウスを作成: localRepository

在D:\java\Maven\apache-maven-3.8.7\ 新建一个空目录,maven-repo

<localRepository>D:\java\Maven\apache-maven-3.8.7\maven-repo</localRepository>

5.6 IDEA配置Maven

画像.png
2回設定する必要があるので注意してください 設定場所は上の写真の通りです!
画像.png
初めてプロジェクトを作成する場合はジェネレーターを使用します
画像.png
画像.png
2 回目でプロジェクトを作成する場合はジェネレーターを使用します
画像.png
以下のように、main-java には Java ソース コードが配置され、resources には設定ファイルが配置され、test-java テストが配置されます(規約は設定よりも優れています!)
画像.png
コンストラクターを使用してそれを再構築します。Maven プロジェクトでは、次の Web アプリ パッケージが表示されます。右クリックして
画像.png
ソース コード ディレクトリとしてマークするか、プロジェクト構造を設定できます。 -モジュールの設定。

5.7 IDEA での Tomcat の構成

右上隅にある現在のファイル、プルダウンして設定ファイル、+ Tomcan ローカル サーバーを選択します。
画像.png
以下のパス設定を に設定しないようにしてください/。そうしないと、Tomcat の元の ROOT ディレクトリが削除されます。
画像.png
その後、それを起動すると、次のことができます。ハローワールドにアクセスします。
画像.png

5.8pomファイル

pom.xml は Maven のコア構成ファイルです

<!--Maven版本和头文件-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  
  <!--这里是刚才配置的GAV-->
  <groupId>org.example</groupId>
  <artifactId>test2</artifactId>
  <version>1.0-SNAPSHOT</version>
  <!--Packaging 项目的打包方式
  jar: java 应用
  war: JavaWeb 应用
  -->
  <packaging>war</packaging>

  <name>test2 Maven Webapp</name>
  <url>http://maven.apache.org</url>
  
  <!--项目依赖-->
  <dependencies>
    <!--具体依赖的jar包-->
		<!--高级之处在于自动下载对应的jar包-->
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
			<!--作用域 -->
      <scope>test</scope>
    </dependency>
  </dependencies>
  
  <!--配置-->
  <properties>
    <!--编码版本 -->
    <maven.compiler.source>8</maven.compiler.source>
    <maven.compiler.target>8</maven.compiler.target>
    <!--项目的默认编码-->
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>
  
  <build>
    <finalName>test2</finalName>
  </build>
</project>

Maven には設定よりも規約が多いため、作成した設定ファイルがエクスポートできない、または有効にならないという問題が発生する可能性があります 解決策: IDEA の操作: 右上隅のディレクトリ ツリーに依存するディレクトリ構造を表示できます
画像.png
Crtl+Alt+Shift+U

IDEA は Maven コンストラクターを使用します。生成される web.xml のデフォルト バージョンは 2.3 であり、Tomcat と一致する必要があるため、Tomcat の ROOT ディレクトリから web.xml のコンテンツをコピーする必要があります。現在は 5.0 です。

<?xml version="1.0" encoding="UTF-8"?>

<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
                      http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
  version="4.0"
  metadata-complete="true">

</web-app>

6、サーブレット

6.1. サーブレットの概要

  • サーブレットは、Sun が動的 Web を開発するために使用するテクノロジーです。
  • Sun は、これらの API で「Servlet」と呼ばれるインターフェースを提供しています。Servlet プログラムを開発する場合は、次の 2 つの小さな手順を実行するだけで済みます。
    • Serlet インターフェースを実装するクラスを作成する
    • 開発した Java クラスを Web サーバーにデプロイします。

サーブレットインターフェースを実装したJavaプログラムはサーブレットと呼ばれます。

6.2、Helloサーブレット

Serlvet インターフェイス Sun には、HttpServlet、GenericServled という 2 つのデフォルト実装クラスがあります。

  1. 通常の Maven プロジェクトをビルドし、その中の src ディレクトリを削除します。将来的には、このプロジェクト内に Moudel をビルドします。この空のプロジェクトがメインの Maven プロジェクトです。
  2. Maven の親プロジェクトと子プロジェクトについての理解。
    親プロジェクトに含まれます。
<modules>
  <module>servlet-01</module>
</modules>

サブプロジェクトもあるだろうし

<parent>
  <artifactId>javaweb-02-servlet</artifactId>
  <groupId>com.kuang</groupId>
  <version>1.0-SNAPSHOT</version>
</parent>

親プロジェクトの Java はサブプロジェクトで直接使用できます

son extends father
  1. Maven環境の最適化
    1. web.xmlを最新のものに変更します
    2. Maven 構造を完成させる
<?xml version="1.0" encoding="UTF-8"?>

<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
                      http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
  version="4.0"
  metadata-complete="true">

</web-app>
  1. サーブレットプログラムを書く
    1. 通常のクラスを書く
    2. Servlet インターフェースを実装します。ここでは HttpServlet を直接継承します。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    
    <groupId>org.example</groupId>
    <artifactId>javaweb-02-servlet</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>pom</packaging>
    <modules>
        <module>servlet-01</module>
        <module>servlet-02</module>
    </modules>
    
    <dependencies>
        <!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>4.0.1</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/javax.servlet.jsp/javax.servlet.jsp-api -->
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>javax.servlet.jsp-api</artifactId>
            <version>2.3.3</version>
        </dependency>
        
         <!--这个是Tomcat10用的-->
         <!--https://mvnrepository.com/artifact/jakarta.servlet/jakarta.servlet-api -->
        <!--<dependency>-->
        <!--    <groupId>jakarta.servlet</groupId>-->
        <!--    <artifactId>jakarta.servlet-api</artifactId>-->
        <!--    <version>6.0.0</version>-->
        <!--</dependency>-->


    </dependencies>
    
    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

</project>
package org.Martin.servlet;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

public class HelloServlet extends HttpServlet {
    
    

    //由于get或者post只是请求实现的不同的方式,可以相互调用,业务逻辑都一样;
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
        //ServletOutputStream outputStream = resp.getOutputStream();
        PrintWriter writer = resp.getWriter(); //响应流
        writer.print("Hello,Serlvet");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
        doGet(req, resp);
    }
}
  1. サーブレット マッピングの作成
    マッピングが必要な理由: JAVA プログラムを作成しますが、ブラウザを介してアクセスする必要があり、ブラウザは Web サーバーに接続する必要があるため、作成したサーブレットを Web サービスに登録して提供する
    必要があります。これは参照です。サーバーがアクセスできるパスです。
<!--注册Servlet-->
<servlet>
  <servlet-name>hello</servlet-name>
  <servlet-class>com.kuang.servlet.HelloServlet</servlet-class>
</servlet>
<!--Servlet的请求路径-->
<servlet-mapping>
  <servlet-name>hello</servlet-name>
  <url-pattern>/hello</url-pattern>
</servlet-mapping>
  1. Tomcat を構成するときの注意
    : プロジェクト リリースの (プロジェクト) パスを構成するだけです。デプロイメントにコンテンツがない場合は、右側の Maven を更新してください。
  2. テストを開始します、OK!
    画像.png

6.3. サーブレットの原理

サーブレットは Web サーバーによって呼び出され、ブラウザー要求を受信した後、Web サーバーは次の処理を行います。
画像.png

6.4. マッピングの問題

  1. サーブレットはマッピング パスを指定できます
<servlet-mapping>
  <servlet-name>hello</servlet-name>
  <url-pattern>/hello</url-pattern>
</servlet-mapping>
  1. サーブレットは複数のマッピング パスを指定できます
<servlet-mapping>
  <servlet-name>hello</servlet-name>
  <url-pattern>/hello</url-pattern>
</servlet-mapping>
<servlet-mapping>
  <servlet-name>hello</servlet-name>
  <url-pattern>/hello2</url-pattern>
</servlet-mapping>
<servlet-mapping>
  <servlet-name>hello</servlet-name>
  <url-pattern>/hello3</url-pattern>
</servlet-mapping>
<servlet-mapping>
  <servlet-name>hello</servlet-name>
  <url-pattern>/hello4</url-pattern>
</servlet-mapping>
<servlet-mapping>
  <servlet-name>hello</servlet-name>
  <url-pattern>/hello5</url-pattern>
</servlet-mapping>
  1. サーブレットはユニバーサル マッピング パスを指定できます
<servlet-mapping>
  <servlet-name>hello</servlet-name>
  <url-pattern>/hello/*</url-pattern>
</servlet-mapping>
  1. デフォルトのリクエストパス
<!--默认请求路径,直接顶替了Index它成为了首页-->
<servlet-mapping>
  <servlet-name>hello</servlet-name>
  <url-pattern>/*</url-pattern>
</servlet-mapping>
  1. いくつかのサフィックスやプレフィックスなどを指定します。
<!--可以自定义后缀实现请求映射
注意点,*前面不能加项目映射的路径
例如不能这样: /*.txt /hello/*.txt
-->
<servlet-mapping>
  <servlet-name>hello</servlet-name>
  <url-pattern>*.qinjiang</url-pattern>
</servlet-mapping>
  1. 優先度の問題:
    固有のマッピング パスが最も高い優先度を持つように指定されています。それが見つからない場合は、デフォルトの処理リクエストが使用されます。
<!-- 访问/hello优先级高,不会进入error界面 -->
<servlet-mapping>
    <servlet-name>hello</servlet-name>
    <url-pattern>/hello</url-pattern>
</servlet-mapping>

<servlet>
    <servlet-name>myError</servlet-name>
    <servlet-class>org.Martin.servlet.ErrorServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>myError</servlet-name>
    <url-pattern>/*</url-pattern>
</servlet-mapping>

6.5、サーブレットコンテキスト

Web コンテナが起動すると、現在の Web アプリケーションを表す各 Web プログラムに対応する ServletContext オブジェクトが作成されます。

1. データを共有する

このサーブレットに保存したデータは、別のサーブレットで取得できます。

public class HelloServlet extends HttpServlet {
    
    
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    

        //this.getInitParameter()   初始化参数
        //this.getServletConfig()   Servlet配置
        //this.getServletContext()  Servlet上下文
        ServletContext context = this.getServletContext();

        String username = "秦疆"; //数据
        context.setAttribute("username",username); //将一个数据保存在了ServletContext中,名字为:username 。值 username

    }

}
public class GetServlet extends HttpServlet {
    
    
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
        ServletContext servletContext = this.getServletContext();

        // 获取HelloServlet保存的
        String username = (String) servletContext.getAttribute("username");

        resp.getWriter().print(username);
    }
}

<servlet>
  <servlet-name>hello</servlet-name>
  <servlet-class>com.Martin.servlet.HelloServlet</servlet-class>
</servlet>    
<servlet-mapping>
  <servlet-name>hello</servlet-name>
  <url-pattern>/hello</url-pattern>
</servlet-mapping>

<servlet>
  <servlet-name>gets</servlet-name>
  <servlet-class>com.Martin.servlet.GetServlet</servlet-class>
</servlet>
<servlet-mapping>
  <servlet-name>gets</servlet-name>
  <url-pattern>/gets</url-pattern>
</servlet-mapping>

アクセス結果をテストします。最初に hello にアクセスすると、アクセスが有効になります。それ以外の場合、hello はデータを送信せず、取得にアクセスできません。

2. 初期化パラメータを取得する
<!--配置一些web应用初始化参数-->
<context-param>
  <param-name>url</param-name>
  <param-value>jdbc:mysql://localhost:3306/mybatis</param-value>
</context-param>

<servlet>
    <servlet-name>gp</servlet-name>
    <servlet-class>com.Martin.servlet.GetParaServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>gp</servlet-name>
    <url-pattern>/gp</url-pattern>
</servlet-mapping>
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
    ServletContext context = this.getServletContext();
    String url = context.getInitParameter("url");
    resp.getWriter().print(url);
}
3. 転送リクエスト

GP リソースを自分のページに転送しました

	@Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
        ServletContext context = this.getServletContext();
        System.out.println("进入了ServletDemo04");
        //RequestDispatcher requestDispatcher = context.getRequestDispatcher("/gp"); //转发的请求路径
        //requestDispatcher.forward(req,resp); //调用forward实现请求转发;
        context.getRequestDispatcher("/gp").forward(req,resp);
    }

画像.png
4. リソースファイルを読み取る
Properties

  • Java ディレクトリに新しいプロパティを作成します (これには構成が必要です)
  • リソースディレクトリに新しいプロパティを作成します。

見つかった: それらはすべて同じパスの下にパッケージ化されています: target-classes。通常、このパスをクラスパスと呼びます:
画像.png画像.png
アイデア: ファイル ストリームが必要です

username=admin	
password=root
public class GetPropertiesServlet extends HttpServlet {
    
    
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
        // 在打包之后的target下的项目路径
        InputStream is = this.getServletContext().getResourceAsStream("/WEB-INF/classes/db.properties");

        Properties prop = new Properties();
        prop.load(is);
        String username = prop.getProperty("username");
        String password = prop.getProperty("password");

        resp.getWriter().print(username+password);
    }
}

テストへのアクセスは問題ありません。

6.6、HTTPサーブレットレスポンス


Web サーバーはクライアントの http リクエストを受信し、このリクエストに対して、リクエストを表す HttpServletRequest オブジェクトとレスポンスを表す HttpServletResponseを作成します。

  • クライアントによって要求されたパラメータを取得したい場合: HttpServletRequest を検索します。
  • クライアントに何らかの情報で応答したい場合: HttpServletResponse を検索します。
1. 簡易分類

ブラウザへのデータ送信を担当するメソッド

ServletOutputStream getOutputStream() throws IOException;
PrintWriter getWriter() throws IOException;

応答ヘッダーをブラウザに送信するメソッド

void setCharacterEncoding(String var1);
void setContentLength(int var1);
void setContentLengthLong(long var1);
void setContentType(String var1);
void setDateHeader(String varl,long var2);
void addDateHeader(String var1,long var2);
void setHeader(String var1,String var2);
void addHeader(String var1,String var2);
void setIntHeader(String var1,int var2);
void addIntHeader(String varl,int var2);

応答ステータスコード
画像.png
画像.png

2. 共通アプリケーション
  1. ブラウザにメッセージを出力する(ずっと話してるので割愛)
  2. ダウンロードファイル
    1. ダウンロードしたファイルへのパスを取得するには
    2. ダウンロードしたファイルの名前は何ですか?
    3. ブラウザが必要なもののダウンロードをサポートできるようにする方法をセットアップする
    4. ダウンロードしたファイルの入力ストリームを取得します
    5. バッファの作成
    6. OutputStream オブジェクトを取得する
    7. FileOutputStream ストリームをバッファー バッファーに書き込みます。
    8. OutputStream を使用して、バッファ内のデータをクライアントに出力します。
package org.Martin.servlet;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URLEncoder;

public class FileServlet extends HttpServlet {
    
    
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
        // 1. 要获取下载文件的路径
        String realPath = this.getServletContext().getRealPath("/WEB-INF/classes/ctfshow.png");
        // String realPath = "E:\\Martin_Code\\java\\javaweb\\javaweb-02-servlet\\Response-01\\target\\Response-01\\WEB-INF\\classes\\ctfshow.png";
        System.out.println("文件路径:"+realPath);
        // 2. 下载的文件名是啥?
        String fileName = realPath.substring(realPath.lastIndexOf("\\") + 1);
        // 3. 设置想办法让浏览器能够支持下载我们需要的东西
        // "Content-Disposition","attachment;filename="+URLEncoder.encode(fileName,"UTF-8"))
        resp.setHeader("Content-Disposition","attachment;filename="+URLEncoder.encode(fileName,"UTF-8"));
        // 4. 获取下载文件的输入流
        FileInputStream fis = new FileInputStream(realPath);
        // 5. 创建缓冲区
        int len=0;
        byte[] buffer = new byte[1024];
        // 6. 获取OutputStream对象
        ServletOutputStream outputStream = resp.getOutputStream();
        // 7. 将FileOutputStream流写入到bufer缓冲区
        while ((len=fis.read(buffer))!=-1){
    
    
            // 8. 使用OutputStream将缓冲区中的数据输出到客户端!
            outputStream.write(buffer,0,len);
        }
        outputStream.close();
        fis.close();
    }
}

3. 認証コード機能

検証はどのようにして行われたのでしょうか?

  • フロントエンドの実装
  • バックエンドの実装では、画像を生成するために Java の画像クラスを使用する必要があります。
package org.Martin.servlet;

import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;

public class ImageServlet extends HttpServlet {
    
    
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    

        // 如何让浏览器每5秒刷新一次
        resp.setHeader("refresh","3");

        // 在内存中创建一个图片
        BufferedImage image = new BufferedImage(80,20,BufferedImage.TYPE_INT_RGB);
        // 得到图片
        Graphics2D g = (Graphics2D) image.getGraphics(); //笔
        // 设置图片背景颜色
        g.setColor(Color.WHITE);
        g.fillRect(0,0,80,20);
        // 给图片写数据
        g.setColor(Color.BLUE);
        g.setFont(new Font("null",Font.BOLD,20));
        g.drawString(makeNum(),0,20);

        // 告诉浏览器这个请求用图片的方式打开
        resp.setContentType("image/png");
        // 网站存在缓冲,不让浏览器缓存
        resp.setDateHeader("expires",-1);
        resp.setHeader("Cache-Control","no-cache");
        resp.setHeader("Pragma","no-cache");

        // 把图片写给浏览器
        ImageIO.write(image,"jpg",resp.getOutputStream());


    }

    // 生成随机数
    private String makeNum(){
    
    
        Random random = new Random();
        // 最大值,4位数
        String num = random.nextInt(9999) + "";
        StringBuffer sb = new StringBuffer();
        // 不足四位数,补充0
        for (int i = 0; i < 4-num.length(); i++) {
    
    
            sb.append("0");
        }
        num = sb.toString() + num;
        return num;
    }
}

<servlet>
  <servlet-name>ImageServlet</servlet-name>
  <servlet-class>com.kuang.servlet.ImageServlet</servlet-class>
</servlet>
<servlet-mapping>
  <servlet-name>Imageservlet</servlet-name>
  <url-pattern>/img</url-pattern>
</servlet-mapping>
4. リダイレクトの実装

画像.png
一般的なシナリオ:

  • ユーザーログイン
void sendRedirect(String var1) throws IOException;

テスト:

public class RedirectServlet extends HttpServlet {
    
    
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
        // 跳转到哪里
        /*
        resp.setHeader("Location","./image");
        resp.setStatus(302);
         */
        // resp.sendRedirect(req.getContextPath()+"/image");
        resp.sendRedirect("./image");

    }
}

画像.png
画像.png
インデックス.jsp

<html>
  <body>
    <h2>Hel1o World!</h2>

    <%--这里超交的路径,需要寻找到项目的路径--%>
      <%--${pageContext. request, contextPath}代表当前的项目--%>
        <form action="${pageContext. request.contextPath}/login" method="get">
          用户名: <input type="text" name="username"> <br>
          密码: <input type="password" name="password"> <br>
          <input type="submit">
        </form>
      </body>
      </html>

リクエストテスト.java

public class RequestTest extends HttpServlet {
    
    
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
        System.out.println("进入请求");
        // 处理请求
        String username = req.getParameter("username");
        String password = req.getParameter("password");

        System.out.println(username+password);

        // 重定向到成功,注意路径
        resp.sendRedirect(req.getContextPath()+"/success.jsp");
        // resp.sendRedirect("./success.jsp");
    }
}

リダイレクトページsuccess.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <h1>success</h1>
</body>
</html>

web.xmlの設定

<servlet>
  <servlet-name>requset</servlet-name>
  <servlet-class>com. kuang. servlet. RequestTest</servlet-class>
</servlet>
<servlet-mapping>
  <servlet-name>requset</servlet-name>
  <url-pattern>/login</url-pattern>
</servlet-mapping>

依存するjarパッケージをインポートする

<dependencies>
    <!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>4.0.1</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/javax.servlet.jsp/javax.servlet.jsp-api -->
    <dependency>
        <groupId>javax.servlet.jsp</groupId>
        <artifactId>javax.servlet.jsp-api</artifactId>
        <version>2.3.3</version>
    </dependency>
</dependencies>

6.7、HTTPサーブレットリクエスト

HttpServletRequest はクライアントのリクエストを表します。ユーザーは Http プロトコルを通じてサーバーにアクセスします。HTTP リクエスト内のすべての情報は HttpServletRequest にカプセル化されます。この HttpServletRequest メソッドを通じて、クライアントのすべての情報が取得されます。
画像.png
画像.png

1. パラメータを取得して転送をリクエストする

画像.png
独自のクラスを作成し、HttpServlet クラスを継承する必要がある

public class LoginServlet extends HttpServlet {
    
    
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
        req. setCharacterEncoding("utf-8");
        resp.setCharacterEncoding("utf-8");

        String username = req.getParameter("username");
        String password = req.getParameter("password");
        System.out.println(username);
        System.out.println(password);
        for (String hobby : req.getParameterValues("hobby")) {
    
    
            System.out.println(hobby);
        }

        // 请求转发 会保留项目地址  所以不用加这个 req.getContextPath()
        req.getRequestDispatcher("/success.jsp").forward(req,resp);

        System.out.println(req.getPathInfo()); // null
        System.out.println(req.getContextPath()); // /Request_01_war 项目的根路径
        System.out.println(req.getServletPath()); // /login 自己这个类的路径

    }
}

6.8. リダイレクトとリクエスト転送の違い!

画像.png

// 重定向,需要根目录的地址
response.sendRedirect(req.getContextPath()+"/success.jsp");


// 请求转发, 会保留项目的根目录地址,不用加requset.getContextPath()来获取根目录地址
requset.getRequestDispatcher("/success.jsp").forward(req,resp);

// 前端获取项目的根地址
${
    
    pageContext.request.contextPath}

7、クッキー、セッション

7.1. 会話

セッション: ユーザーはブラウザを開き、多くのハイパーリンクをクリックし、複数の Web リソースにアクセスし、ブラウザを閉じます。このプロセスはセッションと呼ばれます。ステートフル セッション: クラスメートが教室に行っており、いつ彼が教室に来るかがわかり
ます。次回は教室です。以前もここに来たことのあるこのクラスメートは、これをステートフルな会話と呼んでいます。
どうすれば自分が西開の学生であることを証明できますか?
あなたは西へ車で行きます

  1. 請求書 Xikai が請求書をお渡しします
  2. 学校登録 Xikai はあなたがここに来たことをマークします

ウェブサイトはどのようにしてあなたがそこに行ったことを証明できるのでしょうか?
クライアントサーバー

  1. サーバーはクライアントにレターを送信し、クライアントは次回サーバーにアクセスするときにそのレターを持参できます。
  2. サーバーはあなたが来たことを登録します、そして、あなたが次に来たときに私はあなたとマッチングします; 参照してください

7.2. セッションを保存するための 2 つのテクニック

クッキー

  • クライアントテクノロジー (応答、要求)

セッション

  • サーバーテクノロジー、このテクノロジーを使用すると、ユーザーのセッション情報を保存できますか? Sessionに情報やデータを入れることができます!

共通共通:一度サイトにログインすると次回からはログイン不要、二回目からは直接ログイン!

7.3、クッキー

画像.png

  1. リクエストからCookie情報を取得する
  2. サーバーはクライアントの Cookie に応答します
Cookie[] cookies = req.getCookies(); //获得Cookie
cookie.getName(); //获得cookie中的key
cookie.getValue(); //获得cookie中的vlaue
new Cookie("lastLoginTime", System.currentTimeMillis()+""); //新建一个cookie
cookie.setMaxAge(24*60*60); //设置cookie的有效期
resp.addCookie(cookie); //响应给客户端一个cookie

代码:
public class CookieDemo01  extends HttpServlet {
    
    
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
        // 解决中文乱码,解决不了!!
        req.setCharacterEncoding("UTF-8");
        resp.setCharacterEncoding("UTF-8");

        // 写数据
        PrintWriter writer = resp.getWriter();

        // Cookie从服务器获取
        Cookie[] cookies = req.getCookies(); // 可能存在多个,是一个数组

        // 判断是否是第一次登录
        boolean flag = false;
        for (Cookie cookie : cookies) {
    
    
            if (cookie.getName().equals("lastTime")){
    
    
                flag=true;
                // cookie.getValue();是一个字符串
                // 字符串变整数时间戳
                long lastTime = Long.parseLong(cookie.getValue());
                Date date = new Date(lastTime);
                writer.write("Not first: ");
                writer.write(date.toLocaleString());
            }
        }
        if (!flag){
    
    
            writer.write("The First");
        }

        // 服务器更新Cookie  name value
        // System.currentTimeMillis()一个时间戳
        Cookie cookie = new Cookie("lastTime",String.valueOf(System.currentTimeMillis()));
        cookie.setMaxAge(24*60*60); //有效期
        resp.addCookie(cookie);
    }
}

Cookie: 通常、ローカル ユーザー ディレクトリ AppData に保存されます。Web
サイト上の Cookie に上限はありますか? 詳細について話しましょう

  • Cookie は 1 つの情報のみを保存できます。
  • Web サイトは複数の Cookie をブラウザに送信し、最大 20 個の Cookie を保存できます。
  • Cookie のサイズは 4kb に制限されています。
  • Cookie ブラウザの制限は 300 個

Cookie を削除します。

  • 有効期間を設定しない場合は、ブラウザを閉じると自動的に有効期限が切れます。
  • 有効期間を 0 に設定します。

エンコードデコード:

URLEncoder.encode("秦疆","utf-8");
URLDecoder.decode(cookie.getValue(),"UTF-8");

7.4. セッション(要点)

画像.png
セッションとは:

  • サーバーはユーザー (ブラウザー) ごとに Seesion オブジェクトを作成します。
  • セッションはブラウザを占有します。ブラウザが閉じられていない限り、このセッションは存在します。
  • ユーザーがログインすると、Web サイト全体にアクセスできるようになります。–> ユーザー情報を保存; ショッピングカート情報を保存…

使用するシーン:

  • ログインしているユーザーの情報を保存します。
  • ショッピングカート情報;
  • Web サイト全体で頻繁に使用されるデータはセッションに保存されます。

セッションを使用します:

public class SessionDemo01 extends HttpServlet {
    
    
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    

        //解决乱码
        resp.setCharacterEncoding("utf-8");
        req.setCharacterEncoding("utf-8");
        resp.setContentType("text/html;charset=utf-8");

        // 得到Session
        HttpSession session = req.getSession();

        // session.removeAttribute("name"); 删除session中的name
        // session.invalidate(); 清除session,当浏览器再次访问,会生成新的session,应用于用户手动注销
        
        // 给Session 存信息 可以存一个对象
        session.setAttribute("name","Martin");
        session.setAttribute("Person",new Person("person.name",3));

        // 得到Session 的信息
        System.out.println(session.getAttribute("name"));
        System.out.println(session.getAttribute("Person"));

        // 获取Session ID
        String sessionId = session.getId();

        // 判断是不是新的
        if (session.isNew()){
    
    
            resp.getWriter().write("new: "+sessionId);
        }else {
    
    
            resp.getWriter().write("old: "+sessionId);
        }

        //Session创建的时候做了什么?
        //传递了一个Cookie, name="JSESSIONID" value=session.getId()
    }
}

自動セッション有効期限: web.xml 設定

<!--设置Session默认的失效时间-->
<session-config>
  <!--15分钟后Session自动失效,以分钟为单位-->
  <session-timeout>15</session-timeout>
</session-config>

7.5. Cookie とセッションの比較

  • クッキー
    • クッキーを取得するreq.getCookies()
    • キーと値のペアの Cookie 配列を追加します。resp.addCookies(cookie)
    • Cookie の内容を取得します。cookie.getName();cookie.getValue();
  • セッション
    • セッションの取得req.getSession()
    • Session オブジェクトのキーと値のペアを追加します。session.setAttribute(name,value)
    • セッションの内容を取得します: session.getAttribute(name)
      | Cookie | セッション | トークン |
      | — | — | — |
      | ユーザーが初めてログインするとき:
  1. クライアントがリクエストを送信
  2. サーバーは Cookie を設定し、クライアントに送信します。
  3. クライアントは Cookie を受け入れ、ローカルに保存し、次回アクセスするときに Cookie を持ち歩きます。
  4. サーバーは Cookie を受け入れ、対応するユーザーのデータを元に戻します (Cookie の制限: キーと値のペアでのみ保存できるため、非効率的でセッションが発生します)
    | ユーザーがログインするたび:
  5. クライアントがリクエストを送信
  6. サーバーは一意の SessionID を設定し、それをクライアントに返します (Cookie を使用)
  7. クライアントは、アクセスするたびに SessionID を保持します (Cookie の形式で提供されます)。
  8. サーバーはすべてのユーザーのセッション ID を保存するため、各ユーザーを区別する方法は比較することです。サーバーは大量のデータを保存するため、
    ユーザーがログインするとトークン | が表示されます。
  9. クライアントがリクエストを送信
  10. サーバーはトークンを生成し、ユーザーに返します。このトークンは暗号化された UserID を保存し、ユーザーを区別するために使用されます。
  11. クライアントはアクセスするたびにトークンを保持します。
  12. サーバーはトークンを受け入れ、復号化して、ユーザーを区別するための UserID を取得します。大量の SessionID データを保存するためにセッションを使用しないため、スペースが節約されます

Cookie: キーと値のペアのみを保存でき、効率が低い セッションが導入されました セッション
: SessionID はキーと値のペアの文字列のハッシュ値であり、非常に効率的です (サーバーは SessionID を使用して相互に照合し、検証および区別します)ユーザー) ですが、それらはすべてサーバーに保存されます。サーバー それは非常に不快なので、トークントークンが導入されます
: 暗号化されたユーザー ID をクライアントに保存し、サーバーはそれを復号化してユーザー ID を取得します。これはサーバーにとって非常に簡単です。

8、JSP

8.1. JSPとは

Java サーバー ページ: Java サーバーサイド ページは、サーブレットと同様に、動的 Web テクノロジで使用されます。
最大の特徴:

  • JSP の作成は HTML の作成と似ています
  • 違い:
    • HTML は静的データのみをユーザーに提供します
    • JAVA コードを JSP ページに埋め込んで、ユーザーに動的なデータを提供できます。

8.2. JSP の原則

アイデア: JSP はどのように実行されるのか?

  • コードレベルでは問題ない
  • サーバーの内部動作としては、tomcat に作業ディレクトリがあり、IDEA で Tomcat を使用すると、IDEA の Tomcat に作業ディレクトリが作成されます。

C:\Users\86136\AppData\Local\JetBrains\IntelliJIdea2022.3\tomcat
私のコンピューターのアドレス:C:\Users\86136\AppData\Local\JetBrains\IntelliJIdea2022.3\tomcat\16a6cd02-6b09-4de3-a7fa-601b94a708b7\work\Catalina\localhost\Request_01_war\org\apache\jspディスカバリー・ページは Java プログラムに変換されました。
画像.png
ブラウザはサーバーにリクエストを送信しますが、どのリソースにアクセスしても、実際にはサーブレットにアクセスしています。
JSP は最終的に Java クラスに変換されます。

JSP は本質的にカプセル化されたサーブレットです

//初始化
public void _jspInit() {
    
    

}
//销毁
public void _jspDestroy() {
    
    
}
//JSPService
public void _jspService(.HttpServletRequest request,HttpServletResponse response){
    
    
}

  1. 判決請求
  2. 組み込みオブジェクト
  3. ページを出力する前にコードを追加しました
  4. 上記のオブジェクトを JSP ページで直接使用できます。
final javax.servlet.jsp.PageContext pageContext;  //页面上下文
javax.servlet.http.HttpSession session = null;    //session
final javax.servlet.ServletContext application;   //applicationContext
final javax.servlet.ServletConfig config;         //config
javax.servlet.jsp.JspWriter out = null;           //out
final java.lang.Object page = this;               //page:当前
HttpServletRequest request;                       //请求
HttpServletResponse response;                     //响应
response.setContentType("text/html");       //设置响应的页面类型
pageContext = _jspxFactory.getPageContext(this, request, response,
                                          null, true, 8192, true);
_jspx_page_context = pageContext;
application = pageContext.getServletContext();
config = pageContext.getServletConfig();
session = pageContext.getSession();
out = pageContext.getOut();
_jspx_out = out;

画像.png
JSPページでは
JAVAコードであればそのまま出力、
HTMLコードであればout.write("<html>\r\n");このような形式に変換してフロントエンドに出力します!

8.3. JSPの基本構文

どの言語にも独自の文法があり、JAVA にもそれがあります。Java テクノロジのアプリケーションとして、JSP には独自の拡張構文がいくつかあり (知っておくだけで十分です!)、すべての Java 構文がサポートされています。

JSP式
<%-- 注释 --%> 
<%= 变量或者表达式%>  //作用:用来将程序的输出,输出到客户端
<%= new java.util.Date()%>
jspスクリプトフラグメント
<%--jsp脚本片段--%>

<%
 int sum = 0;
 for (int i = 1; i <=100 ; i++) {
   sum+=i;
 }
 out.println("<h1>Sum="+sum+"</h1>");
%>

スクリプトフラグメントの再実装

<%
 int x = 10;
 out.println(x);
%>
<p>这是一个JSP文档</p>
<%
 int y = 2;
 out.println(y);
%>

<hr>
 
 
<%--在代码嵌入HTML元素--%>
<%
 for (int i = 0; i < 5; i++) {
%>
 <h1>Hello,World  <%=i%> </h1>
<%
 }
%>
JSP宣言
<%!
 static {
   System.out.println("Loading Servlet!");
 }

 private int globalVar = 0;

 public void kuang(){
   System.out.println("进入了方法Kuang!");
 }
%>

JSP 宣言: JSP で生成された Java クラスにコンパイルされます。その他は _jspService メソッドに生成されます。
画像.png
JSP では、Java コードを埋め込むだけです。

<%%>  java代码片段
<%= %> 表达式的值
<%! %> jsp声明
 
<%--注释--%>

JSP コメントはクライアントに表示されませんが、HTML は表示されます。

8.4. JSP 命令

<%@page args.... %>
<%@include file=""%>

<%--@include会将两个页面合二为一,参数不能冲突--%>

<%@include file="common/header.jsp"%>
<h1>网页主体</h1>
<%@include file="common/footer.jsp"%>

<hr>


<%--jSP标签
   jsp:include:拼接页面,本质还是三个,参数互不影响
   --%>
<jsp:include page="/common/header.jsp"/>
<h1>网页主体</h1>
<jsp:include page="/common/footer.jsp"/>

8.5、9 組み込みオブジェクト

  • PageContext には何かが保存されます
  • 何かを保存するリクエスト
  • 応答
  • セッションは物事を保存します
  • アプリケーション [ServletContext] の保存
  • config 【ServletConfig】
  • ページ、理解する必要はありません
  • 例外
pageContext.setAttribute("name1","秦疆1号"); //保存的数据只在一个页面中有效
request.setAttribute("name2","秦疆2号"); //保存的数据只在一次请求中有效,请求转发会携带这个数据
session.setAttribute("name3","秦疆3号"); //保存的数据只在一次会话中有效,从打开浏览器到关闭浏览器
application.setAttribute("name4","秦疆4号");  //保存的数据只在服务器中有效,从打开服务器到关闭服务器

画像.png
request: クライアントはサーバーにリクエストを送信します。生成されたデータは、ユーザーが読んだ後は役に立ちません。例: ニュースは、ユーザーが読んだ後は役に立ちません。
セッション: クライアントはサーバーにリクエストを送信し、生成されたデータはショッピング カートなど、ユーザーがしばらく使用できます; アプリケーション: クライアントはサーバーにリクエストを送信し、生成されたデータはユーザーによって使用され
ますユーザーですが、他のユーザーも引き続き使用する可能性があります。例: チャット データ。

8.6、JSPタグ、JSTLタグ、EL式

<!-- JSTL表达式的依赖 -->
<dependency>
  <groupId>javax.servlet.jsp.jstl</groupId>
  <artifactId>jstl-api</artifactId>
  <version>1.2</version>
</dependency>
<!-- standard标签库 -->
<dependency>
  <groupId>taglibs</groupId>
  <artifactId>standard</artifactId>
  <version>1.1.2</version>
</dependency>

EL 式: ${ }

  • データを取得する
  • 操作を実行する
  • Web 開発で使用される一般的なオブジェクトを取得する

JSPタグ

<%--jsp:include--%>
 
<%--
http://localhost:8080/jsptag.jsp?name=kuangshen&age=12
--%>

<jsp:forward page="/jsptag2.jsp">
   <jsp:param name="name" value="kuangshen"></jsp:param>
   <jsp:param name="age" value="12"></jsp:param>
</jsp:forward>

/jsptag2.jsp
<%=request.getParameter("name")%>

JSTL 表現
JSTL タグ ライブラリを使用すると、HTML タグの欠点を補い、多くのタグをカスタマイズして使用できます。タグの機能は Java コードと同じです。、タグライブラリを導入する必要があります
フォーマットタグ
SQLタグ
XMLタグ
コアタグ(マスター部分)
画像.png
JSTLタグライブラリの使用手順

  • 対応するタグライブラリを導入する<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
  • メソッドを使用する
  • Tomcat は jstl パッケージを導入する必要もあります。そうしないと、「JSTL 解析エラー」というエラーが報告されます。

c:もしも

<head>
  <title>Title</title>
</head>
<body>
<h4>if测试</h4>

<hr>

<form action="coreif.jsp" method="get">
  <%--
  EL表达式获取表单中的数据
  ${param.参数名}
  --%>
  <input type="text" name="username" value="${param.username}">
  <input type="submit" value="登录">
</form>

<%--判断如果提交的用户名是管理员,则登录成功--%>
<!--   test是接受的值,var返回的boolean,cout输出value的值 -->
<c:if test="${param.username=='admin'}" var="isAdmin">
  <c:out value="管理员欢迎您!"/>
</c:if>

<%--自闭合标签--%>
<c:out value="${isAdmin}"/>

</body>

c:cを選択:いつ

<body>

<%--定义一个变量score,值为85--%>

<c:set var="score" value="55"/>

  <c:choose>
    <c:when test="${score>=90}">
      你的成绩为优秀
    </c:when>
    <c:when test="${score>=80}">
      你的成绩为一般
    </c:when>
    <c:when test="${score>=70}">
      你的成绩为良好
    </c:when>
    <c:when test="${score<=60}">
      你的成绩为不及格
    </c:when>
  </c:choose>

</body>

c:forEach

<%
    ArrayList<String> peoples = new ArrayList<>();
    peoples.add(0,"张三");
    peoples.add(1,"李四");
    peoples.add(2,"王五");
    peoples.add(3,"赵六");
    peoples.add(4,"田六");
    request.setAttribute("list",peoples);
%>


<%--
var , 每一次遍历出来的变量
items, 要遍历的对象
begin,   哪里开始
end,     到哪里
step,   步长
--%>
    
<c:forEach var="people" items="${list}">
<c:out value="${people}"/> <br>
</c:forEach>

<hr>

<c:forEach var="people" items="${list}" begin="1" end="3" step="1" >
<c:out value="${people}"/> <br>
</c:forEach>

9、JavaBean

エンティティ クラス
JavaBean には、次のような特有の記述方法があります。

  • パラメーターのないコンストラクターが必要です
  • プロパティはプライベートである必要があります
  • 対応する get/set メソッドが必要です。

通常、ORM をデータベース フィールドにマッピングするために使用されます。ORM
: オブジェクト リレーショナル マッピング

  • テーブル -> クラス
  • フィールド –> プロパティ
  • 行レコード---->オブジェクト

people表

ID 名前 住所
1 秦江第一 3 西安
2 秦江第2 18 西安
3 秦江第3 100 西安
class People{
    
    
    private int id;
    private String name;
    private int id;
    private String address;
}

class A{
    
    
    new People(1,"秦疆1号",3"西安");
    new People(2,"秦疆2号",3"西安");
    new People(3,"秦疆3号",3"西安");
}

画像.png

10. MVC 3 層アーキテクチャ

  • MVC とは: モデル ビュー コントローラー モデル、ビュー、コントローラー
    • モデル: データベーステーブルとクラス間の対応関係
    • 表示: jsp ページ
    • コントローラ: サーブレット

10.1. 以前のアーキテクチャ

画像.png
ユーザーは制御層に直接アクセスし、制御層はデータベースを直接操作できます。

servlet--CRUD-->数据库
弊端:程序十分臃肿,不利于维护  
servlet的代码中:处理请求、响应、视图跳转、处理JDBC、处理业务代码、处理逻辑代码

架构:没有什么是加一层解决不了的!
程序猿调用
↑
JDBC (实现该接口)
↑
Mysql Oracle SqlServer ....(不同厂商)

10.2. MVC 3 層アーキテクチャ

画像.png
モデル

  • 業務処理:ビジネスロジック(サービス)
  • データ永続層: CRUD (Dao - データ永続オブジェクト)

ビュー

  • 表示データ
  • サーブレットリクエストを開始するためのリンクを提供します (a、form、img...)

コントローラ(サーブレット)

  • ユーザーのリクエストを受信します: (リクエスト: リクエストパラメータ、セッション情報...)
  • それをビジネス層に渡して、対応するコードを処理します
  • ビューのジャンプを制御する
登录--->接收用户的登录请求--->处理用户的请求(获取用户登录的参数,username,password)---->交给业务层处理登录业务(判断用户名密码是否正确:事务)--->Dao层查询用户名和密码是否正确-->数据库

11. フィルター(ポイント)

たとえば、Shiro セキュリティ フレームワーク テクノロジーは、
フィルターを使用して実装されています。フィルターは、Web サイトのデータをフィルターするために使用されます。

  • 中国語の文字化けを処理する
  • ログイン認証…。

(たとえば、インターネット上の悪口をフィルタリングするために、私は自分自身を 0-0 で *** します)
画像.png
フィルタリングの開発手順:

  1. ガイドパッケージ
    <dependencies>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>2.5</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>javax.servlet.jsp-api</artifactId>
            <version>2.3.3</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet.jsp.jstl</groupId>
            <artifactId>jstl-api</artifactId>
            <version>1.2</version>
        </dependency>
        <dependency>
            <groupId>taglibs</groupId>
            <artifactId>standard</artifactId>
            <version>1.1.2</version>
        </dependency>
    
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.25</version>
        </dependency>
    </dependencies>
  1. フィルターを書く
    1. 間違ったガイドパッケージを作成しないでください(注)

画像.png
Filter インターフェイスを実装し、対応するメソッドを書き換えます。

package org.example.filter;

import javax.servlet.*;
import java.io.IOException;

public class CharacterEncodingFilter implements Filter {
    
    

    //初始化:web服务器启动,就以及初始化了,随时等待过滤对象出现!
    public void init(FilterConfig filterConfig) throws ServletException {
    
    
        System.out.println("CharacterEncodingFilter初始化");
    }

    //Chain : 链
       /*
       1. 过滤中的所有代码,在过滤特定请求的时候都会执行
       2. 必须要让过滤器继续执行
           chain.doFilter(request,response);
        */
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
    
    
        request.setCharacterEncoding("utf-8");
        response.setCharacterEncoding("utf-8");
        response.setContentType("text/html;charset=UTF-8");

        System.out.println("CharacterEncodingFilter执行前....");
        chain.doFilter(request,response); //让我们的请求继续走,如果不写,程序到这里就被拦截停止!
        System.out.println("CharacterEncodingFilter执行后....");
    }

    //销毁:web服务器关闭的时候,过滤器会销毁
    public void destroy() {
    
    
        System.out.println("CharacterEncodingFilter销毁");
    }
}

  1. web.xml でフィルターを構成する
<filter>
  <filter-name>CharacterEncodingFilter</filter-name>
  <filter-class>org.example.filter.CharacterEncodingFilter</filter-class>
</filter>
<filter-mapping>
  <filter-name>CharacterEncodingFilter</filter-name>
  <!--只要是下方的请求,就会经过过滤器-->
  <url-pattern>/servlet/*</url-pattern>
</filter-mapping>

12. リスナー

リスナー インターフェイスを実装します (n 種類のリスナーがあります)。

  1. リスナーを作成して、リスナーのインターフェイス...依存するjarパッケージを実装します。画像.png
  2. web.xmlにリスナーを登録する
  3. 使うかどうかは状況次第!
//统计网站在线人数 : 统计session
public class OnlineCountListener implements HttpSessionListener {
    
    

    //创建session监听: 看你的一举一动
    //一旦创建Session就会触发一次这个事件!
    public void sessionCreated(HttpSessionEvent se) {
    
    
        ServletContext ctx = se.getSession().getServletContext();

        System.out.println(se.getSession().getId());

        Integer onlineCount = (Integer) ctx.getAttribute("OnlineCount");

        if (onlineCount==null){
    
    
            onlineCount = new Integer(1);
        }else {
    
    
            int count = onlineCount.intValue();
            onlineCount = new Integer(count+1);
        }

        ctx.setAttribute("OnlineCount",onlineCount);

    }

    //销毁session监听
    //一旦销毁Session就会触发一次这个事件!
    public void sessionDestroyed(HttpSessionEvent se) {
    
    
        ServletContext ctx = se.getSession().getServletContext();

        Integer onlineCount = (Integer) ctx.getAttribute("OnlineCount");

        if (onlineCount==null){
    
    
            onlineCount = new Integer(0);
        }else {
    
    
            int count = onlineCount.intValue();
            onlineCount = new Integer(count-1);
        }

        ctx.setAttribute("OnlineCount",onlineCount);

    }


    /*
Session销毁:
1. 手动销毁  getSession().invalidate();
2. 自动销毁
*/
}
<!--注册监听器-->
<listener>
  <listener-class>com.kuang.listener.OnlineCountListener</listener-class>
</listener>
当前在线人数:<%=this.getServletConfig().getServletContext().getAttribute("OnlineCount")%>

13. フィルターとリスナーの一般的な用途

リスナー: GUI プログラミングでよく使用されます。

public class TestPanel {
    
    
    public static void main(String[] args) {
    
    
        Frame frame = new Frame("中秋节快乐");  //新建一个窗体
        Panel panel = new Panel(null); //面板
        frame.setLayout(null); //设置窗体的布局

        frame.setBounds(300,300,500,500);
        frame.setBackground(new Color(0,0,255)); //设置背景颜色

        panel.setBounds(50,50,300,300);
        panel.setBackground(new Color(0,255,0)); //设置背景颜色

        frame.add(panel);

        frame.setVisible(true);

        //监听事件,监听关闭事件
        frame.addWindowListener(new WindowAdapter() {
    
    
            @Override
            public void windowClosing(WindowEvent e) {
    
    
                super.windowClosing(e);
            }
        });

    }
}

ユーザーはログインした後にのみホームページに入ることができます。ユーザーがログアウトすると、ホームページにアクセスできなくなります。

  1. ユーザーがログインしたら、ユーザーのデータをSesisonに入力します。
  2. ホームページに入るとき、ユーザーがログインしているかどうかを判断する必要があります。要件: フィルターに実装されています。

画像.png

// error.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<h1>没有权限或者密码错误</h1>
<a href="./login.jsp"> 请登录</a>
</body>
</html>

// login.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>$Title$</title>
</head>
<body>
${pageContext.request.contextPath}
<form action="${pageContext.request.contextPath}/login" method="get">
    请输入用户名:<input type="text" name="username">
    <input type="submit">
</form>
</body>
</html>

// success.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<h1>登录成功</h1>
<a href="${pageContext.request.contextPath}/logout">注销</a>
</body>
</html>
public class LoginServlet extends HttpServlet {
    
    
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    

        System.out.println("进入LoginServlet->doGet");
        System.out.println(req.getContextPath());
        // 如果是管理员登录,跳转到成功页面
        if (req.getParameter("username").equals("admin")){
    
    
            // 设置Session
            req.getSession().setAttribute("USER_SESSION",req.getSession().getId());
            // 重定向需要获得根目录
            resp.sendRedirect(req.getContextPath()+"/security/success.jsp");
        }else{
    
    
            resp.sendRedirect(req.getContextPath()+"/error.jsp");
        }
    }
}

public class LogoutServlet extends HttpServlet {
    
    
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    

        System.out.println("LogoutServlet->doGet");
        // 销毁Session 或者 移除其中一个属性(建议后者,开销小
        Object userSession = req.getSession().getAttribute("USER_SESSION");

        if (userSession!=null){
    
    
            req.getSession().removeAttribute("USER_SESSION");
            resp.sendRedirect(req.getContextPath()+"/login.jsp");
        }else {
    
    
            resp.sendRedirect(req.getContextPath()+"/error.jsp");
        }
    }
}

public class LogoutFilter implements Filter {
    
    
    public void init(FilterConfig filterConfig) throws ServletException {
    
    
    }
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
    
    
        HttpServletRequest req = (HttpServletRequest) servletRequest;
        HttpServletResponse resp = (HttpServletResponse) servletResponse;
        Object userSession = req.getSession().getAttribute("USER_SESSION");
        if (userSession==null){
    
    
            resp.sendRedirect(req.getContextPath()+"/error.jsp");
        }
        filterChain.doFilter(req,resp);
    }
    public void destroy() {
    
    
    }
}
<!--登录验证-->
<servlet>
    <servlet-name>login</servlet-name>
    <servlet-class>org.example.servlet.LoginServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>login</servlet-name>
    <url-pattern>/login</url-pattern>
</servlet-mapping>

<servlet>
    <servlet-name>logout</servlet-name>
    <servlet-class>org.example.servlet.LogoutServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>logout</servlet-name>
    <url-pattern>/logout</url-pattern>
</servlet-mapping>

<filter>
    <filter-name>LogoutFilter</filter-name>
    <filter-class>org.example.filter.LogoutFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>LogoutFilter</filter-name>
    <url-pattern>/security/*</url-pattern>
</filter-mapping>

14、JDBC

JDBC とは: Java によるデータベースへの接続!
画像.png
jar パッケージのサポートが必要です。

  • java.sql
  • javax.sql
  • mysql-connecter-java… 接続ドライバー (インポートする必要があります)

実験環境のセットアップ

CREATE DATABASE jdbc;
USE jdbc;
CREATE TABLE users(
  id INT PRIMARY KEY,
  `name` VARCHAR(40),
  `password` VARCHAR(40),
  email VARCHAR(60),
  birthday DATE
);

INSERT INTO users(id,`name`,`password`,email,birthday)
VALUES(1,'张三','123456','[email protected]','2000-01-01');
INSERT INTO users(id,`name`,`password`,email,birthday)
VALUES(2,'李四','123456','[email protected]','2000-01-01');
INSERT INTO users(id,`name`,`password`,email,birthday)
VALUES(3,'王五','123456','[email protected]','2000-01-01');


SELECT	* FROM users;

データベースの依存関係をインポートする

<!--mysql的驱动-->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.28</version>
</dependency>

IDEA でのデータベースへの接続:
画像.png
JDBC の修正された手順:

  1. ドライバーをロードする
  2. データベースに接続し、データベースを表す
  3. SQL オブジェクト ステートメントをデータベースに送信: CRUD
  4. SQLの作成(業務に応じて異なるSQL)
  5. SQLの実行
  6. 接続を閉じます (最初に開いてから閉じます)
package org.example;

import java.sql.*;

public class TestJdbc {
    
    
    public static void main(String[] args) throws ClassNotFoundException, SQLException {
    
    
        //配置信息
        //useUnicode=true&characterEncoding=utf-8 解决中文乱码
        String url="jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=utf-8";
        String username = "root";
        String password = "root";

        //1.加载驱动
        Class.forName("com.mysql.cj.jdbc.Driver");
        //2.连接数据库,代表数据库
        Connection connection = DriverManager.getConnection(url, username, password);

        //3.向数据库发送SQL的对象Statement,PreparedStatement : CRUD
        Statement statement = connection.createStatement();

        //4.编写SQL
        String sql = "select * from users";

        //5.执行查询SQL,返回一个 ResultSet  : 结果集
        ResultSet rs = statement.executeQuery(sql);

        while (rs.next()){
    
    
            System.out.println("id="+rs.getObject("id"));
            System.out.println("name="+rs.getObject("name"));
            System.out.println("password="+rs.getObject("password"));
            System.out.println("email="+rs.getObject("email"));
            System.out.println("birthday="+rs.getObject("birthday"));
        }

        //6.关闭连接,释放资源(一定要做) 先开后关
        rs.close();
        statement.close();
        connection.close();
    }
}

プリコンパイルされたSQL

package org.example;
import java.sql.*;

public class TestJdbc2 {
    
    
    public static void main(String[] args) throws Exception {
    
    
        //配置信息
        //useUnicode=true&characterEncoding=utf-8 解决中文乱码
        String url="jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=utf-8";
        String username = "root";
        String password = "root";

        //1.加载驱动
        Class.forName("com.mysql.cj.jdbc.Driver");
        //2.连接数据库,代表数据库
        Connection connection = DriverManager.getConnection(url, username, password);

        //3.编写SQL
        String sql = "insert into  users(id, name, password, email, birthday) values (?,?,?,?,?);";

        //4.预编译
        PreparedStatement preparedStatement = connection.prepareStatement(sql);

        // 注意这里第一个是ID,有没有自增,或者用不用赋值
        preparedStatement.setInt(1,4);//给第一个占位符? 的值赋值为1;
        preparedStatement.setString(2,"狂神说Java");//给第二个占位符? 的值赋值为狂神说Java;
        preparedStatement.setString(3,"123456");//给第三个占位符? 的值赋值为123456;
        preparedStatement.setString(4,"[email protected]");//给第四个占位符? 的值赋值为1;
        preparedStatement.setDate(5,new Date(new java.util.Date().getTime()));//给第五个占位符? 的值赋值为new Date(new java.util.Date().getTime());

        //5.执行SQL
        int i = preparedStatement.executeUpdate();

        if (i>0){
    
    
            System.out.println("插入成功@");
        }

        //6.关闭连接,释放资源(一定要做) 先开后关
        preparedStatement.close();
        connection.close();
    }
}

すべてが
成功するか、すべてが失敗するかのどちらかです。
ACID 原則: データのセキュリティを確保します。

开启事务
事务提交  commit()
事务回滚  rollback()
关闭事务

转账:
A:1000
B:1000

A(900)   --100-->   B(1100) 

Junit 単体テストの依存
関係

<!--单元测试-->
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.13.2</version>
</dependency>

@Test アノテーションを使用するだけでは
メソッドにのみ有効で、このアノテーションが追加されたメソッドであれば直接実行できます。
リフレクションにアノテーションを使用しますか?

import org.junit.Test;

@Test
public void test(){
    
    
    System.out.println("Hello");
}

画像.png
失敗時は赤:
画像.png
環境構築

CREATE TABLE account(
    id INT PRIMARY KEY AUTO_INCREMENT,
    `name` VARCHAR(40),
    money FLOAT
    );

INSERT INTO account(`name`,money) VALUES('A',1000);
INSERT INTO account(`name`,money) VALUES('B',1000);
INSERT INTO account(`name`,money) VALUES('C',1000);
package org.example;


import org.junit.Test;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class TestJdbc3 {
    
    

    @Test
    public void test() {
    
    
        //配置信息
        //useUnicode=true&characterEncoding=utf-8 解决中文乱码
        String url="jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=utf-8";
        String username = "root";
        String password = "root";

        Connection connection = null;

        //1.加载驱动
        try {
    
    
            Class.forName("com.mysql.cj.jdbc.Driver");
            //2.连接数据库,代表数据库
            connection = DriverManager.getConnection(url, username, password);

            //3.通知数据库开启事务,false 开启
            connection.setAutoCommit(false);

            String sql = "update account set money = money-100 where name = 'A'";
            connection.prepareStatement(sql).executeUpdate();

            //制造错误
            //int i = 1/0;

            String sql2 = "update account set money = money+100 where name = 'B'";
            connection.prepareStatement(sql2).executeUpdate();

            connection.commit();//以上两条SQL都执行成功了,就提交事务!
            System.out.println("success");
        } catch (Exception e) {
    
    
            try {
    
    
                //如果出现异常,就通知数据库回滚事务
                connection.rollback();
            } catch (SQLException e1) {
    
    
                e1.printStackTrace();
            }
            e.printStackTrace();
        }finally {
    
    
            try {
    
    
                connection.close();
            } catch (SQLException e) {
    
    
                e.printStackTrace();
            }
        }
    }
}

15. SMBMS(スーパーマーケット運営プロジェクト)

第30話~第37話 SMBMSプロジェクト実験

拡張アプリケーション

1. ファイルのアップロード

Web アプリケーションでは、ファイルのアップロードとダウンロードの機能は非常に一般的な機能ですが、今回はファイルのアップロードとダウンロードの機能を JavaWeb に実装します。

1. 準備

ファイルのアップロードの場合、ブラウザはアップロード プロセス中にストリームの形式でファイルをサーバーに送信します。
通常、Apache のオープン ソース ツール common-fileupload のファイル アップロード コンポーネントを使用することを選択します。
common-fileupload は common-io パッケージに依存しているため、このパッケージもダウンロードする必要があります。
最新の jar パッケージをダウンロードします
https://mvnrepository.com/artifact/commons-io/commons-io
https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload
画像.png

2. 使用クラスの紹介

【ファイルアップロード時の注意事項】

  1. サーバーのセキュリティを確保するには、アップロードされたファイルは、WEB-INF ディレクトリなど、外部から直接アクセスできないディレクトリに配置する必要があります。
  2. ファイルの上書きを防ぐには、アップロードされたファイルに対して一意のファイル名を生成する必要があります。
  3. アップロードされるファイルの最大サイズを制限します。
  4. アップロードされるファイルの種類を制限し、アップロードされたファイル名を受信するときにサフィックス名が正当かどうかを判断できます。

[使用するクラスの詳細説明]
ServletFileUpload は、アップロードされたファイル データを処理し、フォーム内の各入力項目をFileItemオブジェクトにカプセル化する役割を果たします。DiskFileItemFactoryオブジェクトは、 ServletFileUploadオブジェクトを使用してリクエストを解析するときに必要です。したがって、解析する前に DiskFileItemFactory オブジェクトを構築し、 ServletFileUpload オブジェクトの構築メソッドまたは setFileItemFactory()== メソッドを通じて ServletFileUpload オブジェクトの fileItemFactoryプロパティを設定する必要があります。

FileItemクラス

HTML ページ入力にはフォームが必要ですname <input type="file" name="filename">
。ファイル アップロード入力が含まれる場合は、このフォームの enctype 属性を multipart/form-data に設定する必要があります。ブラウザの
フォーム タイプが multipart/form-data の場合は、必要に応じてサーバー側でデータを取得するため、ストリームを渡すため。


<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>$Title$</title>
  </head>
  <body>
    <%--通过表单上传
      get:上传文件大小有限制
      post: 上传文件大小没有限制--%>
      <form action = "" method = "post" enctype="multipart/form-data">
        上传用户:<input type="text" name="username"><br/>
        <p><input type="file" name="file1"></p>
        <p><input type="file" name="file2"></p>
        <p><input type="submit"> |<input type="reset"></p>
      </form>
  </body>
</html>

【一般的な手法の紹介】

//isFormField方法用于判断FileItem类对象封装的数据是一个普通文本表单
//还是一个文件表单,如果是普通表单字段则返回true,否则返回false
boolean isFormField();

//getFieldName方法用于返回表单标签name属性的值。
String getFieldName();

//getString方法用于将FileItem对象中保存的数据流内容以一个字符串返回
String getString();

//getName方法用于获得文件上传字段中的文件名。
String getName();

//以流的形式返回上传文件的数据内容。
InputStream getInputStream();

//delete方法用来清空FileItem类对象中存放的主体内容
//如果主体内容被保存在临时文件中,delete方法将删除该临时文件。
void delete();
ServletFileUpload クラス

ServletFileUpload は、アップロードされたファイル データを処理し。そのparseRequest(HttpServletRequest)メソッドを使用して、フォーム内の各 HTML タグを通じて送信されたデータを FileItem オブジェクトにカプセル化し、次に Returned in を使用します。リストリストの形式。この方法はシンプルで使いやすいファイルのアップロードです。

3. コードの書き方

アップロードサーブレット

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.ProgressListener;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.List;
import java.util.UUID;

public class UploadServlet extends HttpServlet {
    
    
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    

        try {
    
    
            //判断上传的文件是普通的表单还是带文件的表单
            if (!ServletFileUpload.isMultipartContent(request)) {
    
    
                return;//如果是普通文件,我们可以直接返回
            } //如果通过了这个if,说明我们的表单是带文件上传的;

            //创建上传文件的保存路径,建议在WEB-INF路径下,安全,用户无法直接访问上传的文件;
            String uploadPath = this.getServletContext().getRealPath("/WEB-INF/upload");
            File uploadFile = new File(uploadPath);
            if (!uploadFile.exists()) {
    
    //如果目录不存在,创建这样一个目录;
                uploadFile.mkdir();
            }

            //临时路径,假如文件超过了预期的大小,我们就把他放到一个临时文件中,过几天自动删除,或者提醒用户转存为永久
            String tmpPath = this.getServletContext().getRealPath("/WEB-INF/tmp");
            File file = new File(tmpPath);
            if (!file.exists()) {
    
    //如果目录不存在,创建这样一个目录;
                file.mkdir();
            }

            //处理上传的文件,一般都需要通过流来获取,我们可以使用request.getInputStream(),原生态的文件上传流获取,十分麻烦
            //但是我们都建议使用 Apache的文件上传组件来实现,common-fileupload,它需要依赖于 commons-io组件;

            //1.创建DiskFileItemFactory对象,处理文件上传路径或者大小限制的;
            DiskFileItemFactory factory = getDiskFileItemFactory(file);
            //2.获取ServletFileUpload
            ServletFileUpload upload = getServletFileUpload(factory);
            //3.处理上传的文件
            String msg = uploadParseRequest(upload, request, uploadPath);

            //servlet请求转发消息
            request.setAttribute("msg",msg);
            request.getRequestDispatcher("msg.jsp").forward(request,response);

        } catch (FileUploadException e) {
    
    
            e.printStackTrace();
        }

    }


    public static DiskFileItemFactory getDiskFileItemFactory(File file) {
    
    
        DiskFileItemFactory factory = new DiskFileItemFactory();
        //通过这个工厂设置一个缓冲区,当上传的文件大于这个缓冲区的时候,将他放到临时文件中;
        factory.setSizeThreshold(1024 * 1024); //缓存区大小为1M
        factory.setRepository(file);//临时目录的保存目录,需要一个File
        return factory;
    }

    public static ServletFileUpload getServletFileUpload(DiskFileItemFactory factory) {
    
    
        ServletFileUpload upload = new ServletFileUpload(factory);
        //监听文件上传进度;
        upload.setProgressListener(new ProgressListener() {
    
    
            @Override
            //pBytesRead:已经读取到的文件大小
            //pContentLength : 文件大小
            public void update(long pBytesRead, long pContentLength, int pItems) {
    
    
                System.out.println("总大小:" + pContentLength + "已上传:" + pBytesRead);
            }
        });

        //处理乱码问题
        upload.setHeaderEncoding("UTF-8");
        //设置单个文件的最大值
        upload.setFileSizeMax(1024 * 1024 * 10);
        //设置总共能够上传文件的大小
        //1024 = 1kb * 1024 = 1M * 10 = 10M
        upload.setSizeMax(1024 * 1024 * 10);

        return upload;
    }


    public static String uploadParseRequest(ServletFileUpload upload,HttpServletRequest request,String uploadPath)
    throws FileUploadException, IOException {
    
    

        String msg = "";

        //3.把前端请求解析,封装成一个FileItem对象
        List<FileItem> fileItems = upload.parseRequest(request);
        for (FileItem fileItem : fileItems) {
    
    
            if (fileItem.isFormField()){
    
     //判断上传的文件是普通的表单还是带文件的表单
                //getFieldName指的是前端表单控件的name;
                String name = fileItem.getFieldName();
                String value = fileItem.getString("UTF-8"); //处理乱码
                System.out.println(name+":"+value);
            }else {
    
     //判断它是上传的文件

                //=======================处理文件===============================//

                //拿到文件名字
                String uploadFileName = fileItem.getName();
                System.out.println("上传的文件名:"+uploadFileName);

                if (uploadFileName.trim().equals("")||uploadFileName==null){
    
    
                    continue;
                }

                //获得上传的文件名  /images/girl/paojie.png
                String fileName = uploadFileName.substring(uploadFileName.lastIndexOf("\\") + 1);
                //获得文件的后缀名
                String fileExtName = uploadFileName.substring(uploadFileName.lastIndexOf(".") + 1);
                /*
如果文件后缀名 fileExtName 不是我们所需要的
就直接return,不处理,告诉用户文件类型不对。
*/

                System.out.println("文件信息 [件名:"+fileName+"---文件类型"+fileExtName+"]");

                //可以使用UUID(唯一识别的通用码),保证文件名唯一;
                //UUID.randomUUID(),随机生一个唯一识别的通用码;
                String uuidPath = UUID.randomUUID().toString();

                //=======================处理文件完毕===============================//

                //存到哪? uploadPath
                //文件真实存在的路径 realPath
                String realPath =   uploadPath+"\\"+uuidPath;
                //给每个文件创建一个对应的文件夹
                File realPathFile = new File(realPath);
                if (!realPathFile.exists()){
    
    
                    realPathFile.mkdir();
                }

                //=======================存放地址完毕===============================//

                //获得文件上传的流
                InputStream inputStream = fileItem.getInputStream();

                //创建一个文件输出流
                //realPath = 真实的文件夹;
                //差了一个文件; 加上输出文件的名字+"/"+uuidFileName
                FileOutputStream fos = new FileOutputStream(realPath+"\\"+fileName);

                //创建一个缓冲区
                byte[] buffer = new byte[1024*1024];

                //判断是否读取完毕
                int len = 0;
                //如果大于0说明还存在数据;
                while ((len=inputStream.read(buffer))>0){
    
    
                    fos.write(buffer,0,len);
                }

                //关闭流
                fos.close();
                inputStream.close();

                msg = "文件上传成功!";
                fileItem.delete(); //上传成功,清除临时文件
                //=======================文件传输完毕===============================//
            }
        }

        return msg;
    }
}

アップロード.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
  <html>
    <head>
      <title>文件上传</title>
    </head>
    <body>
      <form action="${pageContext.request.contextPath}/upload.do" enctype="multipart/form-data" method="post">
        上传用户:<input type="text" name="username"><br/>
        上传文件1:<input type="file" name="file1"><br/>
        上传文件2:<input type="file" name="file2"><br/>
        <input type="submit" value="提交">
      </form>
    </body>
  </html>

msg.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
  <html>
    <head>
      <title>消息提示</title>
    </head>
    <body>
      ${msg}
    </body>
  </html>

web.xml

<?xml version="1.0" encoding="UTF-8"?> 
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"         
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"          
  xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee 
  http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"          
  version="4.0">    
  <servlet>         
    <servlet-name>upload</servlet-name>         
    <servlet-class>com.kuang.servlet.UploadFileServlet</servlet-class>     
  </servlet>     
  <servlet-mapping>         
    <servlet-name>upload</servlet-name>         
    <url-pattern>/upload.do</url-pattern>     
  </servlet-mapping> </web-app> 

メールの送受信

Eメール

メール機能をネットワーク上に実装するには、専用のメールサーバーが必要です。
これらのメール サーバーは現実の郵便局に似ており、主にユーザーが配信したメールを受信し、メール受信者のメール ボックスに配信する役割を果たします。
SMTPサーバー アドレス: 通常はsmtp.xxx.comたとえば 163 メールボックスは smtp.163.comqq メールボックスは smtp.qq.com です
メールアドレス(E-Mailアドレス)を取得するには、メールサーバーに申請する必要があります。たとえば、QQ メールボックスを使用したい場合は、メールボックス機能をアクティブにする必要があります。
画像.png

転送プロトコル

電子メール送信用のSMTP プロトコル
:
通常、ユーザーの SMTP 要求 (電子メール送信要求) を処理するサーバーを SMTP サーバー (電子メール送信サーバー) と呼びます。
メールを受信するためのPOP3 プロトコル
:
通常、ユーザーの Pop3 リクエスト (メール受信リクエスト) を処理するサーバーを POP3 サーバー (メール受信サーバー) と呼びます。
電子メールの送受信の原則
画像.png

  1. Da Kuangshen は、SMTP プロトコルを通じて Smtp サーバーに接続し、NetEase のメール サーバーに電子メールを送信します。
  2. NetEase の分析により、QQ のメール サーバーにアクセスし、SMTP プロトコルを通じてメールを QQ の Smtp サーバーに転送する必要があることが判明しました。
  3. QQ は受信した電子メールを電子メール アカウント [email protected] のスペースに保存します。
  4. Xiaokuangshen は Pop3 プロトコルを通じて Pop3 サーバーに接続し、電子メールを収集します
  5. 電子メール アカウント [email protected] のスペースから電子メールを取得します。
  6. Pop3 サーバーは取得した電子メールを小さな狂った神に送信します

[注意] 受信者アドレス、送信者アドレスなどの情報が正しく、コンソールに正しい情報が出力されても、受信箱で情報を受信できない場合があります。これは、受信トレイ サーバーが送信した電子メールを拒否した可能性があるためです (たとえば、電子メールが広告であると判断された場合)。この時点では、ゴミ箱にある可能性がありますが、見つからない可能性があります。解決策は、重複したメール内容を複数回送信しないこと、または受信トレイを変更しないことです。

Java を使用して電子メールを送信する

概要

このコードを使用して電子メールの送信を完了します。登録時にアカウントアクティベーションのメール送信が必要になったり、OAプロジェクトでのタスクリマインダーにメールを利用したりするなど、実際のプロジェクトでも広く活用されています。
Java を使用して電子メールを送信するのは非常に簡単ですが、最初に JavaMail API と Java Activation Framework を準備する必要があります。
2 つの jar パッケージを取得します。

  • mail.jar
  • アクティベーション.jar

JavaMail は、Java 開発者がアプリケーションに電子メールの送受信機能を実装することを容易にするために、Sun Corporation (現在は Oracle に買収) によって提供されている標準開発パッケージのセットです。前述の SMTP などの一般的に使用される電子メール プロトコルをサポートしています。POP3、IMAP、やMIMEなど。JavaMail API を使用して電子メールを作成する場合、電子メールの基礎となる実装の詳細を考慮する必要はなく、JavaMail 開発キット内の対応する API クラスを呼び出すだけで済みます。
まず簡単な電子メールを送信して、コンピューターがネットワークに接続できるかどうかを確認します。

  • メール サーバーのネットワーク接続情報を含む Session オブジェクトを作成します。
  • 電子メールの内容を表す Message オブジェクトを作成します。
  • Transport オブジェクトを作成し、サーバーに接続し、メッセージを送信して、接続を閉じます。

コアクラスは大きく分けて4つあり、プログラムを書く際にはこの4つのコアクラスを覚えておくとJavaメール処理プログラムを書きやすくなります。
画像.png

プレーンテキストメール

まず、jar パッケージ QQ メールボックスをプロジェクトにインポートして、
画像.png
対応するアクセス許可を取得します。QQ
メールボックスにはセキュリティ検証が必要であり、対応するアクセス許可を取得する必要があります。QQ
メールボックス –> メールボックス設定 –> アカウント
画像.png
画像.png
作成テスト コード

import com.sun.mail.util.MailSSLSocketFactory;

import java.util.*;
import javax.mail.*;
import javax.mail.internet.*;

public class SendEmail {
    
    
    public static void main(String[] args) throws Exception {
    
    
        Properties prop = new Properties();
        prop.setProperty("mail.host", "smtp.qq.com");  设置QQ邮件服务器
        prop.setProperty("mail.transport.protocol", "smtp"); // 邮件发送协议
        prop.setProperty("mail.smtp.auth", "true"); // 需要验证用户名密码

        // 关于QQ邮箱,还要设置SSL加密,加上以下代码即可
        MailSSLSocketFactory sf = new MailSSLSocketFactory();
        sf.setTrustAllHosts(true);
        prop.put("mail.smtp.ssl.enable", "true");
        prop.put("mail.smtp.ssl.socketFactory", sf);

        //使用JavaMail发送邮件的5个步骤
        //创建定义整个应用程序所需的环境信息的 Session 对象

        Session session = Session.getDefaultInstance(prop, new Authenticator() {
    
    
            public PasswordAuthentication getPasswordAuthentication() {
    
    

                //发件人邮件用户名、授权码
                return new PasswordAuthentication("[email protected]", "授权码");

            }
        });

        //开启Session的debug模式,这样就可以查看到程序发送Email的运行状态
        session.setDebug(true);
        //2、通过session得到transport对象
        Transport ts = session.getTransport();
        //3、使用邮箱的用户名和授权码连上邮件服务器
        ts.connect("smtp.qq.com", "[email protected]", "授权码");
        //4、创建邮件
        //创建邮件对象
        MimeMessage message = new MimeMessage(session);
        //指明邮件的发件人
        message.setFrom(new InternetAddress("[email protected]"));
        //指明邮件的收件人,现在发件人和收件人是一样的,那就是自己给自己发
        message.setRecipient(Message.RecipientType.TO, new InternetAddress("[email protected]"));
        //邮件的标题
        message.setSubject("只包含文本的简单邮件");
        //邮件的文本内容
        message.setContent("你好啊!", "text/html;charset=UTF-8");
        //5、发送邮件
        ts.sendMessage(message, message.getAllRecipients());
        ts.close();
    }
}

写真や添付ファイルを含むメール

まず、2 つのクラスと 1 つの名詞について理解しましょう。
MIME (多目的インターネット メール拡張タイプ)
MimeBodyPart クラス
javax.mail.internet.MimeBodyPart クラスは、MimeMessage クラスと同様に、Part インターフェイスから継承される MIME メッセージを表します。
MimeMultipart クラス
javax.mail.internet.MimeMultipart は、抽象クラス Multipart の実装サブクラスであり、複数の MIME メッセージを結合するために使用されます。MimeMultipart オブジェクトには、MIME メッセージを表す複数の MimeBodyPart オブジェクトを含めることができます。
画像.png
埋め込み画像を含むメールの作成
前の例では、HTML またはプレーン テキスト コンテンツを単独で使用していましたが、一部の画像をプレーン テキストでインライン表示する必要がある場合があるため、プレーン テキストと埋め込み画像を組み合わせる必要があります。そしてそれを Mimemultipart オブジェクトに保存します。

import com.sun.mail.util.MailSSLSocketFactory;

import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import java.util.Properties;

public class SendImageEmail {
    
    
    public static void main(String[] args) throws Exception {
    
    
        Properties prop = new Properties();
        prop.setProperty("mail.host", "smtp.qq.com");  设置QQ邮件服务器
        prop.setProperty("mail.transport.protocol", "smtp"); // 邮件发送协议
        prop.setProperty("mail.smtp.auth", "true"); // 需要验证用户名密码

        // 关于QQ邮箱,还要设置SSL加密,加上以下代码即可
        MailSSLSocketFactory sf = new MailSSLSocketFactory();
        sf.setTrustAllHosts(true);
        prop.put("mail.smtp.ssl.enable", "true");
        prop.put("mail.smtp.ssl.socketFactory", sf);

        //使用JavaMail发送邮件的5个步骤
        //1、创建定义整个应用程序所需的环境信息的 Session 对象
        Session session = Session.getDefaultInstance(prop, new Authenticator() {
    
    
            public PasswordAuthentication getPasswordAuthentication() {
    
    
                //发件人邮件用户名、授权码
                return new PasswordAuthentication("[email protected]", "授权码");
            }
        });

        //开启Session的debug模式,这样就可以查看到程序发送Email的运行状态
        session.setDebug(true);
        
        //2、通过session得到transport对象
        Transport ts = session.getTransport();
        //3、使用邮箱的用户名和授权码连上邮件服务器
        ts.connect("smtp.qq.com", "[email protected]", "授权码");
        //4、创建邮件
        //创建邮件
        MimeMessage message = new MimeMessage(session);
        // 设置邮件的基本信息
        //发件人
        message.setFrom(new InternetAddress("[email protected]"));
        //收件人
        message.setRecipient(Message.RecipientType.TO, new InternetAddress("[email protected]"));
    //邮件标题
    message.setSubject("带图片的邮件");
    // 准备邮件数据
    // 准备图片数据
    MimeBodyPart image = new MimeBodyPart();
    DataHandler dh = new DataHandler(new FileDataSource("src/resources/bz.jpg"));
    image.setDataHandler(dh);
    image.setContentID("bz.jpg");
    // 准备正文数据
    MimeBodyPart text = new MimeBodyPart();
    text.setContent("这是一封邮件正文带图片<img src='cid:bz.jpg'>的邮件", "text/html;charset=UTF-8");
    // 描述数据关系
    MimeMultipart mm = new MimeMultipart();
    mm.addBodyPart(text);
    mm.addBodyPart(image);
    mm.setSubType("related");
    //设置到消息中,保存修改
    message.setContent(mm);
    message.saveChanges();
    //5.发送邮件
    ts.sendMessage(message, message.getAllRecipients());
    ts.close();
    }
}

写真や添付ファイルを含む複雑なメールを送信する

import com.sun.mail.util.MailSSLSocketFactory;



 



import javax.activation.DataHandler;



import javax.activation.FileDataSource;



import javax.mail.*;



import javax.mail.internet.InternetAddress;



import javax.mail.internet.MimeBodyPart;



import javax.mail.internet.MimeMessage;



import javax.mail.internet.MimeMultipart;



import java.security.GeneralSecurityException;



import java.util.Properties;



 



public class SendFileMail {
    
    



    public static void main(String[] args) throws MessagingException, GeneralSecurityException {
    
    



 



        //创建一个配置文件保存并读取信息



        Properties properties = new Properties();



 



        //设置qq邮件服务器



        properties.setProperty("mail.host","smtp.qq.com");



        //设置发送的协议



        properties.setProperty("mail.transport.protocol","smtp");



        //设置用户是否需要验证



        properties.setProperty("mail.smtp.auth", "true");



 



 



        //=================================只有QQ存在的一个特性,需要建立一个安全的链接



        // 关于QQ邮箱,还要设置SSL加密,加上以下代码即可



        MailSSLSocketFactory sf = new MailSSLSocketFactory();



        sf.setTrustAllHosts(true);



        properties.put("mail.smtp.ssl.enable", "true");



        properties.put("mail.smtp.ssl.socketFactory", sf);



 



        //=================================准备工作完毕



 



        //1.创建一个session会话对象;



        Session session = Session.getDefaultInstance(properties, new Authenticator() {
    
    



            @Override



            protected PasswordAuthentication getPasswordAuthentication() {
    
    



                return new PasswordAuthentication("[email protected]", "授权码");



            }



        });



 



        //可以通过session开启Dubug模式,查看所有的过程



        session.setDebug(true);



 



 



        //2.获取连接对象,通过session对象获得Transport,需要捕获或者抛出异常;



        Transport tp = session.getTransport();



 



        //3.连接服务器,需要抛出异常;



        tp.connect("smtp.qq.com","[email protected]","授权码");



 



        //4.连接上之后我们需要发送邮件;



        MimeMessage mimeMessage = imageMail(session);



 



        //5.发送邮件



        tp.sendMessage(mimeMessage,mimeMessage.getAllRecipients());



 



        //6.关闭连接



        tp.close();



 



    }



 



 



    public static MimeMessage imageMail(Session session) throws MessagingException {
    
    



 



        //消息的固定信息



        MimeMessage mimeMessage = new MimeMessage(session);



 



        //邮件发送人



        mimeMessage.setFrom(new InternetAddress("[email protected]"));



        //邮件接收人,可以同时发送给很多人,我们这里只发给自己;



        mimeMessage.setRecipient(Message.RecipientType.TO, new InternetAddress("[email protected]"));



        mimeMessage.setSubject("我也不知道是个什么东西就发给你了"); //邮件主题



 



 



        /*



        编写邮件内容



        1.图片



        2.附件



        3.文本



         */



 



        //图片



        MimeBodyPart body1 = new MimeBodyPart();



        body1.setDataHandler(new DataHandler(new FileDataSource("src/resources/yhbxb.png")));



        body1.setContentID("yhbxb.png"); //图片设置ID



 



        //文本



        MimeBodyPart body2 = new MimeBodyPart();



        body2.setContent("请注意,我不是广告<img src='cid:yhbxb.png'>","text/html;charset=utf-8");



 



        //附件



        MimeBodyPart body3 = new MimeBodyPart();



        body3.setDataHandler(new DataHandler(new FileDataSource("src/resources/log4j.properties")));



        body3.setFileName("log4j.properties"); //附件设置名字



 



        MimeBodyPart body4 = new MimeBodyPart();



        body4.setDataHandler(new DataHandler(new FileDataSource("src/resources/1.txt")));



        body4.setFileName(""); //附件设置名字



 



        //拼装邮件正文内容



        MimeMultipart multipart1 = new MimeMultipart();



        multipart1.addBodyPart(body1);



        multipart1.addBodyPart(body2);



        multipart1.setSubType("related"); //1.文本和图片内嵌成功!



 



        //new MimeBodyPart().setContent(multipart1); //将拼装好的正文内容设置为主体



        MimeBodyPart contentText =  new MimeBodyPart();



        contentText.setContent(multipart1);



 



        //拼接附件



        MimeMultipart allFile =new MimeMultipart();



        allFile.addBodyPart(body3); //附件



        allFile.addBodyPart(body4); //附件



        allFile.addBodyPart(contentText);//正文



        allFile.setSubType("mixed"); //正文和附件都存在邮件中,所有类型设置为mixed;



 



 



        //放到Message消息中



        mimeMessage.setContent(allFile);



        mimeMessage.saveChanges();//保存修改



 



 



        return mimeMessage;



 



    }



 



}

JavaWebメール送信

現在、多くの Web サイトでユーザー登録機能が提供されており、通常、登録が完了すると、登録 Web サイトからメールが届きます。電子メールの内容には、登録されたユーザー名とパスワード、アカウントをアクティブ化するためのハイパーリンクなどの情報が含まれる場合があります。今回はそのような機能も実装します. ユーザーが登録に成功すると, ユーザーの登録情報がユーザーの登録したメールボックスにメールの形式で送信されます. メール送信機能を実装するには JavaMail を使用する必要があります.
コード:

  1. 新しい JavaWeb プロジェクトを作成し、Tomcat を構成し、jar パッケージを追加します
    画像.png
  2. 対応するユーザーエンティティクラスを記述します
package com.kuang.pojo;



 



public class User {
    
    



 



    private String username;



    private String password;



    private String email;



 



    public User() {
    
    



    }



 



    public User(String username, String password, String email) {
    
    



        this.username = username;



        this.password = password;



        this.email = email;



    }



 



    public String getUsername() {
    
    



        return username;



    }



    public void setUsername(String username) {
    
    



        this.username = username;



    }



    public String getPassword() {
    
    



        return password;



    }



    public void setPassword(String password) {
    
    



        this.password = password;



    }



    public String getEmail() {
    
    



        return email;



    }



    public void setEmail(String email) {
    
    



        this.email = email;



    }



 



    @Override



    public String toString() {
    
    



        return "User{" +



                "username='" + username + '\'' +



                ", password='" + password + '\'' +



                ", email='" + email + '\'' +



                '}';



    }



}
  1. フロントエンド登録ページ
<%@ page contentType="text/html;charset=UTF-8" language="java" %>



<html>



<head>



    <title>注册</title>



</head>



<body>



 



<form action="${pageContext.request.contextPath}/RegisterServlet.do" method="post">



    用户名:<input type="text" name="username"><br/>



    密码:<input type="password" name="password"><br/>



    邮箱:<input type="text" name="email"><br/>



    <input type="submit" value="注册">



</form>



 



</body>



</html>
  1. メール送信ツール
package com.kuang.utils;



 



import com.kuang.pojo.User;



import com.sun.mail.util.MailSSLSocketFactory;



 



import javax.mail.*;



import javax.mail.internet.InternetAddress;



import javax.mail.internet.MimeMessage;



import java.util.Properties;



 



public class Sendmail extends Thread {
    
    



 



    //用于给用户发送邮件的邮箱



    private String from = "[email protected]";



    //邮箱的用户名



    private String username = "[email protected]";



    //邮箱的密码



    private String password = "授权码";



    //发送邮件的服务器地址



    private String host = "smtp.qq.com";



 



    private User user;



    public Sendmail(User user){
    
    



        this.user = user;



    }



 



    //重写run方法的实现,在run方法中发送邮件给指定的用户



    @Override



    public void run() {
    
    



        try{
    
    



            Properties prop = new Properties();



            prop.setProperty("mail.host", host);



            prop.setProperty("mail.transport.protocol", "smtp");



            prop.setProperty("mail.smtp.auth", "true");



 



            // 关于QQ邮箱,还要设置SSL加密,加上以下代码即可



            MailSSLSocketFactory sf = new MailSSLSocketFactory();



            sf.setTrustAllHosts(true);



            prop.put("mail.smtp.ssl.enable", "true");



            prop.put("mail.smtp.ssl.socketFactory", sf);



 



            //1、创建定义整个应用程序所需的环境信息的 Session 对象



            Session session = Session.getDefaultInstance(prop, new Authenticator() {
    
    



                public PasswordAuthentication getPasswordAuthentication() {
    
    



                    //发件人邮件用户名、授权码



                    return new PasswordAuthentication("[email protected]", "授权码");



                }



            });



 



            //开启Session的debug模式,这样就可以查看到程序发送Email的运行状态



            session.setDebug(true);



 



            //2、通过session得到transport对象



            Transport ts = session.getTransport();



 



            //3、使用邮箱的用户名和授权码连上邮件服务器



            ts.connect(host, username, password);



 



            //4、创建邮件



            MimeMessage message = new MimeMessage(session);



            message.setFrom(new InternetAddress(from)); //发件人



            message.setRecipient(Message.RecipientType.TO, new InternetAddress(user.getEmail())); //收件人



            message.setSubject("用户注册邮件"); //邮件的标题



 



            String info = "恭喜您注册成功,您的用户名:" + user.getUsername() + ",您的密码:" + user.getPassword() + ",请妥善保管,如有问题请联系网站客服!!";



 



            message.setContent(info, "text/html;charset=UTF-8");



            message.saveChanges();



 



            //发送邮件



            ts.sendMessage(message, message.getAllRecipients());



            ts.close();



        }catch (Exception e) {
    
    



            throw new RuntimeException(e);



        }



    }



}
  1. 対応するサーブレット処理クラスを作成します。
package com.kuang.servlet;



 



import com.kuang.pojo.User;



import com.kuang.utils.Sendmail;



 



import javax.servlet.ServletException;



import javax.servlet.http.HttpServlet;



import javax.servlet.http.HttpServletRequest;



import javax.servlet.http.HttpServletResponse;



import java.io.IOException;



 



public class RegisterServlet extends HttpServlet {
    
    



    @Override



    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    



        try {
    
    



            //接收用户请求,封装成对象



            String username = request.getParameter("username");



            String password = request.getParameter("password");



            String email = request.getParameter("email");



            User user = new User(username,password,email);



 



            //用户注册成功之后,给用户发送一封邮件



            //我们使用线程来专门发送邮件,防止出现耗时,和网站注册人数过多的情况;



            Sendmail send = new Sendmail(user);



            //启动线程,线程启动之后就会执行run方法来发送邮件



            send.start();



 



            //注册用户



            request.setAttribute("message", "注册成功,我们已经发了一封带了注册信息的电子邮件,请查收!如网络不稳定,可能过会儿才能收到!!");



            request.getRequestDispatcher("info.jsp").forward(request, response);



        } catch (Exception e) {
    
    



            e.printStackTrace();



            request.setAttribute("message", "注册失败!!");



            request.getRequestDispatcher("info.jsp").forward(request, response);



        }



    }



 



 



    @Override



    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    



        doGet(req, resp);



    }



}
  1. web.xmlを構成する
<?xml version="1.0" encoding="UTF-8"?>



<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"



         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"



         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"



         version="4.0">



    <servlet>



        <servlet-name>register</servlet-name>



        <servlet-class>com.kuang.servlet.RegisterServlet</servlet-class>



    </servlet>



    



    <servlet-mapping>



        <servlet-name>register</servlet-name>



        <url-pattern>/RegisterServlet.do</url-pattern>



    </servlet-mapping>



</web-app>
  1. 成功または失敗のフィードバック送信ページ
<%@ page contentType="text/html;charset=UTF-8" language="java" %>



<html>



<head>



    <title>提示信息</title>



</head>



<body>



    ${message}



</body>



</html>

Tomcat テストを実行してください。
メールは正常に送信されました。OK!

おすすめ

転載: blog.csdn.net/qq_53517370/article/details/128861163