`
masterkey
  • 浏览: 338828 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

New Servlet 3.0 (JSR-315) Specification

阅读更多

Introduction

All modern Java web applications use Servlets and Filters. They are the backbone of Java EE, the communication gateway to the World Wide Web.

Now there is a new specification coming, Servlet 3.0 (JSR-315). The Early Draft of this specification features some new really neat features, and in my opinion some mistakes. In this article I'm going to show the new additions to the EOD (ease of development), comment on them, and try to improve them.

Servlets

Since Servlet 2.3 we've been using the Servlet interface to create our Servlets. This interface has one main method called service(ServletRequest reand a ServletResponse. The abstract class HttpServlet helps us to create a HTTP suitable Servlet. It contains methods like doGet and doPost.

The easiest way to create custom behavior was to extend the HttpServlet and implement your own doGet and/or doPost.

public class GetPostServlet extends HttpServlet {
  public void doGet(HttpServletRequest req, HttpServletResponse res) 
    throws ServletException, IOException {
     ....
  }
}

To instruct a Servlet Container to use your Servlet you have to add them to a file called the web.xml. This file contains mapping information from URL to Servlet, so when a user requests the mapped URL the Servlet will be called and asked for a response.

JSR-315

Servlet 3.0 has a couple of proposed changes. One of the big changes is adding support for continuations, in the new API you can call request.suspend() to suspend the request, and later (from another thread) call request.resume(), the Servlet is then again called to resume the request.

The second important addition is pluggability. Servlets can now be added to the container during runtime. If you create an instance of the ServletContextListener you can call servletContext.addServlet() and servletContext.addServletMapping() to add Servlets on runtime. Of course this poses a security risk, because included JARs could register their own Servlets, something you definitely don't want. But the specification is aware of this, and working on making it safer (for example, giving you a switch to turn auto-detection off).

The third major addition are the new annotations. Here is an example of these annotations in use:

@Servlet(urlMapping={"/myServlet"}, name="MyServlet")
public class PojoServlet() {
  @GET
  public void handleGet(HttpServletRequest req, HttpServletResponse resp) {
     ....
  }
}

As you can see there are a couple of new features. First of all, the Servlet is a POJO; there is no more interface/abstract class. Also notice the url mapping in the @Servlet annotation; no need for the mapping in the web.xml.

Then there are the Filters:

@ServletFilter
@FilterMapping(urlPatter="/myFilter")
public class PojoFilter() {
  public void doFilter(HttpServletRequest req, HttpServletResponse resp) {
     ....
  }
}

Here we can see a ServletFilter with the new annotations. This again has the mapping in the annotation, no need for the web.xml and it is a POJO again, no more interface/abstract class.

What is the problem?

So you might ask, what is wrong with this proposals new ease of development?

Well, maybe a couple of things. First of all, lets see what these new annotations add:

  • The mapping information is in the Servlet
  • The Servlets are POJO's
  • You can specify which method handles the GET and POST

Well, first of all the mapping information, which is a great feature. Although the naming of the annotations is a bit unfortunate. Why does the @Servlet annotation have the mapping inside, and does the @ServletFilter have a seperate annotation @FilterMapping? It would be much cleaner to have one way of declaring these mappings.

The second and third change (the ability to specify the GET and POST with @GET, @POST, @HEAD, @PUT etc.) has only one small advantage. Who hasn't written the following code while creating Servlets:

public class GetPostServlet extends HttpServlet {
  public void doGet(HttpServletRequest req, HttpServletResponse res) 
    throws ServletException, IOException {
    handleRequest(req,res);
  }
  public void doPost(HttpServletRequest req, HttpServletResponse res) 
    throws ServletException, IOException {
    handleRequest(req,res);
  }

  /* Handle GET and POST */
  public void handleRequest(HttpServletRequest req, HttpServletResponse res) 
    throws ServletException, IOException {
    ....
  }
}

This could be done a lot easier with the new annotations:

@Servlet
public class GetPostServlet {
  @GET
  @POST
  public void handleRequest(HttpServletRequest req, HttpServletResponse res) 
    throws ServletException, IOException {
    ....
  }
}

So, nothing wrong here! Well, I asked if you could specify two of these annotation on one method during the launch of the specification on JavaOne 2008, but the spec-lead wasn't sure this could be done. So this is probably not the way its meant to be used.

And there is more, this also adds problems to the code, for example what if I coded this:

@Servlet
public class GetPostServlet {
  @GET
  public void requestOne(HttpServletRequest req, HttpServletResponse res) 
    throws ServletException, IOException {
    ....
  }
  @GET
  public void requestTwo(HttpServletRequest req, HttpServletResponse res) 
    throws ServletException, IOException {
    ....
  }
}

Now which method will be called? I have no idea! This will probably not even be documented, just like having two Servlets mapped on the same URL, you just can't predict what will happen, its up to the container.

These annotations are (supposed to be) added to help the developers, but there are more problems. The IDE doesn't know you are making a Servlet just because you add one annotation, so there is no support from the current generation of IDE's. When we had the interface or abstract class you would just override the methods you want, and you have code-completion. This is a huge advantage we'll loose when programming with these annotations!

It gets even worse if you look at the @ServletFilter. When you add this annotation to your code it turns the POJO into a Filter. But there is no check if you have implemented the doFilter() method. Also, it is much more error-prone, what if you accidently misspell "doFilter"?

The same thing also applies to the @ServletListenerContext, just look at this example:

@ServletContextListener
public class MyListener {
  public void contextInitialized(ServletContextEvent sce) {
     ....
  }
}

Again, nothing will check if you correctly spelled "contextInitialized" (which is a pretty hard word to type over and over without error-checking), you'll always have to manually double check. I'd rather type "implements ServletContextListener" instead of "@ServletContextListener" and then let my IDE write the implementing methods.

Okay, that is enough tough feedback. Next I would like to do something constructive and explain what direction I would like to see Servlet 3.0 go.

Proposal 1

The idea of having annotations for the url-mapping if very good. URLs are a good example of metadata, it doesn't say anything about the class or inner workings, but it does tell the container when to call it. This is something you would use an annotation for, also because its not mandatory to have mapping in the class, it would work perfectly without it. But as I said before, the naming is a bit off, I'd rather see this:

@ServletMapping(name="....", mapping={"...","..."}) //Use for both Servlets and Filters

The second thing is the annotations (@GET, @POST). I don't think this will help the user in any way, so just leave them out. I know the standard reply will be "Just don't use them if you don't like them...".

But there are already a lot of Java features we should just 'not use'. The problem is, people WILL use them, and it doesn't help them! In fact it will only add more choices/options for the programmers, making it all less clear if you incidentally have to work with Servlets. I personally haven't heard anybody complain about the interfaces/abstract classes before... And I can't seem to find any new advantage that it adds, only loosing the type-safety!

This was exactly the thing I was afraid of when they introduced annotations, people who start using them because they can, not because they have some metadata they want to have near the classes instead of in separate XML files.

Proposal 2

But *sigh* if they really want to use the annotations on the methods, then please add functionality to the Servlets. Currently they'll just serve as a (bad) alternative way of writing Servlets. But with a slight change you could actually add new features with these annotations, like this:

public class ExampleServlet {
  
  @ServletMethod(name="LoginServlet", mapping="/login", type={ServletType.GET, ServletType.POST})
  public void handleLogin(...) { ... }
  
  //And:
  
  @FilterMethod(name="AuthorizationFilter", mapping="/login", type={ServletType.POST})
  public void doAuthorization(...) { ... }
}

This way you can have one class (POJO) with all the handling methods for a specific Use Case. More or less like the new Spring MVC Controllers. You'll still have the same functionality as the proposed JSR-315 annotations, but now you can group Servlet methods in one class! You still have the drawbacks I mentioned before, regarding the type-safety, but by using these annotations you actually gain some functionality and freedom.

Conclusion

My preference would still be not using annotations at all for GET/POST methods, but I've read the Java EE 6 specification is promoting the use of annotations like this and the JSR-315 writers have 'no choice' (bad excuse). The comments I made in this article have been send to the JSR-group, but I haven't got a response yet.

Also I've been unable to reach members for a reaction and/or explanation and/or clarification. Recently the Java EE 6 specification went on public review, and it contains references to this Servlet 3.0 specification, so it will become part of Java EE 6. This must mean they are working actively, maybe even franticly, to finish it on time. But I plead them to take the time to reconsider their choices about the annotations.

分享到:
评论

相关推荐

    servlet-api-3.0-alpha-1.jar

    Servlet 3.0引入了对JSR 330(依赖注入)的支持,允许开发者使用注解(@Inject)来声明和管理依赖关系,从而简化代码并提高可测试性。这减少了对XML配置文件的依赖,使得应用程序更加灵活和易于维护。 2. **异步处理...

    undertow-websockets-jsr-2.1.7.Final-API文档-中文版.zip

    赠送jar包:undertow-websockets-jsr-2.1.7.Final.jar; 赠送原API文档:undertow-websockets-jsr-2.1.7.Final-javadoc.jar; 赠送源代码:undertow-websockets-jsr-2.1.7.Final-sources.jar; 赠送Maven依赖信息...

    servlet3.0 规范pdf 包含javadoc

    在JSR-315(JavaTM Servlet 3.0 API Specification)中,专家小组对这项规范进行了详尽的定义和解释。这个规范PDF文件是开发人员深入理解Servlet 3.0的核心资源,同时包含的javadoc为开发者提供了API的详细文档,...

    javax.servlet-3.0

    它是由Java Community Process (JCP) 通过JSR(Java Specification Request)制定的标准,用于定义Servlet API的接口和类,是开发基于Java的Web应用程序的关键组件。 【描述】"javax.servlet-3.0" 重复提及三次,...

    EJB3.0规范-EJB3.0 SPECIFICATION

    7. **依赖注入(Dependency Injection, DI)**:EJB3.0引入了JSR-299(后来成为CDI,Contexts and Dependency Injection)的早期形式,允许通过`@Inject`注解实现依赖的自动装配。 8. **查询语言(JPQL)**:Java ...

    undertow-websockets-jsr-2.1.7.Final-API文档-中英对照版.zip

    赠送jar包:undertow-websockets-jsr-2.1.7.Final.jar; 赠送原API文档:undertow-websockets-jsr-2.1.7.Final-javadoc.jar; 赠送源代码:undertow-websockets-jsr-2.1.7.Final-sources.jar; 赠送Maven依赖信息...

    JSR-303接口标准和参考实现

    JSR-303接口标准,全称为Java Specification Request 303,是Java平台上的一个规范,旨在提供一种统一的、与框架无关的bean验证框架。该标准由Java Community Process(JCP)提出,目的是简化Java应用中的数据验证...

    jsr-275-1.0-beta-2.jar

    java.lang.ClassNotFoundException: javax.measure.converter.ConversionException所需的jar

    官方servlet3.0.rar

    Servlet 3.0通过JSR-330规范实现了依赖注入(DI),使得开发者可以利用如`@Inject`注解来注入依赖,简化了组件之间的耦合。 6. **可选的部署描述符(Optional Deployment Descriptors)** 虽然XML配置仍然可用,...

    JSR-133 Java 内存模型 英文版

    This document is the proposed final draft version of the JSR-133 specification, the Java Memory Model (JMM) and Thread Specification. This specification is intended to be part of the JSR-176 umbrella ...

    undertow-websockets-jsr-2.2.14.Final-API文档-中文版.zip

    赠送jar包:undertow-websockets-jsr-2.2.14.Final.jar; 赠送原API文档:undertow-websockets-jsr-2.2.14.Final-javadoc.jar; 赠送源代码:undertow-websockets-jsr-2.2.14.Final-sources.jar; 赠送Maven依赖信息...

    undertow-websockets-jsr-2.2.14.Final-API文档-中英对照版.zip

    赠送jar包:undertow-websockets-jsr-2.2.14.Final.jar; 赠送原API文档:undertow-websockets-jsr-2.2.14.Final-javadoc.jar; 赠送源代码:undertow-websockets-jsr-2.2.14.Final-sources.jar; 赠送Maven依赖信息...

    Java EE Security (JSR-375) Specification.zip

    2. **统一的安全上下文**:JSR-375定义了一个统一的安全上下文,使得在各种Java EE组件之间(如Servlet、EJB、JMS、JPA等)可以方便地访问和管理安全信息,如当前用户身份、角色和会话状态。 3. **容器管理的身份...

    servlet 3.0 规范提案

    发布,作为JSR-000315的一部分。这个版本引入了许多新特性和改进,旨在提升Web应用程序的开发效率和灵活性。以下是Servlet 3.0规范中的关键知识点: 1. **注解支持**: - Servlet 3.0引入了对注解的全面支持,允许...

    servlet3.0文档html

    7. **WebSocket支持**:虽然Servlet 3.0本身不直接支持WebSocket,但它是WebSocket规范的基础,提供了JSR 356(Java API for WebSocket)的实现,使得开发者能够创建高性能、低延迟的双向通信应用。 8. **JNDI查找...

    23 Spring Core参数校验之JSR303_JSR-349注解-慕课专栏1

    User user = new User(); Set<ConstraintViolation<User>> violations = validator.validate(user); if (!violations.isEmpty()) { // 处理验证错误 } ``` 在实际运行时,如Tomcat等服务器需要提供EL(Expression ...

    JSR-133-Java Memory Model Specification 中文版+英文版+参考资料

    JSR133-memory_model-1_0-pfd2-spec.pdf JSR133中文版.pdf j-jtp02244-Java.theory...The JSR-133 Cookbook.pdf jsr-133-faq.pdf JSR-133-Appr-The Java Memory Model.pdf 深入理解Java内存模型之系列篇 - CSDN博客.pdf

    Servlet3.0 新特性之模块化实践

    Servlet 3.0支持JSR-330标准的依赖注入(DI)功能,允许开发者使用`@Inject`注解注入依赖对象,减少了手动管理对象和依赖关系的工作。这有助于实现松耦合,使代码更加易于测试和维护。 七、过滤器链的改进 在...

    JSR-107 标准手册 Specification

    JSR-107,即JCache API,是一个旨在为Java程序提供与缓存系统交互的API规范。在Java社区中,分布式缓存对于提升系统的性能和可伸缩性起着至关重要的作用。然而,直到JSR-107标准的出现之前,Java平台并没有一个完整...

    JSR-75-135-172_Supported List.xls

    JSR-75-135-172_Supported List 主流手机对JSR 75 135 172的支持!

Global site tag (gtag.js) - Google Analytics