Buku Dr. Yan Hong "JAVA and Patterns" dimulai dengan deskripsi model Rantai Tanggung Jawab:
Pola rantai tanggung jawab merupakan pola perilaku objek. Dalam pola rantai tanggung jawab, banyak objek yang dihubungkan membentuk rantai dengan referensi setiap objek kepada keturunannya. Permintaan diteruskan ke rantai sampai objek dalam rantai memutuskan untuk menangani permintaan tersebut. Klien yang membuat permintaan tidak mengetahui objek mana dalam rantai yang pada akhirnya menangani permintaan tersebut, yang memungkinkan sistem untuk mengatur ulang dan menetapkan tanggung jawab secara dinamis tanpa mempengaruhi klien.
Mulai dari menabuh genderang dan menebar bunga
Menabuh genderang dan mengoper bunga adalah permainan minum yang hidup dan menegangkan. Pada saat jamuan makan, para tamu duduk secara berurutan, dan satu orang memainkan gendang. Tempat pementasan gendang dan tempat pengoperan bunga dipisahkan untuk menunjukkan keadilan. Ketika genderang dimulai, karangan bunga mulai dibagikan, dan segera setelah genderang jatuh, jika karangan bunga ada di tangan seseorang, orang tersebut harus minum.
Misalnya Jia Mu, Jia She, Jia Zheng, Jia Baoyu dan Jia Huan adalah lima orang pelintas bunga yang mengikuti permainan drum dan passing bunga. Mereka membentuk sebuah rantai. Penabuh genderang memberikan bunga kepada Jia Mu dan memulai permainan mengoper bunga. Bunga tersebut diwariskan dari Jia Mu ke Jia She, dari Jia She ke Jia Zheng, dari Jia Zheng ke Jia Baoyu, dari Jia Baoyu ke Jia Huan, dari Jia Huan ke Jia Mu, dan seterusnya, seperti terlihat pada gambar di bawah. Ketika tabuhan genderang berhenti, orang yang memegang bunga di tangannya harus melaksanakan perintah minum.
Menabuh genderang dan menebar bunga merupakan penerapan model rantai tanggung jawab. Rantai tanggung jawab dapat berupa garis lurus, rantai, atau bagian dari struktur pohon.
Struktur model rantai tanggung jawab
Implementasi paling sederhana dari pola rantai tanggung jawab digunakan di bawah ini.
Peran yang terlibat dalam model rantai tanggung jawab adalah sebagai berikut:
● Peran pengendali abstrak (Handler): mendefinisikan antarmuka untuk memproses permintaan. Jika diperlukan, antarmuka dapat menentukan metode untuk mengatur dan mengembalikan referensi ke antarmuka berikutnya. Peran ini biasanya diimplementasikan oleh kelas abstrak Java atau antarmuka Java. Hubungan agregasi kelas Handler pada gambar di atas memberikan referensi subkelas tertentu ke subkelas berikutnya. Metode abstrak handleRequest() menstandardisasi pengoperasian subkelas dalam memproses permintaan.
● Peran Concrete Handler (ConcreteHandler): Setelah menerima permintaan, Concrete Handler dapat memilih untuk memproses permintaan tersebut atau meneruskan permintaan tersebut ke pihak berikutnya. Karena pengolah beton menyimpan referensi ke rumah berikutnya, pengolah beton dapat mengakses rumah berikutnya jika diperlukan.
kode sumber
peran penangan abstrak
Copy kode kodenya sebagai berikut:
Pengendali kelas abstrak publik {
/**
* Memegang objek tanggung jawab penerus
*/
penerus Handler yang dilindungi;
/**
* Menunjukkan metode pemrosesan permintaan, meskipun metode ini tidak meneruskan parameter
* Namun, parameter sebenarnya dapat diteruskan. Anda dapat memilih apakah akan meneruskan parameter sesuai dengan kebutuhan spesifik.
*/
abstrak publik void handleRequest();
/**
* Metode nilai
*/
Pengendali publik getSuccessor() {
kembalinya penerus;
}
/**
* Metode penugasan untuk menetapkan objek tanggung jawab selanjutnya
*/
public void setSuccessor(Penanganan penerus) {
this.successor = penerus;
}
}
Peran prosesor tertentu
Copy kode kodenya sebagai berikut:
kelas publik ConcreteHandler memperluas Handler {
/**
* Metode pemrosesan, panggil metode ini untuk memproses permintaan
*/
@Mengesampingkan
public void handleRequest() {
/**
* Tentukan apakah ada objek penerus yang bertanggung jawab
* Jika ada, teruskan permintaan tersebut ke objek penanggung jawab berikutnya
* Jika tidak, proses permintaan tersebut
*/
jika(getSuccessor() != null)
{
System.out.println("Biarkan permintaannya berjalan");
getSuccessor().handleRequest();
}kalau tidak
{
System.out.println("Memproses permintaan");
}
}
}
Kelas klien
Copy kode kodenya sebagai berikut:
Klien kelas publik {
public static void main(String[] args) {
// Merakit rantai tanggung jawab
Penangan handler1 = new ConcreteHandler();
Penangan handler2 = new ConcreteHandler();
handler1.setSuccessor(handler2);
//Kirim permintaan
handler1.handleRequest();
}
}
Dapat dilihat bahwa klien membuat dua objek handler dan menentukan bahwa objek handler berikutnya dari objek handler pertama adalah objek handler kedua, sedangkan objek handler kedua tidak memiliki rumah berikutnya. Klien kemudian meneruskan permintaan ke objek penangan pertama.
Karena logika transfer contoh ini sangat sederhana: selama ada pemilik berikutnya, maka akan diteruskan ke pemilik berikutnya untuk diproses; jika tidak ada pemilik berikutnya, maka akan ditangani sendiri. Oleh karena itu, setelah objek penangan pertama menerima permintaan, ia akan meneruskan permintaan tersebut ke objek penangan kedua. Karena objek pengendali kedua tidak mempunyai rumah, ia menangani permintaan itu sendiri. Diagram urutan aktivitas ditunjukkan di bawah ini.
Skenario penggunaan
Mari kita pertimbangkan fungsi berikut: mengajukan permohonan pengelolaan biaya pesta makan malam.
Banyak perusahaan yang mendapatkan keuntungan seperti ini, yaitu tim proyek atau departemen dapat mengajukan sejumlah biaya pesta makan malam dari perusahaan, yang digunakan untuk menyelenggarakan pesta makan malam bagi anggota tim proyek atau anggota departemen.
Proses umum pengajuan biaya pesta makan malam secara umum adalah: pemohon terlebih dahulu mengisi formulir permohonan, kemudian menyerahkannya kepada pimpinan untuk disetujui, jika permohonan disetujui, pimpinan akan memberitahukan kepada pemohon bahwa persetujuan telah lolos. dan kemudian pemohon akan pergi ke departemen keuangan untuk memungut biayanya. Jika tidak disetujui, pimpinan akan Pemohon akan diberitahu bahwa persetujuan belum disahkan dan masalah tersebut akan dibatalkan.
Pimpinan di tingkat yang berbeda memiliki batas persetujuan yang berbeda. Misalnya, manajer proyek hanya dapat menyetujui permohonan dengan batas 500 yuan; manajer departemen dapat menyetujui permohonan dengan batas 1.000 yuan;
Dengan kata lain, ketika seseorang mengajukan permintaan biaya pesta makan malam, permintaan tersebut akan diproses sesuai dengan salah satu manajer proyek, manajer departemen, dan manajer umum, namun orang yang membuat permintaan tersebut tidak mengetahui apa yang akan terjadi pada akhirnya. . Siapa yang akan menangani permintaannya? Umumnya, pelamar mengajukan lamarannya kepada manajer proyek, dan mungkin manajer umum akhirnya menangani permintaannya.
Anda dapat menggunakan model rantai tanggung jawab untuk mewujudkan fungsi di atas: ketika seseorang mengajukan permintaan biaya pesta makan malam, permintaan tersebut akan diteruskan dalam rantai pemrosesan kepemimpinan seperti manajer proyek -> manajer departemen -> manajer umum Orang tersebut yang mengajukan permintaan tidak Mengetahui siapa yang akan menangani permintaannya, setiap pemimpin akan menilai apakah akan menangani permintaan tersebut atau menyerahkannya kepada pemimpin yang lebih tinggi berdasarkan ruang lingkup tanggung jawabnya masing-masing. transfernya sudah selesai.
Penting untuk mengisolasi pemrosesan masing-masing pemimpin dan mengimplementasikannya ke dalam objek pemrosesan tanggung jawab yang terpisah, dan kemudian memberi mereka objek tanggung jawab induk abstrak yang umum, sehingga rantai tanggung jawab dapat digabungkan secara dinamis pada klien untuk mencapai kebutuhan fungsional yang berbeda. .
kode sumber
Kelas peran pengendali abstrak
Copy kode kodenya sebagai berikut:
Pengendali kelas abstrak publik {
/**
* Memegang objek yang menangani permintaan berikutnya
*/
penerus Handler yang dilindungi = null;
/**
* Metode nilai
*/
Pengendali publik getSuccessor() {
kembalinya penerus;
}
/**
* Atur objek selanjutnya untuk menangani permintaan
*/
public void setSuccessor(Penanganan penerus) {
this.successor = penerus;
}
/**
* Memproses permohonan biaya pesta
* @pemohon pengguna param
* @param fee Jumlah uang yang diajukan
* @return Pemberitahuan khusus tentang keberhasilan atau kegagalan
*/
public abstract String handleFeeRequest(Pengguna string, biaya ganda);
}
Peran prosesor tertentu
Copy kode kodenya sebagai berikut:
ProjectManager kelas publik memperluas Handler {
@Mengesampingkan
public String handleFeeRequest(Pengguna string, biaya ganda) {
String str = "";
//Otoritas manajer proyek relatif kecil dan hanya dapat berada dalam kisaran 500
jika (biaya < 500)
{
//Demi pengujian, buatlah tetap sederhana dan hanya menyetujui permintaan Zhang San.
if("Zhang San".sama dengan(pengguna))
{
str = "Sukses: Manajer proyek menyetujui biaya pesta makan malam [" + pengguna + "], jumlahnya adalah " + biaya + "yuan";
}kalau tidak
{
//Tidak ada orang lain yang setuju
str = "Kegagalan: Manajer proyek tidak setuju dengan biaya pesta makan malam [" + pengguna + "], jumlahnya adalah " + biaya + "yuan";
}
}kalau tidak
{
//Jika melebihi 500, terus berikan ke orang dengan level yang lebih tinggi untuk diproses.
jika(getSuccessor() != null)
{
return getSuccessor().handleFeeRequest(pengguna, biaya);
}
}
kembalikan str;
}
}
Copy kode kodenya sebagai berikut:
DeptManager kelas publik memperluas Handler {
@Mengesampingkan
public String handleFeeRequest(Pengguna string, biaya ganda) {
String str = "";
//Otoritas manajer departemen hanya boleh dalam 1000
jika (biaya < 1000)
{
//Demi pengujian, buatlah tetap sederhana dan hanya menyetujui permintaan Zhang San.
if("Zhang San".sama dengan(pengguna))
{
str = "Sukses: Manajer departemen menyetujui biaya pesta makan malam [" + pengguna + "], jumlahnya adalah " + biaya + "yuan";
}kalau tidak
{
//Tidak ada orang lain yang setuju
str = "Kegagalan: Manajer departemen tidak setuju dengan biaya pesta makan malam [" + pengguna + "], jumlahnya adalah " + biaya + "yuan";
}
}kalau tidak
{
//Jika melebihi 1000, terus berikan ke orang dengan level yang lebih tinggi untuk diproses.
jika(getSuccessor() != null)
{
return getSuccessor().handleFeeRequest(pengguna, biaya);
}
}
kembalikan str;
}
}
Copy kode kodenya sebagai berikut:
kelas publik GeneralManager memperluas Handler {
@Mengesampingkan
public String handleFeeRequest(Pengguna string, biaya ganda) {
String str = "";
//Manajer umum memiliki otoritas yang besar. Selama permintaan datang ke sini, dia dapat menanganinya.
if(biaya >= 1000)
{
//Demi pengujian, buatlah tetap sederhana dan hanya menyetujui permintaan Zhang San.
if("Zhang San".sama dengan(pengguna))
{
str = "Sukses: Manajer umum menyetujui biaya makan malam [" + pengguna + "], jumlahnya adalah " + biaya + "yuan";
}kalau tidak
{
//Tidak ada orang lain yang setuju
str = "Kegagalan: Manajer umum tidak setuju dengan biaya pesta makan malam [" + pengguna + "], jumlahnya adalah " + biaya + "yuan";
}
}kalau tidak
{
//Jika ada objek pemrosesan berikutnya, lanjutkan meneruskannya
jika(getSuccessor() != null)
{
return getSuccessor().handleFeeRequest(pengguna, biaya);
}
}
kembalikan str;
}
}
Kelas klien
Copy kode kodenya sebagai berikut:
Klien kelas publik {
public static void main(String[] args) {
//Pertama-tama susun rantai tanggung jawab
Penangan h1 = GeneralManager baru();
Penangan h2 = DeptManager baru();
Penangan h3 = ProjectManager baru();
h3.setSucccessor(h2);
h2.setSucccessor(h1);
//Mulai pengujian
String test1 = h3.handleFeeRequest("Zhang San", 300);
System.out.println("tes1 = " + tes1);
String test2 = h3.handleFeeRequest("李思", 300);
System.out.println("tes2 = " + tes2);
System.out.println("---------------------------------------");
String test3 = h3.handleFeeRequest("Zhang San", 700);
System.out.println("tes3 = " + tes3);
String test4 = h3.handleFeeRequest("李思", 700);
System.out.println("tes4 = " + tes4);
System.out.println("---------------------------------------");
String test5 = h3.handleFeeRequest("Zhang San", 1500);
System.out.println("test5 = " + test5);
String test6 = h3.handleFeeRequest("李思", 1500);
System.out.println("tes6 = " + tes6);
}
}
Hasil yang berjalan adalah sebagai berikut:
Model rantai tanggung jawab yang murni dan tidak murni
Model rantai tanggung jawab murni mengharuskan objek pemroses tertentu hanya dapat memilih satu dari dua tindakan: tindakan pertama adalah mengambil tanggung jawab, namun meneruskan tanggung jawab tersebut kepada pihak berikutnya. Objek pemroses tertentu tidak diperbolehkan untuk menyerahkan tanggung jawab setelah mengambil beberapa tanggung jawab.
Dalam model rantai tanggung jawab murni, permintaan harus diterima oleh objek penangan; dalam model rantai tanggung jawab tidak murni, permintaan tidak boleh diterima oleh objek penerima mana pun.
Contoh nyata dari model rantai tanggung jawab murni sulit ditemukan, dan contoh yang umum terlihat adalah implementasi dari model rantai tanggung jawab tidak murni. Beberapa orang berpikir bahwa rantai tanggung jawab yang tidak murni bukanlah model rantai tanggung jawab sama sekali, dan ini mungkin masuk akal. Namun dalam sistem yang sebenarnya, rantai tanggung jawab yang murni sulit ditemukan. Jika Anda bersikeras bahwa rantai tanggung jawab itu tidak murni, dan itu bukan model rantai tanggung jawab, maka model rantai tanggung jawab tidak akan masuk akal.
Penerapan model rantai tanggung jawab di Tomcat
Seperti kita ketahui bersama, Filter di Tomcat menggunakan model rantai tanggung jawab. Selain membuat konfigurasi yang sesuai di file web.xml, membuat Filter juga memerlukan implementasi antarmuka javax.servlet.Filter.
Copy kode kodenya sebagai berikut:
TestFilter kelas publik mengimplementasikan Filter{
public void doFilter(Permintaan ServletRequest, respons ServletResponse,
Rantai FilterChain) menampilkan IOException, ServletException {
chain.doFilter(permintaan, tanggapan);
}
kehancuran publik void() {
}
public void init(FilterConfig filterConfig) melempar ServletException {
}
}
Hasil yang terlihat menggunakan mode DEBUG adalah sebagai berikut:
Faktanya, sebelum benar-benar mengeksekusi kelas TestFilter, kelas tersebut akan melewati banyak kelas internal Tomcat. Omong-omong, pengaturan kontainer Tomcat juga merupakan model rantai tanggung jawab. Perhatikan kelas yang dilingkari oleh kotak merah. Dari Mesin ke Host ke Konteks ke Pembungkus, permintaan diteruskan melalui rantai. Ada kelas bernama ApplicationFilterChain di tempat yang dilingkari oleh kotak hijau. Kelas ApplicationFilterChain berperan sebagai pemroses abstrak, dan peran pemroses spesifik dimainkan oleh setiap Filter.
Pertanyaan pertama adalah di mana ApplicationFilterChain menyimpan semua filter?
Jawabannya disimpan dalam array objek ApplicationFilterConfig di kelas ApplicationFilterChain.
Copy kode kodenya sebagai berikut:
/**
*Filter.
*/
filter ApplicationFilterConfig[] pribadi =
ApplicationFilterConfig[0] baru;
Jadi apa itu objek ApplicationFilterConfig?
ApplicationFilterConfig adalah wadah Filter. Berikut ini adalah deklarasi kelas ApplicationFilterConfig:
Copy kode kodenya sebagai berikut:
/**
* Implementasi <code>javax.servlet.FilterConfig</code> berguna dalam
* mengelola contoh filter yang dipakai saat aplikasi web
* pertama kali dimulai.
*
* @penulis Craig R. McClanahan
* @version $Id: ApplicationFilterConfig.java 1201569 14-11-2011 01:36:07Z kkolinko $
*/
ApplicationFilterConfig secara otomatis dibuat ketika aplikasi web dimulai untuk pertama kalinya. Ia membaca informasi Filter yang dikonfigurasi dari file web.xml aplikasi web dan kemudian memuatnya ke dalam wadah.
Saya baru saja melihat bahwa panjang array ApplicationFilterConfig yang dibuat di kelas ApplicationFilterChain adalah nol.
Copy kode kodenya sebagai berikut:
filter ApplicationFilterConfig[] pribadi =
ApplicationFilterConfig[0] baru;
Itu terjadi ketika memanggil metode addFilter() dari kelas ApplicationFilterChain.
Copy kode kodenya sebagai berikut:
/**
* Int yang memberikan jumlah filter saat ini dalam rantai.
*/
int pribadi n = 0;
INCREMENT int akhir statis publik = 10;
Copy kode kodenya sebagai berikut:
batal addFilter(ApplicationFilterConfig filterConfig) {
// Mencegah filter yang sama ditambahkan beberapa kali
untuk (filter ApplicationFilterConfig: filter)
jika(filter==filterConfig)
kembali;
if (n == filter.panjang) {
ApplicationFilterConfig[] filter baru =
ApplicationFilterConfig baru[n + PENINGKATAN];
System.arraycopy(filter, 0, filter baru, 0, n);
filter = filter baru;
}
filter[n++] = filterConfig;
}
Variabel n digunakan untuk mencatat jumlah filter dalam rantai filter saat ini. Secara default, n sama dengan 0, dan panjang array objek ApplicationFilterConfig juga sama dengan 0, sehingga ketika metode addFilter() dipanggil pertama kali, jika (n == filter .length) benar dan panjang array ApplicationFilterConfig diubah. Kemudian filter[n++] = filterConfig; masukkan variabel filterConfig ke dalam array ApplicationFilterConfig dan tambahkan 1 ke jumlah filter dalam rantai filter saat ini.
Jadi di manakah metode addFilter() dari ApplicationFilterChain dipanggil?
Itu ada dalam metode createFilterChain() dari kelas ApplicationFilterFactory.
Copy kode kodenya sebagai berikut:
ApplicationFilterChain publik buatFilterChain
(Permintaan ServletRequest, Pembungkus pembungkus, Servlet servlet) {
// dapatkan tipe operator
DispatcherType operator = null;
jika (permintaan.getAttribute(DISPATCHER_TYPE_ATTR) != null) {
operator = (DispatcherType) permintaan.getAttribute(DISPATCHER_TYPE_ATTR);
}
String requestPath = nol;
Atribut objek = request.getAttribute(DISPATCHER_REQUEST_PATH_ATTR);
jika (atribut != nol){
requestPath = atribut.toString();
}
// Jika tidak ada servlet yang akan dieksekusi, kembalikan null
jika (servlet == nol)
kembali (nol);
komet boolean = salah;
// Membuat dan menginisialisasi objek rantai filter
ApplicationFilterChain filterChain = null;
if (permintaan contoh Permintaan) {
Permintaan permintaan = (Permintaan) permintaan;
komet = req.isComet();
if (Global.IS_SECURITY_ENABLED) {
// Keamanan: Jangan mendaur ulang
filterChain = AplikasiFilterChain baru();
jika (komet) {
req.setFilterChain(filterChain);
}
} kalau tidak {
filterChain = (ApplicationFilterChain) req.getFilterChain();
jika (filterChain == null) {
filterChain = AplikasiFilterChain baru();
req.setFilterChain(filterChain);
}
}
} kalau tidak {
//Minta operator yang sedang digunakan
filterChain = AplikasiFilterChain baru();
}
filterChain.setServlet(servlet);
filterChain.setDukungan
(((StandardWrapper)wrapper).getInstanceSupport());
// Dapatkan pemetaan filter untuk Konteks ini
Konteks StandardContext = (StandardContext) wrapper.getParent();
FilterMap filterMaps[] = konteks.findFilterMaps();
// Jika tidak ada pemetaan filter, kita selesai
if ((filterMaps == null) || (filterMaps.length == 0))
kembali (filterChain);
// Dapatkan informasi yang kita perlukan untuk mencocokkan pemetaan filter
String servletName = bungkus.getName();
// Tambahkan filter yang dipetakan jalur yang relevan ke rantai filter ini
for (int i = 0; i < filterMaps.length; i++) {
if (!matchDispatcher(filterMaps[i] ,dispatcher)) {
melanjutkan;
}
jika (!matchFiltersURL(filterMaps[i], requestPath))
melanjutkan;
ApplicationFilterConfig filterConfig = (ApplicationFilterConfig)
konteks.findFilterConfig(filterMaps[i].getFilterName());
jika (filterConfig == nol) {
// FIXME - masalah konfigurasi log
melanjutkan;
}
boolean isCometFilter = salah;
jika (komet) {
mencoba {
isCometFilter = filterConfig.getFilter() contoh CometFilter;
} tangkapan (Pengecualian e) {
// Catatan: Try catch ada karena getFilter memiliki banyak
// mendeklarasikan pengecualian. Namun, filternya dialokasikan banyak
// lebih awal
T yang dapat dilempar = ExceptionUtils.unwrapInvocationTargetException(e);
ExceptionUtils.handleThrowable(t);
}
jika (isCometFilter) {
filterChain.addFilter(filterConfig);
}
} kalau tidak {
filterChain.addFilter(filterConfig);
}
}
// Tambahkan filter yang cocok dengan nama servlet kedua
for (int i = 0; i < filterMaps.length; i++) {
if (!matchDispatcher(filterMaps[i] ,dispatcher)) {
melanjutkan;
}
if (!matchFiltersServlet(filterMaps[i], servletName))
melanjutkan;
ApplicationFilterConfig filterConfig = (ApplicationFilterConfig)
konteks.findFilterConfig(filterMaps[i].getFilterName());
jika (filterConfig == nol) {
// FIXME - masalah konfigurasi log
melanjutkan;
}
boolean isCometFilter = salah;
jika (komet) {
mencoba {
isCometFilter = filterConfig.getFilter() contoh CometFilter;
} tangkapan (Pengecualian e) {
// Catatan: Try catch ada karena getFilter memiliki banyak
// mendeklarasikan pengecualian. Namun, filternya dialokasikan banyak
// lebih awal
}
jika (isCometFilter) {
filterChain.addFilter(filterConfig);
}
} kalau tidak {
filterChain.addFilter(filterConfig);
}
}
// Mengembalikan rantai filter yang telah selesai
kembali (filterChain);
}
Kode di atas dapat dibagi menjadi dua bagian, bagian pertama sebelum baris 51, dan bagian kedua setelah baris 51.
Tujuan utama paragraf pertama adalah membuat objek ApplicationFilterChain dan mengatur beberapa parameter.
Tujuan utama paragraf kedua adalah untuk mendapatkan semua informasi Filter dari konteksnya, dan kemudian menggunakan loop for untuk melintasi dan memanggil filterChain.addFilter(filterConfig); memasukkan filterConfig ke dalam array ApplicationFilterConfig dari objek ApplicationFilterChain.
Jadi di manakah metode createFilterChain() dari kelas ApplicationFilterFactory dipanggil?
Ini dipanggil dalam metode invoke() dari kelas StandardWrapperValue.
Karena metode invoke() panjang, banyak tempat yang dihilangkan.
Copy kode kodenya sebagai berikut:
pemanggilan pembatalan akhir publik (Permintaan permintaan, Respon respons)
melempar IOException, ServletException {
...Hilangkan kode perantara // Buat rantai filter untuk permintaan ini
Pabrik ApplicationFilterFactory =
ApplicationFilterFactory.getInstance();
ApplicationFilterChain filterChain =
pabrik.createFilterChain(permintaan, pembungkus, servlet);
...hilangkan kode perantara
filterChain.doFilter(permintaan.getRequest(), respon.getResponse());
...hilangkan kode perantara
}
Proses normalnya seharusnya seperti ini:
Panggil metode createFilterChain() dari kelas ApplicationFilterChai dalam metode invoke() dari kelas StandardWrapperValue ---> panggil metode addFilter() dari kelas ApplicationFilterChain dalam metode createFilterChain() dari kelas ApplicationFilterChai ---> panggil metode addFilter() dari kelas ApplicationFilterChain Tetapkan nilai ke array ApplicationFilterConfig.
Berdasarkan kode di atas, terlihat bahwa metode invoke() dari kelas StandardWrapperValue akan terus mengeksekusi metode doFilter() dari kelas ApplicationFilterChain setelah menjalankan metode createFilterChain(), dan kemudian metode internalDoFilter() akan menjadi dipanggil dalam metode doFilter().
Berikut ini adalah bagian dari kode metode internalDoFilter()
Copy kode kodenya sebagai berikut:
// Panggil filter berikutnya jika ada
jika (pos < n) {
//Dapatkan Filter berikutnya dan gerakkan penunjuk ke bawah satu posisi
//pos ini mengidentifikasi filter mana yang dijalankan oleh ApplicationFilterChain (rantai filter saat ini) saat ini
ApplicationFilterConfig filterConfig = filter[pos++];
Filter filter = nol;
mencoba {
//Dapatkan instance dari Filter yang ditunjuk saat ini
filter = filterConfig.getFilter();
dukungan.fireInstanceEvent(InstanceEvent.BEFORE_FILTER_EVENT,
filter, permintaan, respons);
if (permintaan.isAsyncSupported() && "false".equalsIgnoreCase(
filterConfig.getFilterDef().getAsyncSupported())) {
permintaan.setAttribute(Global.ASYNC_SUPPORTED_ATTR,
Boolean.SALAH);
}
if(Global.IS_SECURITY_ENABLED) {
permintaan ServletRequest terakhir = permintaan;
res ServletResponse akhir = respons;
Kepala Sekolah =
((HttpServletRequest) req).getUserPrincipal();
Objek[] args = Objek baru[]{req, res, this};
SecurityUtil.doAsPrivilege
("doFilter", filter, classType, args, prinsipal);
} kalau tidak {
//Panggil metode doFilter() pada Filter
filter.doFilter(permintaan, tanggapan, ini);
}
Filter.doFilter(request, respon, this); di sini untuk memanggil metode doFilter() di TestFilter yang kita buat sebelumnya. Metode doFilter() di TestFilter akan terus memanggil metode chain.doFilter(request, respon); dan rantai ini sebenarnya adalah ApplicationFilterChain, jadi proses pemanggilan kembali ke pemanggilan dofilter dan pemanggilan metode internalDoFilter di atas, dan ini eksekusi berlanjut hingga filter di dalam Jalankan semuanya.
Jika dua filter ditentukan, hasil Debugnya adalah sebagai berikut: