مفهوم init و Service در Servlet
در سری مقالات آموزش Java Enterprise, میخواهیم به جمع بندی مطالب گفته شده و همچنین بیان مطالب پایانی پیرامون Servlet ها بپردازیم.
همانطور که در آموزش های قبلی گفته شد, قبل از Servlet از CGI استفاده میشد. یکی از مهم ترین ضعف های CGI ها ایجاد Instance های جدید به ازای هر درخواست بود و برای حل این مشکل در Servlet ها یک بار instance ایجاد میشد و به ازای هر درخواست یک thread برای آن در نظر گرفته میشد. درخواست ها نیز از طریق HTTP Protocol ارسال میشوند و حاوی یکسری اطلاعات میباشند و عمدتا با استفاده از دو متد رایج Post و Get ارسال میگردند. هر درخواست در object از کلاس HttpServletRequest نگهداری میشوند و همچنین پاسخ به آن نیز از طریق کلاس HttpServletResponse میباشد و ایجاد object از این کلاس ها بر عهده Tomcat Container میباشد.
برای مثال فرض کنید دو Servlet داریم و آنهارا با S1 و S2 مشخص میکنیم و از طریق دو Client به آنها درخواست ارسال میکنیم. Client A یک درخواست به S1 ارسال میکند. اگر object مربوط به S1 در Container وجود داشته باشد یک Thread برای آن ایجاد میکند و اگر وجود نداشته باشد ابتدا object برای S1 میسازد و سپس یک Thread برای آن ایجاد میکند. حال Client A یک درخواست دیگر ( برای مثال از یک مرورگر دیگر ) به S1 ارسال میکند و یک Thread جدید برای درخواست آن ایجاد میگردد. Client B یک درخواست به S2 ارسال میکند و به صورت مشابه اگر object آن ایجاد شده باشد یک Thread جدید و اگر object آن در Container وجود نداشته باشد یک object ایجاد میکند و سپس یک Thread برای آن ایجاد میکند. در این بین Container به ازای هر درخواست Object های مورد نیاز برای دریافت Request و ارسال Response را نیز ایجاد میکند.
اما اگر بخواهیم ساختار Servlet هارا عمیق تر بررسی کنیم, باید بگوییم Life Cycle آن به صورت میباشد
همانطور که مشخص است وقتی یک object از Servlet توسط Container ایجاد میگردد, متد init فراخوانی میگردد. این متد تنها یک بار و در ابتدای ایجاد object فراخوانی میگردد. در مرحله بعد متد service فراخوانی میگردد. به ازای هر درخواست این متد مجددا فراخوانی میشود و مشخص کننده این است که کدام یک از متد های doPost و یا doGet باید فراخوانی شوند. در حقیقت مشخص کننده متد HTTP درخواست میباشد. برای مثال کد زیر را در نظر بگیرید :
public class MyServlet extends HttpServlet { @Override public void init() throws ServletException { super.init(); System.out.println("init Called"); } @Override public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException { super.service(req, res); System.out.println("service called"); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { ..... some code .... } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { ..... some code .... }
وقتی کد فوق را اجرا کنید ابتدا پیام init called و سپس پیام service Called را در Log دریافت خواهید کرد. اگر صفحه را refresh کنید و یا با مرورگر دیگری URL مربوط به Servlet را باز کنید, باز هم پیام Service called در خروجی نمایش داده میشود. زیرا با اولین درخواست object در Tomcat Container ایجاد میگردد و سپس با هربار درخواست متد Service مشخص میکند که کدام متد برای پاسخگویی به این درخواست باید فراخوانی شود.
کلاس MyServlet از کلاس HttpServlet ارث بری کرده است که خود این کلاس از GenericServlet ارث بری کرده است. در کلاس GenericServlet متد init, Service وجود دارد با استفاده از ServletConfig فراخوانی میگردد :
public void init(ServletConfig config) throws ServletException { this.config = config; this.init(); } public void init() throws ServletException { }
و پیاده سازی Service در کلاس HttpServlet میباشد :
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException { HttpServletRequest request; HttpServletResponse response; try { request = (HttpServletRequest)req; response = (HttpServletResponse)res; } catch (ClassCastException var6) { throw new ServletException("non-HTTP request or response"); } this.service(request, response); }
مشاهده میکنید که دو کلاس HttpServletRequest و HttpServletResponse در این متد ساخته میشوند. همانطور که گفته شد به ازای هر درخواست متد Service فراخوانی میشود و واضح است که به ازای هر درخواست نیز نیاز است تا یک Request و Response منحصر به آن ایجاد گردد و مشخص میکند که بر اساس کدام متد HTTP این درخواست ارسال شده است. برای مثال متد doPost در HttpServlet به این صورت مشخص شده است :
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String protocol = req.getProtocol(); String msg = lStrings.getString("http.method_post_not_supported"); if(protocol.endsWith("1.1")) { resp.sendError(405, msg); } else { resp.sendError(400, msg); } }
و در نهایت در کلاس MyServlet کد مورد نظر برای هر متد را قرار میدهیم.
با یک مثال شیوه کار init را توضیح خواهیم داد :
@WebServlet(name = "Servlet", urlPatterns = {"/simpleServlet"}, initParams = {@WebInitParam(name = "user", value = "vhdrjb")}) public class Servlet extends HttpServlet { @Override public void init() throws ServletException { super.init(); System.out.println("init"); } @Override public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException { super.service(req, res); System.out.println("service"); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { .., some code .... System.out.println(this.getServletConfig().getInitParameter("user")); }
در خروجی ابتدا init سپس vhdrjb و در آخر Service در خروجی نمایش داده میشود. ابتدا کلاس ServletConfig به init ارسال میگردد. سپس متد Service فراخوانی میشود و با استفاده از super.Service متد بالایی خود را فراخوانی میکند. در متد اصلی Service که در کلاس HttpServlet قرار دارد مشخص میشود که متد doGet باید فراخوانی شود. پس از فراخوانی doGet دستور
System.out.println("service");
انجام میشود.
توجه داشته باشید که یکی از وظایف متد Service در HttpServlet مشخص کردن متد درخواست ارسال شده میباشد. در صورتی که در Servlet پیاده سازی شده ما این متد وجود نداشته باشد خطای
HTTP method *** is not supported by this URL
را نمایش خواهد داد. برای مثال درخواست از طریق متد Get ارسال شده است و Servlet ما فاقد متد doGet میباشد در نتیجه چنین خطایی در خروجی به ما میدهد :
HTTP method GET is not supported by this URL
سری آموزش های Servlet در اینجا به پایان میرسد اما سری مقالات آموزش Java Enterprise همچنان ادامه دارد. در مقاله بعدی مبحث JSP ها را آغاز میکنیم.
با ما همراه باشید.
مطالب زیر را حتما مطالعه کنید
از Java به Dart – کلاس و Constructor
آموزش Gradle – اهمیت Project Automation
تفاوت Sequence و List در کاتلین
بهترین محیط های توسعه(IDE) برای جاوا
Open/Closed Principle در قوانین Solid
توابع در زبان برنامه نویسی Kotlin
5 Comments
Join the discussion and tell us your opinion.
دیدگاهتان را بنویسید لغو پاسخ
برای نوشتن دیدگاه باید وارد بشوید.
سلام لطفا اگه میشه درمورد متدهای put و delete هم یک توضیح مختصری بدید و اینکه یک مثال کوچیک برای دریافت و ارسال اطلاعات با این متد ها رو انجام بدید.
با سلام. ممنون از همراهیتون.
چیزی که در تعریف متد post وجود دارد این است که این متد برای بروز رسانی و update منابع استفاده می شود مانند
x++
و از متد put برای ایجاد منابع و مقدار دهی صریح استفاده می شود مانند :x = 5
به این ترتیب اگر شما از وجود منبعی اطلاع دقیق دارید و می خواهید مقداری را بجای آن قرار دهدید از put و اگر نمیدانید در کجا باید ذخیره شود از post استفاده می شود . برای مثال شما یک کتاب را می خواهید اضافه کنید. اگر بدانید در آدرس https://www.zerotohero.ir/books/1234 این کتاب وجود دارد و بخواهید کتابی را جایگزین آن کنید از متد put باید استفاده کنید :
اما نمیدانید کتاب را درکجا باید ذخیره کنید و فقط میخواهید کتابی به کتاب های مجموعه اضافه کنید ( update منابع ) باید از متد post استفاده کنید :
و در servlet هم مانند باقی متد ها می توان این درخواست را دریافت کرد :
@Override
protected void doPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String username = req.getParameter("username");
System.out.println("User : " + username);
}
متد delete هم همانطور که از اسمش مشخص است برای حذف منابع استفاده می شود. در صورتی که response code 200 باشد به این معنا است که با موفقیت انجام شده است. ۲۰۲ وقتی که هنوز انجام نشده است , ۲۰۴ مقدار مورد نظر یافت نشد. معمولا اگر پس از حذف درخواست مجددا ارسال شود , خطای ۴۰۴ بر می گرداند. روش دسترسی به این متد هم در servlet مانند باقی متد ها می باشد :
@Override
protected void doDelete(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doDelete(req, resp);
}
اگر سوالی بود بفرمایید.
بسیار عالی
ممنون از پاسختون
ممنون بابت سری مقالاتتون
تفاووتget وpost در چیه؟
تفاووت کارکردی هم دارند؟
با سلام. ممنون از همراهیتون دوست عزیز. HTTP یکسری متد ها داره که post و get هم شامل این متد ها میشن . هر متدی خاصیت خودش داره مثل محتوایی که میتونه با خودش ارسال کنه و میزان امنیتی که در ازای اون محتوا تامین میکنه. برای مثال اطلاعات حساس سعی میشه بر اساس post ارسال بشه . چون ارسال پارامتر از طریق URL نمیشه و حتما باید از طریق یک form یا یک برنامه ارسال بشه و پارامتر هاش مشخص بشن ولی get امنیت کمتری داره و پارامتر ها درون URL قرار میگیرن. برای مثال سعی میشه تا برای دریافت اطلاعات یک کاربر از متد get استفاده بشه ولی برای ثبت اطلاعاتش از متد post استفاده بشه . .در این مقاله https://zerotohero.ir/?p=8203 پیرامون get و post توضیح داده شده. اگر بازم جایی ابهام داشت بفرمایین. با تشکر