开发者

Can we replace the purpose of init method to the servlet constructor?

Can we replace the pupose of init method to the servlet constructor? My question is why does servlet need a separate method int(ServletConfig config) for the pupo开发者_StackOverflow中文版se of initialization we could have achieve the same thing by having a parameterised constructor let XServlet(ServletConfig config) and the container can invoke the same .


Probably because you cannot specify the parameter signature for constructors in an interface.


It is generally considered a bad practice to perform logic in constructor (it should only initialize the field and create object in consistent state). It also makes testing harder.

Also it is much harder to perform injection - when using init the container can create a servlet, inject dependencies and run init. With constructor you would expect to have all the dependencies already set. Wicket works around this problem by injecting Spring beans into page class from superclass constructor - because superclass constructor runs first. However modifying subclass fields from superclass constructor seems wrong.

That being said using separate init method some things simpler and easier to maintain. Also note that EJB promotes @PostConstruct annotation as well.


I guess this choice was made to simplify the coding of servlets. In the current situation, a servlet having no need for specific initialization can be coded like this:

public class MyServlet extends HttpServlet {
    // doGet, doPost, etc.
}

If the servlet was initialized using the constructor, it would need to be coded like this:

public class MyServlet extends HttpServlet {

    public MyServlet(ServletConfig config) {
        super(config);
    }

    // doGet, doPost, etc.
}

BTW, they even introduced a no-arg init method that can be used to avoid being forced to call super.init(config).


Short answer: NO.

Long answer: If a servlet contains a constructor and a init method, you will see the constructor is called first, and then the init method (try it out with sysout statements).

A servlet is a java class, so it must follow the java process, so constructor is called first and then the init method (note that the init method is called by your servlet container like tomcat because that's how servlet's are supposed to be initialized; read the servlet specification).

So, if you need to do some operation that is specific to your business need (say create an DB connection or read a set of user details etc); constructors are not the best place to put these things in.

Usually constructors should never have any complex logic/business processing. They should initialize bare minimum member variables and leave the complex things to later; in case of servlets the heavy lifting can be done by init method.

Also note that by the time the init() is called the servlet container is up and ready with it's system resources, i.e it would have initialized the JNDi name bindings, data sources so on and so forth. So in a way it guarantees you that when you call the init(), it will have the system resources ready for you to work on.

The servlet 3 spec says this:

2.3.1 Loading and Instantiation The servlet container is responsible for loading and instantiating servlets. The loading and instantiation can occur when the container is started, or delayed until the container determines the servlet is needed to service a request. When the servlet engine is started, needed servlet classes must be located by the servlet container. The servlet container loads the servlet class using normal Java class loading facilities. The loading may be from a local file system, a remote file system, or other network services. After loading the Servlet class, the container instantiates it for use.

2.3.2 Initialization After the servlet object is instantiated, the container must initialize the servlet before it can handle requests from clients. Initialization is provided so that a servlet can read persistent configuration data, initialize costly resources (such as JDBC APIbased connections), and perform other one-time activities. The container initializes the servlet instance by calling the init method of the Servlet interface with a unique (per servlet declaration) object implementing the ServletConfig interface. This configuration object allows the servlet to access name-value initialization parameters from the Web application’s configuration information. The configuration object also gives the servlet access to an object (implementing the ServletContext interface) that describes the servlet’s runtime environment. See Chapter 4, Servlet Context for more information about the ServletContext interface.

Read this part:

The servlet container loads the servlet class using normal Java class loading facilities.

so, the container will have to use standard java class loading mechanism. Which means it can not do what Duncan have just suggested.


int(ServletConfig config) is a life cycle method of Servlet.and it is being called by servlet container.

We can replace the init method code in parameter constructor of super class servlet. but we can't force the developer to call super class constructor for example

 /*If generic servlet has a constructor like this*/
      public GenericServlet(ServletConfig  config){
        ....
 }

 /*And Developers servlet is calling only default servlet.*/
public MyServlet(){
  super();
}

So in this scenario initialization never happens for that servlet. it cause issues problem. because ServletConfig obj is not initialized. And we cant force the user to call specifict super class constructor.


The simple answer is that you have to have a no-arg ctor and an init method because that is what the spec requires...

Why the spec is written like that is probably a matter of history. These days I think that we might defer construction until the ServletContext is available and call a ctor with that argument. But looking back there was a ServletContext.getServlet(name) method, so that one servlet could look up another on initialisation and communicate with it. For this to work they would all have had to be created up-front and then init'd.

getServlet was deprecated and now returns null (I think it was a security hole for containers that were running multiple apps).

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜