2009-08-14 31 views

Trả lời

25

Chúng ta có thể viết một constructor đối số trong một Servlet?

Có, bạn có thể vô dụng vì thùng chứa servlet sẽ không gọi nó.

Cách thích hợp để làm điều đó là sử dụng init() phương pháp:

@Override 
public void init() throws ServletException { 
    String foo = getInitParameter("foo"); 
    String bar = getServletContext().getInitParameter("bar"); 
    // ... 
} 

Trong ví dụ này, getInitParameter("foo") trả về giá trị của <init-param> của <servlet> mục cụ thể trong web.xml, và getServletContext().getInitParameter("bar") trả về giá trị của độc lập <context-param> trong web.xml.

+3

servlet + web.xml là một trong những khuôn khổ tiêm phụ thuộc đầu tiên của lịch sử – dfa

5

Constructors là các đối tượng được quản lý bởi máy chủ ứng dụng.

Để khởi tạo, hãy xem phương thức init().

Cập nhật:

Tôi có thể sử dụng một constructor trong servlet của tôi?

A: Một servlet là một lớp Java bình thường, vì vậy khi không có các nhà thầu tùy chỉnh , có một hàm tạo mặc định là không có đối số. Các thùng chứa Servlet thường sử dụng phương thức Class.newInstance() để tải servlets, vì vậy bạn phải cẩn thận thêm một hàm tạo mặc định rõ ràng nếu bạn thêm các hàm tạo không mặc định.

nguồn: http://www.codestyle.org/java/servlets/FAQ.shtml

+0

Tại sao init() chứ không phải là hàm tạo của servlet? –

5

Bạn không thể. Servlet được khởi tạo một cách phản ánh bằng container. Nếu đặc tả servlet đã cho phép các đối số trong hàm tạo, bạn sẽ phải có một số mô tả triển khai phức tạp như,

<servlet> 
    <servlet-name>MyServlet</servlet-name> 
    <servlet-class>MyServlet</servlet-class> 
    <servlet-argument id="1" type="string">Test<servlet-argument> 
    <servlet-argument id="2" type="int">10</servlet-argument> 
    <load-on-startup>1</load-on-startup> 
</servlet> 

Tôi đoán không ai muốn điều đó.

+0

Câu trả lời thú vị –

+1

Vấn đề ở đây là cú pháp cấu hình servlet, không phức tạp của các nhà xây dựng tham số – Aivar

20

Vấn đề có thể được nhà nước quát hơn:.

"Theo servlets (2.3) đặc điểm kỹ thuật, các servlets là instantiated bởi servlet engine bởi viện dẫn không-arg constructor Làm thế nào thể Tôi khởi tạo một servlet đúng cách cho rằng khởi tạo chính xác phụ thuộc vào cấu hình trung tâm/toàn cầu/duy nhất/ứng dụng ? "

Thực ra, bạn có thể sử dụng serlvets với hàm tạo và/hoặc khởi tạo chúng theo ý muốn. Tuy nhiên, nó đòi hỏi một chút đường ống dẫn nước.

Giả sử bạn có một servlet với một constructor có tham số:

package org.gawi.example.servlets; 

import java.io.*; 

import javax.servlet.*; 
import javax.servlet.http.*; 

public class SampleServlet extends HttpServlet 
{ 
    private final String mMessage; 

    public SampleServlet(String message) 
    { 
     mMessage = message; 
    } 

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException 
    { 
     response.setContentType("text/plain"); 
     response.getWriter().write(mMessage); 
    } 
} 

Điều đầu tiên bạn cần là một servlet độc đáo whithin ứng dụng của bạn, chúng ta hãy gọi nó InitializationServlet, để tạo ra tất cả các trường hợp cần thiết. Những trường hợp đó sau đó phải được xuất khẩu trong ngữ cảnh servlet để được lấy bởi một servlet khác (được giải thích sau). InitializationServlet có thể trông giống như sau:

package org.gawi.example.servlets; 

import javax.servlet.*; 
import javax.servlet.http.*; 

public class InitializationServlet extends HttpServlet 
{ 
    public void init() throws ServletException 
    { 
     SampleServlet servletA = new SampleServlet("this is servlet A"); 
     SampleServlet servletB = new SampleServlet("this is servlet B"); 
     SampleServlet servletC = new SampleServlet("this is servlet C"); 

     getServletContext().setAttribute("servletA", servletA); 
     getServletContext().setAttribute("servletB", servletB); 
     getServletContext().setAttribute("servletC", servletC); 
    } 
} 

Bạn thấy rằng chỉ có phương thức init() được cung cấp. Servlet này không phục vụ bất kỳ yêu cầu HTTP nào. Mục đích duy nhất của nó là lưu trữ servlet trong ServletContext. Lưu ý rằng bạn cũng có thể sử dụng servlet này để tải cấu hình ứng dụng của bạn. Vì vậy, điều này có thể hoạt động như điểm vào ứng dụng web, như phương thức main(String[] args) của một chương trình. Điều này có thể nhắc bạn về ContextLoaderServlet của SpringSource.

Phần cuối cùng là DelegateServlet rằng hiệu quả sẽ được khởi tạo bởi các container servlet, chỉ servlet này sẽ chuyển tất cả các phương pháp thích hợp cuộc gọi đến dụ servlet bọc:

package org.gawi.example.servlets; 

import java.io.*; 

import javax.servlet.*; 
import javax.servlet.http.*; 

public class DelegateHttpServlet extends HttpServlet 
{ 
    private static final String SERVLET_CONTEXT_KEY_INIT_PARAMETER = "servletContextKey"; 

    private HttpServlet mServlet; 

    public void init(ServletConfig servletConfig) throws ServletException 
    { 
     super.init(servletConfig); 
     locateServlet(servletConfig); 
     mServlet.init(servletConfig); 
    } 

    private void locateServlet(ServletConfig servletConfig) throws ServletException 
    { 
     String servletContextAttributeName = servletConfig.getInitParameter(SERVLET_CONTEXT_KEY_INIT_PARAMETER); 
     if (servletContextAttributeName == null) 
     { 
      throw new ServletException("Unable to find init parameter '" + SERVLET_CONTEXT_KEY_INIT_PARAMETER + "'"); 
     } 

     Object object = servletConfig.getServletContext().getAttribute(servletContextAttributeName); 

     if (object == null) 
     { 
      throw new ServletException("Unable to find " + servletContextAttributeName + " in servlet context."); 
     } 

     if (!(object instanceof HttpServlet)) 
     { 
      throw new ServletException("Object is not an instance of" 
             + HttpServlet.class.getName() 
             + ". Class is " 
             + object.getClass().getName() 
             + "."); 
     } 

     mServlet = (HttpServlet) object; 
    } 

    public void destroy() 
    { 
     mServlet.destroy(); 
    } 

    public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException 
    { 
     mServlet.service(req, res); 
    } 

} 

Trong thời gian khởi của nó, là DelegateServlet sẽ tra cứu servlet đích trong ngữ cảnh servlet bằng cách sử dụng đối số đầu tiên servlet servletContextKey.

Các web.xml cho một ứng dụng như vậy có thể trông như thế:

<?xml version="1.0" encoding="ISO-8859-1"?> 

<!DOCTYPE web-app 
    PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" 
    "http://java.sun.com/dtd/web-app_2_3.dtd"> 

<web-app> 

    <display-name>Example</display-name> 
    <description>Example web showing handling of servlets w/ constructors.</description> 


    <servlet> 
    <servlet-name>Initialization</servlet-name> 
    <servlet-class>org.gawi.example.servlets.InitializationServlet</servlet-class> 
    <load-on-startup>1</load-on-startup> 
    </servlet> 

    <servlet> 
    <servlet-name>A</servlet-name> 
    <servlet-class>org.gawi.example.servlets.DelegateHttpServlet</servlet-class> 

    <init-param> 
     <param-name>servletContextKey</param-name> 
     <param-value>servletA</param-value> 
    </init-param> 

    <load-on-startup>2</load-on-startup> 
    </servlet> 

    <servlet> 
    <servlet-name>B</servlet-name> 
    <servlet-class>org.gawi.example.servlets.DelegateHttpServlet</servlet-class> 

    <init-param> 
     <param-name>servletContextKey</param-name> 
     <param-value>servletB</param-value> 
    </init-param> 

    <load-on-startup>3</load-on-startup> 
    </servlet> 

    <servlet> 
    <servlet-name>C</servlet-name> 
    <servlet-class>org.gawi.example.servlets.DelegateHttpServlet</servlet-class> 

    <init-param> 
     <param-name>servletContextKey</param-name> 
     <param-value>servletC</param-value> 
    </init-param> 

    <load-on-startup>4</load-on-startup> 
    </servlet> 

    <servlet-mapping> 
    <servlet-name>A</servlet-name> 
    <url-pattern>/servlet/a</url-pattern> 
    </servlet-mapping> 

    <servlet-mapping> 
    <servlet-name>B</servlet-name> 
    <url-pattern>/servlet/b</url-pattern> 
    </servlet-mapping> 

    <servlet-mapping> 
    <servlet-name>C</servlet-name> 
    <url-pattern>/servlet/c</url-pattern> 
    </servlet-mapping> 

    <session-config> 
    <session-timeout>5</session-timeout> 
    </session-config> 
</web-app> 

Hãy chắc chắn để nạp InitializationServlet đầu tiên, sử dụng một giá trị thấp <load-on-startup>.

Lợi ích của cách tiếp cận này là HttpServlet đối tượng có thể được xử lý giống như bất kỳ đối tượng Java hoặc bean thông thường nào khác. Do đó, nó cung cấp sự kiểm soát tốt hơn đối với việc khởi tạo: không có nhiều thứ phức tạp hơn để thực hiện trong phương thức init(), cũng như xử lý servlet init-arg lộn xộn.

+0

Làm thế nào servlets có thể được singleton nếu chúng ta có constructor parameterized hoặc một constructor công khai? ? Thùng chứa servlet có một instace của "SampleServlet" như trong ví dụ của bạn. bạn có thể vui lòng xây dựng.? –

Các vấn đề liên quan