リフレクション
57.リフレクションとは何ですか?
リフレクションは主に、プログラムが自身の状態または動作にアクセスし、検出し、変更する能力を指します
Javaリフレクション:
Javaランタイム環境では、どのクラスでも、このクラスがどのプロパティとメソッドを持っているかを知ることができますか?どのオブジェクトでも、そのメソッドを呼び出すことができますか
Javaリフレクションメカニズムは、主に次の機能を提供します。
-
実行時に、オブジェクトが属するクラスを決定します。
-
実行時に任意のクラスのオブジェクトを作成します。
-
実行時に任意のクラスのメンバー変数とメソッドを決定します。
-
実行時に任意のオブジェクトメソッドを呼び出します。
58. Javaシリアライゼーションとは何ですか?シリアル化はいつ必要ですか?
つまり、さまざまなオブジェクトの状態をメモリに保存すること(つまり、メソッドではなくインスタンス変数)であり、保存したオブジェクトの状態を再度読み取ることができます。独自のさまざまなメソッドを使用してオブジェクトの状態を保存できますが、Javaは、独自の方法よりも優れたオブジェクトの状態を保存するメカニズム、つまりシリアル化を提供します。
シリアル化するタイミング:
a)オブジェクトの状態をメモリ内のファイルまたはデータベースに保存する
場合; b)ソケットを使用してネットワーク上のオブジェクトを転送する
場合; c)RMIを介してオブジェクトを転送する場合;
59.動的エージェントとは何ですか?アプリケーションは何ですか?
動的プロキシ:
インターフェイスを実装するクラスのメソッドに追加の処理を追加する場合。たとえば、ログの追加、トランザクションの追加などです。このクラスのプロキシを作成できるため、その名前は新しいクラスを作成することです。このクラスには、元のクラスメソッドの関数が含まれるだけでなく、元のベースで追加の処理を行うための新しいクラスが追加されます。このプロキシクラスは定義されていません。動的に生成されます。これは、分離、柔軟性、および強力な拡張性の意味を持っています。
動的プロキシの適用:
-
春的AOP
-
プラス取引
-
権限を追加
-
ログを追加
60.動的プロキシを実装するには?
最初に、インターフェースを定義する必要があり、InvocationHandler(インターフェースへのインターフェースを実装するクラスのオブジェクトを渡す)処理クラスも必要です。別のツールクラスプロキシがあります(通常、プロキシクラスと呼ばれます。これは、彼のnewInstance()を呼び出すとプロキシオブジェクトが生成されるためです。実際、彼は単なるプロキシオブジェクトを生成するツールクラスです)。InvocationHandlerを使用し、プロキシクラスのソースコードをステッチし、コンパイルしてプロキシクラスのバイナリコードを生成し、ローダーでロードしてインスタンス化し、プロキシオブジェクトを生成して、最後に戻ります。
オブジェクトのコピー
61.クローンを使用する理由
オブジェクトを処理し、次の操作のために元のデータを保持したい場合は、オブジェクトを複製する必要があります。Javaでは、複製はクラスのインスタンスを指します。
62.オブジェクトのクローンを作成するには?
2つの方法があります。
1)。Cloneableインターフェースを実装し、Objectクラスのclone()メソッドをオーバーライドします。
2)。Serializableインターフェースを実装し、オブジェクトのシリアライゼーションとデシリアライゼーションを通じてクローンを作成すると、真のディープクローンを実現できます。コードは次のとおりです。
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
public class MyUtil {
private MyUtil() {
throw new AssertionError();
}
@SuppressWarnings("unchecked")
public static <T extends Serializable> T clone(T obj)
throws Exception {
ByteArrayOutputStream bout = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bout);
oos.writeObject(obj);
ByteArrayInputStream bin =
new ByteArrayInputStream(bout.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bin);
return (T) ois.readObject();
// 说明:调用ByteArrayInputStream
//或ByteArrayOutputStream对象的close方法没有任何意义
// 这两个基于内存的流只要垃圾回收器清理对象就能够释放资源,
//这一点不同于对外部资源(如文件流)的释放
}
}
これがテストコードです:
import java.io.Serializable;
/**
* 人类
* @author nnngu
*
*/
class Person implements Serializable {
private static final long serialVersionUID
= -9102017020286042305L;
private String name; // 姓名
private int age; // 年龄
private Car car; // 座驾
public Person(String name, int age, Car car) {
this.name = name;
this.age = age;
this.car = car;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Car getCar() {
return car;
}
public void setCar(Car car) {
this.car = car;
}
@Override
public String toString() {
return "Person [name=" + name + ",
age=" + age + ", car=" + car + "]";
}
}
/**
* 小汽车类
* @author nnngu
*
*/
class Car implements Serializable {
private static final long serialVersionUID
= -5713945027627603702L;
private String brand; // 品牌
private int maxSpeed; // 最高时速
public Car(String brand, int maxSpeed) {
this.brand = brand;
this.maxSpeed = maxSpeed;
}
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public int getMaxSpeed() {
return maxSpeed;
}
public void setMaxSpeed(int maxSpeed) {
this.maxSpeed = maxSpeed;
}
@Override
public String toString() {
return "Car [brand=" + brand + ",
maxSpeed=" + maxSpeed + "]";
}
}
class CloneTest {
public static void main(String[] args) {
try {
Person p1 = new Person("郭靖", 33,
new Car("Benz", 300));
Person p2 = MyUtil.clone(p1); // 深度克隆
p2.getCar().setBrand("BYD");
// 修改克隆的Person对象p2关联的汽车对象的品牌属性
// 原来的Person对象p1关联的汽车不会受到任何影响
// 因为在克隆Person对象时其关联的汽车对象也被克隆了
System.out.println(p1);
} catch (Exception e) {
e.printStackTrace();
}
}
}
注:シリアライゼーションとデシリアライゼーションに基づくクローン作成は、ディープクローン作成だけでなく、より重要なこととして、一般的な修飾により、クローンされるオブジェクトがシリアライゼーションをサポートしているかどうかを確認できます。このチェックは、実行時に例外がスローされるこれは、Objectクラスのcloneメソッドを使用してオブジェクトを複製するよりもはるかに優れたソリューションです。実行時に問題を残すよりも、コンパイル時に問題を公開する方が常に優れています。
63.ディープコピーとシャローコピーの違いは何ですか?
-
浅いコピーはオブジェクトの参照アドレスのみをコピーし、2つのオブジェクトは同じメモリアドレスを指すため、その中の任意の値を変更すると、他の値はそれに応じて変更されます。これは浅いコピーです(例:割り当て())
-
ディープコピーとは、オブジェクトと値をコピーすることです。2つのオブジェクトがいずれかの値を変更しても、他の値は変更されません。これはディープコピーです(例:JSON.parse()とJSON.stringify()ですが、このメソッドは関数をコピーできません)タイプ)
Java Web
64. jspとサーブレットの違いは何ですか?
-
コンパイル後、jspはサーブレットになります(JSPの本質はサーブレットです。JVMはjavaクラスのみを認識できますが、JSPコードは認識できません。Webコンテナーは、JSPコードをJVMが認識するjavaクラスにコンパイルします)。
-
jspはページの表示に優れており、サーブレットはロジック制御に優れています。
-
サーブレットには組み込みオブジェクトがありません。Jspの組み込みオブジェクトは、HttpServletRequestオブジェクト、HttpServletResponseオブジェクト、およびHttpServletオブジェクトを介して取得する必要があります。
-
Jspはサーブレットの簡略化です。Jspを使用すると、プログラマがクライアントに出力する必要があるコンテンツを完成させるだけで済みます。JspのJavaスクリプトをクラスに埋め込む方法は、Jspコンテナによって行われます。サーブレットは完全なJavaクラスであり、このクラスのServiceメソッドはクライアントへの応答を生成するために使用されます。
65. jspにはどの組み込みオブジェクトがありますか?役割は何ですか?
JSPには9つの組み込みオブジェクトがあります。
-
request:GETまたはPOSTリクエストからのパラメーターを含むクライアントのリクエストをカプセル化します。
-
response:サーバーのクライアントへの応答をカプセル化します。
-
pageContext:このオブジェクトを通じて他のオブジェクトを取得できます。
-
セッション:ユーザーのセッションをカプセル化するオブジェクト。
-
アプリケーション:サーバーの動作環境をカプセル化するオブジェクト。
-
out:サーバー応答によって出力された出力ストリームオブジェクト。
-
config:Webアプリケーションの構成オブジェクト。
-
page:JSPページ自体(Javaプログラムではこれに相当)。
-
exception:ページによってスローされた例外をカプセル化するオブジェクト。
66. jspの4つのスコープについて教えてください。
JSPの4つのスコープには、具体的には、ページ、リクエスト、セッション、およびアプリケーションが含まれます。
-
ページは、ページに関連するオブジェクトと属性を表します。
-
requestは、Webクライアントが発行したリクエストに関連するオブジェクトと属性を表します。リクエストは複数のページにまたがり、複数のWebコンポーネントを含む場合があります。ページに表示する必要がある一時データをこのスコープに配置できます。
-
セッションは、ユーザーとサーバー間で確立されたセッションに関連するオブジェクトと属性を表します。ユーザーに関連するデータは、ユーザー自身のセッションに配置する必要があります。
-
アプリケーションは、Webアプリケーション全体に関連するオブジェクトと属性を表します。これは基本的に、複数のページ、要求、セッションを含むWebアプリケーション全体にわたるグローバルスコープです。
67.セッションとcookieの違いは何ですか?
-
HTTPプロトコルはステートレスプロトコルであるため、サーバーがユーザーの状態を記録する必要がある場合、サーバーは特定のユーザーを識別するメカニズムを使用する必要があります。このメカニズムはセッションです。ショッピングカートなどの一般的なシナリオ(注文ボタンをクリックしたとき) HTTPプロトコルはステートレスであるため、どのユーザーが操作しているかはわかりません。サーバーは、特定のユーザー用に特定のセッションを作成し、このユーザーの識別とユーザーの追跡に使用して、ショッピングカート内の数を把握する必要があります。本。このセッションはサーバーに保存され、一意の識別子を持っています。セッションをサーバーに保存するには、メモリ、データベース、ファイルなど、さまざまな方法があります。クラスタリングする場合は、セッションの転送も考慮する必要があります。大規模なウェブサイトでは、通常、ユーザーセッションを保存するための専用のセッションサーバークラスタが存在します。現時点では、セッション情報はメモリに保存され、Memcachedなどの一部のキャッシュサービスが使用されます。是非、セッションを入れてください。
-
サーバーが特定の顧客をどのように識別するかについて考えますか?この時、クッキーが登場しました。HTTPリクエストのたびに、クライアントは対応するCookie情報をサーバーに送信します。実際、ほとんどのアプリケーションはCookieを使用してセッショントラッキングを実装しています。初めてセッションを作成するとき、サーバーはHTTPプロトコルでクライアントにセッションIDをCookieに記録する必要があることを通知します。セッションIDがサーバーに送信され、私はあなたが誰であるかを知っています。誰かが尋ねます、クライアントのブラウザがクッキーを無効にするとどうなりますか?通常、この場合、URL書き換えと呼ばれる手法がセッショントラッキングに使用されます。つまり、すべてのHTTPインタラクションで、URLにsid = xxxxxなどのパラメーターが追加され、サーバーはこれに基づいてユーザーを認識します。
-
Cookieは実際には、いくつかのユーザーフレンドリーなシナリオで使用できます。Webサイトに一度ログインしたことがあり、次回ログインするときにアカウント番号を再度入力したくないと想像してください。どうしますか?この情報はCookieに書き込むことができます。Webサイトにアクセスすると、Webサイトのページのスクリプトがこの情報を読み取ることができ、ユーザー名が自動的に入力されるので、ユーザーを容易にすることができます。これはCookie名の由来でもあり、ユーザーにとっては少し甘いです。つまり、セッションはサーバーに保存されたデータ構造であり、ユーザーの状態を追跡するために使用されます。このデータは、クラスター、データベース、ファイルに保存できます。Cookieは、クライアントがユーザー情報を保存するためのメカニズムであり、記録に使用されます一部のユーザー情報は、Sessionを実装する方法でもあります。
68.セッションの仕組みについて教えてください。
実際、セッションはサーバーに保存されているハッシュテーブルに似たファイルです。必要な情報が含まれており、必要なときに取り出すことができます。大きなマップと同様に、内部のキーにはユーザーのセッションIDが格納され、ユーザーはサーバーにリクエストを送信するときにこのセッションIDを取得します。このとき、対応する値を取り出すことができます。
69.クライアントがCookieを禁止している場合、セッションを使用できますか?
Cookieとセッションは、一般に2つの別個のものと見なされ、Sessionはサーバー側で状態を維持するスキームを採用し、Cookieはクライアント側で状態を維持するスキームを採用します。しかし、Cookieを無効にすると、なぜセッションを取得できないのですか?セッションはセッションIDを使用して現在のセッションに対応するサーバーセッションを決定し、セッションIDはCookieを介して渡されるため、Cookieを無効にすることはセッションIDを失うことに相当し、セッションを取得できません。
Cookieが閉じているときにユーザーがセッションを使用すると想定すると、実装方法は次のようになります。
-
php.ini設定ファイルで「session.use_trans_sid = 1」を設定するか、コンパイル時に「--enable-trans-sid」オプションを開いて、PHPがページ間でセッションIDを自動的に渡すようにします。
-
URLを介して手動で値を渡し、非表示のフォームでセッションIDを渡します。
-
セッションIDをファイル、データベースなどの形式で保存し、クロスページプロセス中に手動で呼び出します。
70. Spring MVCとStrutsの違いは何ですか?
-
さまざまな遮断メカニズム
Struts2はクラスレベルのインターセプトです。各リクエストはアクションを作成します。Springと統合する場合、Struts2のActionBeanインジェクションスコープはプロトタイプモードのプロトタイプであり、リクエストデータはセッターとゲッターを介してプロパティに注入されます。Struts2では、アクションはリクエストとレスポンスのコンテキストに対応します。パラメータを受け取る場合、属性を通じて受け取ることができます。つまり、属性パラメータは複数のメソッドで共有されます。Struts2のアクションのメソッドはURLに対応できますが、そのクラス属性はすべてのメソッドで共有されます。アノテーションや他のメソッドを使用して独自のメソッドを識別するために使用することはできず、複数のケースとしてのみ設計できます。
SpringMVCはメソッドレベルのインターセプトであり、メソッドはリクエストコンテキストに対応するため、メソッドは基本的に独立しており、リクエストとレスポンスのデータは排他的です。また、各メソッドは同時にどのURLに対応し、パラメーターの転送はメソッドに直接注入され、メソッドに固有です。処理結果は、ModeMapを介してフレームワークに返されます。Springの統合中、Spring MVCのコントローラーBeanはデフォルトでシングルトンモードのシングルトンに設定されるため、デフォルトではすべてのリクエストに対して1つのコントローラーのみが作成され、共有属性がないため、スレッドセーフです。変更するには@Scopeアノテーションを追加する必要があります。
Struts2には独自のインターセプターメカニズムがあり、SpringMVCは独立したAopメソッドを使用するため、SpringMVCよりもStruts2構成ファイルの量が多くなります。
-
基礎となるフレームワークの違い
Struts2はFilter(StrutsPrepareAndExecuteFilter)で実装され、SpringMVC(DispatcherServlet)はServletで実装されます。フィルターはコンテナーの開始後に初期化され、サービスは停止後にサーブレットよりも後にクラッシュします。サーブレットは、呼び出されると、Filter呼び出しの前に初期化され、サービスが停止すると破棄されます。
-
パフォーマンス
Struts2はクラスレベルのインターセプトです。各リクエストは新しいアクションのインスタンスに対応します。すべての属性値インジェクションをロードする必要があります。SpringMVCはゼロ構成を実装します。SpringMVCのメソッドベースのインターセプトにより、シングルトンBeanインジェクションがあります。したがって、SpringMVCの開発効率とパフォーマンスはStruts2よりも高くなっています。
-
構成の側面
Spring MVCとSpringはシームレスです。このプロジェクトの管理とセキュリティもStruts2よりも高くなっています。
71. SQLインジェクションを回避するには?
-
PreparedStatement(シンプルで効果的な方法)
-
正規表現を使用して入力パラメーターをフィルター処理する
-
文字列フィルタリング
-
JSPでこの関数を呼び出して、パケットが不正な文字であるかどうかを確認します
-
JSPページ判定コード
72. XSS攻撃とは何ですか。
XSS攻撃はCSSとも呼ばれ、クロスサイトスクリプト(クロスサイトスクリプティング攻撃)の正式名称です。原則として、攻撃者が悪意のあるHTMLコードをXSS脆弱性のあるWebサイトに入力すると、ユーザーがWebサイトを閲覧すると、このHTMLコードが自動的に実行されます。攻撃の目的を達成するために。XSS攻撃はSQLインジェクション攻撃に似ています。SQLインジェクション攻撃では、SQLステートメントは、データのクエリ/変更/削除の目的を達成するためのユーザー入力として使用されます。xss攻撃では、悪意のあるスクリプトがユーザーのブラウザーを制御するために挿入されます一部のユーザー情報。XSSはWebプログラムの一般的な脆弱性であり、XSSはパッシブでクライアント側の攻撃方法です。
XSS防止の一般的な考え方は、入力(およびURLパラメーター)をフィルターに掛け、出力をエンコードすることです。
73. CSRF攻撃とは何ですか。
CSRF(クロスサイトリクエストフォージェリ)は、ワンクリック攻撃またはセッションライディングとも呼ばれ、中国語のフルネームはクロスサイトリクエストフォージェリと呼ばれます。一般的に言って、攻撃者はユーザーのブラウザを偽造することによってユーザーがアクセスすることを認証したWebサイトにリクエストを送信するため、ターゲットWebサイトはそれがユーザーの実際の操作であると誤って認識し、コマンドを実行します。通常、口座番号の盗用、送金、偽のメッセージの送信などに使用されます。攻撃者はWebサイトの検証の脆弱性を使用して、このような攻撃を実行します。Webサイトは、要求がユーザーのブラウザーから発信されたことを確認できますが、要求がユーザーの実際の動作から発信されたかどうかは確認できません。
回避する方法:
1. HTTPリファラーフィールドを確認する
HTTPヘッダーのRefererフィールドは、HTTP要求の送信元アドレスを記録します。通常の状況では、セキュリティが制限されたページへのアクセス要求は同じWebサイトから送信されます。ハッカーがCSRF
攻撃を実装したい場合、ハッカーは通常、自分のWebサイトでのみ要求を作成できます。したがって、Referer値を確認することにより、CSRF攻撃を防ぐことができます。
2.確認コードを使用する
キー操作ページに検証コードを追加し、バックグラウンドでリクエストを受け取ってから検証コードを判定することでCSRFを防御できます。しかし、この方法はユーザーフレンドリーではありません。
3.リクエストアドレスにトークンを追加して確認する
CSRF攻撃が成功する理由は、ハッカーがユーザーのリクエストを完全に偽造できるためです。リクエスト内のすべてのユーザー認証情報はCookieに含まれているため、ハッカーは認証情報を知らなくてもユーザー自身のCookieを直接使用できます。セキュリティ検証に合格する。CSRFから保護するための鍵は、ハッカーが偽造できないリクエスト情報を入れることであり、その情報はCookieに存在しません。ランダムに生成されたトークンをパラメーターの形式でHTTPリクエストに追加し、サーバー上にインターセプターを確立してトークンを検証できます。リクエストにトークンがない場合、またはトークンの内容が正しくない場合、CSRF攻撃と見なされ、リクエストが拒否されます。 。この方法は、Refererをチェックするよりも安全です。トークンは、ユーザーがログインしてセッションに配置された後に生成され、各リクエストでセッションからトークンが取り出され、リクエスト内のトークンと比較されますが、これはこのメソッドの難しさは、トークンをパラメーターの形式でリクエストに追加する方法です。
GETリクエストの場合、トークンはリクエストアドレスに追加されるため、URLはhttp:// url?Csrftoken = tokenvalueになります。
POST要求の場合、フォームの最後に<input type = "hidden" name = "csrftoken" value = "tokenvalue" />を追加して、トークンがパラメーターとして要求に追加されるようにします。
4. HTTPヘッダーの属性をカスタマイズして確認する
この方法もトークンを使用して認証を実行します。前の方法とは異なり、これはトークンをHTTPリクエストにパラメーターとして配置するのではなく、HTTPヘッダーのカスタム属性に配置します。XMLHttpRequestクラスを介して、csrftoken HTTPヘッダー属性をこのタイプのすべてのリクエストに一度に追加し、それにトークン値を入れることができます。これにより、前のメソッドでリクエストにトークンを追加する際の不便さが解決されます。同時に、XMLHttpRequestを介してリクエストされたアドレスはブラウザのアドレスバーに記録されず、トークンがリファラーを介して他のウェブサイトに漏洩することを心配する必要はありません。