序文
JavaWebシリーズのチュートリアル
JavaWeb—サーブレット
シミュレーションサーブレットエッセンス
IDEAを使用してサーブレットプログラムを開発するサーブレット
オブジェクトライフサイクル
アダプタ(GenericServlet)を使用して、サーブレット
ServletConfig
サーブレット-サーブレットコンテキストHTTPプロトコルを変換します。Webサイトのウェルカムページ
の取得と投稿の違い1つはHttpServletRequestを学習します。もしそうなら、波のように小さな手を動かして収集するのもよいでしょう。これは後で確認するのにも便利です。
何かを学ぶ前に、まずそれが何であるかを理解し、次にそれを理解する必要があります。
HttpServletRequestを理解する
-
HttpServletRequestはインターフェースであり、完全修飾名:jakarta.servlet.http.HttpServletRequest
-
HttpServletRequestインターフェースは、サーブレット仕様のメンバーです。
-
HttpServletRequestインターフェースの親インターフェース:ServletRequest
パブリックインターフェイスHttpServletRequestはServletRequestを拡張します{}
実装クラス
-
HttpServletRequestインターフェースの実装クラスを作成したのは誰ですか?HttpServletRequestオブジェクトを作成したのは誰ですか?
-
テストに合格します。org.apache.catalina.connector.RequestFacadeはHttpServletRequestインターフェースを実装します
public class RequestFacade implements HttpServletRequest { }
テスト結果は、Tomcatサーバー(WEBサーバー、WEBコンテナー)がHttpServletRequestインターフェースを実装していることを示しています。これは、Tomcatサーバーがサーブレット仕様を実装していることも示しています。私たちjavawebプログラマーにとって、実際にこれを気にする必要はありません。インターフェースをプログラムするだけで済みます。私たちが気にするのは、HttpServletRequestインターフェースにあるメソッドと、これらのメソッドが実行できる機能です。!!!
パッケージ情報
-
HttpServletRequestオブジェクトにはどのような情報がありますか?どのような情報が詰め込まれていますか?
- HttpServletRequestオブジェクトは、Tomcatサーバーによって作成されます。このオブジェクトにはどのような情報がカプセル化されていますか?HTTPリクエストプロトコルをカプセル化します。
- 実際、ユーザーがリクエストを送信すると、HTTPプロトコルに従い、HTTPリクエストプロトコルが送信されます。TomcatサーバーはHTTPプロトコル内のすべての情報とデータを解析し、Tomcatサーバーはその情報をHttpServletRequestオブジェクトにカプセル化して送信します。私たちjavawebプログラマーにとってはそれです。
- Java WebプログラマーはHttpServletRequestインターフェース用にプログラミングしており、リクエストの情報はメソッドを呼び出すことで取得できます。
-
リクエストオブジェクトとレスポンスオブジェクトのライフサイクル?
- リクエストオブジェクトとレスポンスオブジェクト。一方はリクエストオブジェクトで、もう一方はレスポンスオブジェクトです。これらの2つのオブジェクトは、現在のリクエストでのみ有効です。
- 1つのリクエストは1つのリクエストに対応します。
- 2つのリクエストは2つのリクエストに対応します。
- …
HttpServletRequestインターフェースで一般的に使用されるメソッド
-
フロントエンドブラウザユーザーから送信されたデータを取得するにはどうすればよいですか?
Map<String,String[]> getParameterMap() 这个是获取Map Enumeration<String> getParameterNames() 这个是获取Map集合中所有的key String[] getParameterValues(String name) 根据key获取Map集合的value String getParameter(String name) 获取value这个一维数组当中的第一个元素。这个方法最常用。 以上的4个方法,和获取用户提交的数据有关系。
以下はメソッドのテストです
Enumeration<String> parameterNames = request.getParameterNames();
while (parameterNames.hasMoreElements()){
String s = parameterNames.nextElement();
writer.print(s+"<br>");
}
//获取所有name
Enumeration<String> parameterNames = request.getParameterNames();
while (parameterNames.hasMoreElements()){
String s = parameterNames.nextElement();
//通过name,获取value
String[] parameterValues = request.getParameterValues(s);
for (int i = 0; i < parameterValues.length; i++) {
writer.print(s+"--->"+parameterValues[i]+"<br>");
}
}
考える:
上記の方法を理解し、覚えやすくするために、現在のフォームフォームでデータを送信した後、データを自分自身で保存する方法について考えてみましょう。
フロントエンドによって送信されたデータ形式:username = abc&userpwd = 111&aihao = s&aihao = d&aihao = tt
Mapコレクションを使用して以下を保存します。
Map<String,String>
key存储String
value存储String
这种想法对吗?不对。
如果采用以上的数据结构存储会发现key重复的时候value覆盖。
key value
---------------------
username abc
userpwd 111
aihao s
aihao d
aihao tt
这样是不行的,因为map的key不能重复。
Map<String, String[]>
key存储String
value存储String[]
key value
-------------------------------
username {
"abc"}
userpwd {
"111"}
aihao {
"s","d","tt"}
注:フロントエンドフォームがデータを送信する場合、120などの「番号」が送信されると想定されますが、実際には文字列「120」の形式で送信されるため、サーバー側は「 120 "、数字ではありません。(フロントエンドは常に文字列を送信し、バックエンドは常に文字列を取得します。)
ドメインオブジェクトをリクエストする
リクエストオブジェクトは、実際には「リクエストドメイン」オブジェクトとも呼ばれます。
リクエストドメインオブジェクトとアプリケーションドメインオブジェクトを比較して学習できます
前回のブログで関連内容は既にお伝えしましたが、忘れてしまったかもしれません
前に説明したアプリケーションドメインオブジェクトを確認しましょう。
アプリケーションドメインオブジェクト
アプリケーションドメインオブジェクトとは何ですか?
サーブレットコンテキスト(サーブレットコンテキストオブジェクト。)
どのような状況で、データをServletContextアプリケーションドメインにバインドすることを検討しますか?
- まず、すべてのユーザーが共有するデータ。-現在データベーステーブルがあり、クエリされたデータをServletContextに配置するとします。今後もデータを取得したい場合は、毎回データベースに接続しなくても、ServletContextから直接データを取得できます。 、データベースとの対話およびデータベースとの対話には、IOストリーム、多数のIOストリームを使用する必要があり、効率が非常に低くなります。IOはハードディスクを読み取り、ハードディスクには磁気針があります。いいえどんなに速くても、それは機械的な振る舞いでもあります。通常、システムを最適化するときに使用します。キャッシングメカニズム
- 2番目:これが共有するデータの量は少ないです。-ServletContextはアプリケーションドメインであり、サーバーの起動時に作成され、サーバーのシャットダウン時に破棄され、常にメモリを占有します
- 3番目:この共有データには、変更操作がほとんどありません。・頻繁に改造すると糸の安全性に問題がありますが、これを回避するためにロック機構を採用しているため、効率が低下します。
- 上記の3つの条件が満たされている場合、このアプリケーションドメインオブジェクトを使用すると、プログラムの実行効率を大幅に向上させることができます。
- 実際、データをアプリケーションドメインにバインドすることは、データをキャッシュ(Cache)に入れ、ユーザーがアクセスしたときにキャッシュから直接フェッチすることと同じです。これにより、IO操作が削減され、システムのパフォーマンスが大幅に向上します。キャッシングテクノロジーは、システムパフォーマンスの重要な手段を改善することです。
どのようなキャッシングテクノロジーを見たことがありますか?
- 文字列定数プール
- 整数定数プール[-128〜127]ですが、この範囲のすべての整数オブジェクトは新しいオブジェクトを作成しなくなり、この整数定数プールから直接取得されます。システムパフォーマンスを大幅に向上させます。
-データベース接続プール(事前にN個の接続オブジェクトを作成し、コレクションに接続オブジェクトを配置し、接続オブジェクトを使用する場合はキャッシュから直接取得します。接続オブジェクトの作成プロセスは省略されます。効率が向上します。)
-スレッドプール(Tomcatサーバーはマルチスレッドをサポートしています。いわゆるスレッドプールは、事前にN個のスレッドオブジェクトを作成し、コレクションにスレッドオブジェクトを格納し、ユーザーの要求後にスレッドプールからスレッドオブジェクトを直接取得して、それらを直接使用することです。 。システムパフォーマンスの向上)
-後で、redis、mongoDBなどのキャッシュテクノロジーについて学習します。
- ServletContextでドメインを操作するには、次の3つの方法があります。
void setAttribute(String name, Object obj); // 向域当中绑定数据。
Object getAttribute(String name); // 从域当中根据name获取数据。
void removeAttribute(String name); // 将域当中绑定的数据移除
// 以上的操作类似于Map集合的操作。
Map<String, Object> map;
map.put("name", obj); // 向map集合中放key和value
Object obj = map.get("name"); // 通过map集合的key获取value
map.remove("name"); // 通过Map集合的key删除key和value这个键值对。
ドメインのリクエスト」オブジェクト
「リクエストドメイン」オブジェクトは、「アプリケーションドメイン」オブジェクトよりもスコープがはるかに小さく、ライフサイクルははるかに短いです。リクエストドメインは、1つのリクエストに対してのみ有効です。
リクエストオブジェクトリクエストは、リクエストドメインオブジェクトに対応します。リクエストが終了すると、リクエストフィールドは破棄されます。
実行原理
ドメインオブジェクトメソッドのリクエスト:
void setAttribute(String name, Object obj); // 向域当中绑定数据。
Object getAttribute(String name); // 从域当中根据name获取数据。
void removeAttribute(String name); // 将域当中绑定的数据移除
リクエストドメインとアプリケーションドメインの選択の原則
占有されるリソースが少なくなるように、可能な限り小さなドメインオブジェクトを使用することを選択します
前方
第一步:获取请求转发器对象
RequestDispatcher dispatcher = request.getRequestDispatcher("/b");
第二步:调用转发器的forward方法完成跳转/转发
dispatcher.forward(request,response);
转发是一次请求
第一步和第二步代码可以联合在一起。
request.getRequestDispatcher("/b").forward(request,response);
2つのサーブレットがデータを共有します
-
もちろん、データをServletContextアプリケーションドメインに入れることは可能ですが、アプリケーションドメインのスコープが大きすぎて、多くのリソースを消費します。使用はお勧めしません。
-
データをリクエストフィールドに入力すると、AServletはそれをBServletに転送して、AServletとBServletが同じリクエストに含まれるようにし、2つのサーブレットまたは複数のサーブレットが同じデータを共有できるようにします。
-
サーバーの正当なリソースである限り、HTML、サーブレットなどの転送が可能です。
-
注:転送するときは、パスの書き込みに注意してください。転送パスは、プロジェクト名のない「/」で始まります。
紛らわしい方法
uri?username = zhangsan&userpwd = 123&sex = 1
String username = request.getParameter( "username");
次の前に実行されている必要があります。request.setAttribute( "name"、new Object())
Object obj = request.getAttribute( "name");
上記の2つの方法の違いは何ですか。
最初の方法:ブラウザでユーザーが送信したデータを取得します
。2番目の方法:リクエストドメインにバインドされたデータを取得します。
他の方法と文字化けした問題
その他の方法
-
クライアントのIPアドレスを取得します
StringremoteAddr= request.getRemoteAddr(); -
アプリケーションのルートパスを取得します
StringcontextPath= request.getContextPath(); -
リクエストメソッドを取得し
ますStringmethod= request.getMethod(); -
リクエストのURIを取得し
ますStringuri= request.getRequestURI(); // / aaa / testRequest -
获取servletパス
文字列servletPath=request.getServletPath(); // / testRequest
文字化けした問題
プログラムを書いた後、サーバーを起動してブラウザでの実行結果を楽しみにしていることもありますが、文字が文字化けする問題があります。どうすれば解決できますか?
getリクエストは、リクエストラインでデータを送信します。
POSTリクエストは、リクエスト本文でデータを送信します。
リクエスト本文の文字セットを設定します。(明らかに、このメソッドはPOSTリクエストの文字化けの問題を処理するためのものです。このメソッドはgetリクエストの文字化けの問題を解決しません。)
Tomcat 10以降、リクエスト本文に設定される文字はデフォルトでUTF-8であり、文字セットを設定する必要はありません、文字化けの問題は表示されません。
Tomcat 9(9を含む)より前では、フロントエンドのリクエスト本文が中国語で送信され、バックエンドが文字化けした文字を取得した場合、この文字化けした文字を解決するにはどうすればよいですか?次のコードを実行します。
request.setCharacterEncoding( "UTF-8");
Tomcat9(9を含む)より前は、中国語の応答も文字化けしていましたが、文字化けした応答を解決するにはどうすればよいですか?
response.setContentType( "text / html; charset = UTF-8");
10を含むTomcat10以降、中国語に応答するときに文字化けの問題が発生しなくなりました。上記のコードでは、UTF-8を設定する必要はありません。
10以降のバージョンを含むTomcat10の詳細
に注意してください。中国語は、文字化けして表示されなくなります。(これはまた、中国人の地位の上昇を反映しています。)
リクエストの文字化けの問題を解決するにはどうすればよいですか?
getリクエストが送信されると、データはリクエスト本文ではなくリクエストラインで送信されます。
文字化けしたget要求の解決方法を解決する方法:CATALINA_HOME
/ conf / server.xml構成ファイルを変更します
注:Tomcat8以降、URIEncodingのデフォルト値はUTF-8であるため、GET要求の文字化けの問題はありません。
転送とリダイレクト(重要)
コードの違い
前方
リクエストフォワーダーオブジェクトを取得します
RequestDispatcherdispatcher = request.getRequestDispatcher( "/ dept / list")
リクエストフォワーダーオブジェクトのforwardメソッドを呼び出して、転送を完了します
dispatcher.forward(request, response);
合并一行代码
request.getRequestDispatcher("/dept/list").forward(request,
response);
转发的时候是一次请求,不管你转发了多少次。都是一次请求。
AServlet转发到BServlet,再转发到CServlet,再转发到DServlet,不管转发了多少次,都在同一个request当中。
这是因为调用forward方法的时候,会将当前的request和response对象传递给下一个Servlet。
重定向
注意:路径上要加一个项目名。为什么?
浏览器发送请求,请求路径上是需要添加项目名的。
以下这一行代码会将请求路径“/oa/dept/list”发送给浏览器
浏览器会自发的向服务器发送一次全新的请求:/oa/dept/list
response.sendRedirect("/oa/dept/list");
形式上的区别
转发(一次请求)
在浏览器地址栏上发送的请求是:http://localhost:8080/servlet10/a ,最终请求结束之后,浏览器地址栏上的地址还是这个。没变。
重定向(两次请求)
- 在浏览器地址栏上发送的请求是:http://localhost:8080/servlet10/a ,最终在浏览器地址栏上显示的地址是:http://localhost:8080/servlet10/b
- 在浏览器输入:localhost:8080/servlet09/a结果直接跳转到b
本质区别
-
转发:是由WEB服务器来控制的。A资源跳转到B资源,这个跳转动作是Tomcat服务器内部完成的。
-
リダイレクト:ブラウザによって行われます。ジャンプするリソースを決定するのはブラウザ次第です。
選び方
-
転送とリダイレクトはどのように選択する必要がありますか?いつ転送を使用し、いつリダイレクトを使用するのですか?
- 前のサーブレットのリクエストフィールドにデータがバインドされている場合は、リクエストフィールドのデータが次のサーブレットから取り出され、転送メカニズムが使用されることが望まれます。
- 残りのすべてのリクエストはリダイレクトを使用します。(リダイレクトがより多く使用されます。)
-
次のリソースにジャンプするための要件はありますか?サーブレットである必要がありますか?
- リダイレクトされたリソースがサーバー内の正当なリソースである限り、必ずしもそうとは限りません。含む:サーブレット、JSP、HTML ..
-
転送時にブラウザの更新の問題が発生します。
たとえば、データベースにデータを保存し、成功ページにジャンプしたいと考えています。転送を使用する場合、ブラウザが1回更新される限り、データベースにもう1つのデータが存在するため、望ましくありません。リダイレクトを使用する
ここでは、転送とリダイレクトに関する記事をお勧めします:転送とリダイレクト(完全な理解と要約)