首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >不直接为创建REST编写Servlets的原因

不直接为创建REST编写Servlets的原因
EN

Stack Overflow用户
提问于 2014-02-21 23:33:42
回答 4查看 21.3K关注 0票数 25

在我当前的公司中,我们将启动一个新项目,它将是Java中的REST,部署在像Tomcat这样的servlet容器中。在我以前的经验中,我使用了一些REST框架,比如与泽西一起使用JAX、JBOSS轻松、Spring,我知道使用类似于直接编写Servlets来处理请求的框架有哪些优点。

(当然,我们知道前面提到的框架仍然在幕后使用Servlets )

我发现很难说服他们。正如他们建议编写servlet一样,认为这对性能更好(这是可能的,但我认为使用其中一个框架的开销对于REST来说应该是微不足道的)。

以下是我的理由:

1) 少样板,代码更简洁(易于维护和测试)。使用JAX框架或SpringMVC,您可以非常容易地通过编写方法来定义REST资源,其中包含指示资源路径的注释、要使用的http方法、查询和url参数、标头(如编码接受)等。

示例:

代码语言:javascript
运行
复制
@GET
@Path("/users")
@Produces({MediaType.APPLICATION_JSON}) 
public UserList getUsers(@QueryParam("group") String group) {
    return userService.findUsers(group);
}

有了servlet,您至少需要这样的东西:

为web.xml中的每个servlet映射url (这在Servlet3.0中和Servlet3.0之上是不必要的):

代码语言:javascript
运行
复制
<servlet>
    <servlet-name>UsersServlet</servlet-name>
    <servlet-class>test.UsersServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>UsersServlet</servlet-name>
    <url-pattern>/users</url-pattern>
</servlet-mapping>

然后在servlet类中:

代码语言:javascript
运行
复制
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 
    String group = request.getParameter("group");
    response.setContentType("application/json");
    PrintWriter out = response.getWriter();
    JsonSerializer someJsonSerializer = new JsonSerializer();
    String json = someJsonSerializer.serialize(userService.findUsers(group));      
    out.print(json);
}

2) 适应性。上述框架允许您轻松地向应用程序添加功能,否则需要手动完成,比如使用多个媒体类型的输入和输出。例如,通过创建一个服务来返回xml或json或任何其他的服务,这取决于accept标头。像SpringMVC和泽西这样的框架可以非常容易地为您的请求和响应配置序列化/反序列化器。

3) REST最佳实践。通常,这些框架是建立在对REST所遵循的最佳实践的坚实理解之上的,并且是基于REST体系结构的标准定义的,这使得构建一个可靠和标准一致的应用程序更加容易。另一方面,Servlets在如何处理请求/响应方面给予您很高的自由度,因此很难意识到您根本不是RESTfull。

还有其他的吗?

EN

回答 4

Stack Overflow用户

发布于 2014-08-11 10:10:29

让我用我的答案来扮演魔鬼的提倡者。

首先,不需要将servlet添加到web.xml文件中。Servlet3.0允许您使用注解

第二,这些框架确实会对性能造成重大影响。请参阅这些基准

第三,您可以在servlet中使用葛森,它比Jackson (在Spring和泽西默认情况下使用)更快。这将使您获得更高的性能,特别是考虑到性能对您的需求至关重要。

最后,如果您关心样板,将您在servlet中编写的代码放在某个实用程序类中,并从多个servlet中使用它。当你(和大多数人一样)可能会使用它的一小部分功能时,这比承载一个框架的巨大负荷要好。

票数 31
EN

Stack Overflow用户

发布于 2016-09-25 12:55:17

几个月前,我发表评论说,我确实支持纯Servlet3.0解决方案,反对使用REST框架。

经过几个月的使用,我确认了我的选择!

我试着安装Jackson和其他框架,但是它比编写额外的5行代码需要更多的工作,而且我不需要处理额外的软件组件来安装、学习、更新.

下面是我的工作示例:

代码语言:javascript
运行
复制
package example;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.gson.Gson;

/**@WebServlet(name = "booking", urlPatterns = { "/api/v1/booking" })*/
public class BookingWs extends javax.servlet.http.HttpServlet {

    public static final Logger LOGGER = LoggerFactory.getLogger(BookingWs.class);

    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        
        try {
            // Used for JSON handling
            Gson gson = new Gson(); 
            
            // De-serialize from request
            BookingRequest bRequest = gson.fromJson(request.getReader(), BookingRequest.class);
            
            // Do your business logic.
            BookingResponse bResponse = new BookingResponse();
            bResponse.request = bRequest;
            bResponse.accepted = "bar".equalsIgnoreCase(bRequest.type);
            bResponse.reason = bResponse.accepted ? "Welcome" : "Only bar table booking left";
            
            // Serialize and send response back;
            response.setContentType("application/json");
            PrintWriter pw = response.getWriter();
            gson.toJson(bResponse, pw);
        } catch (Throwable t) {
            response.setStatus(500);
            PrintWriter pw = response.getWriter();
            pw.write("{\"error\":\"" + t.getLocalizedMessage() + "\"}");
        }
    }
}

class BookingRequest{
    String type;
    int seats;
    String name;
    long requiredTimestamp;
}

class BookingResponse{
    BookingRequest request;
    boolean accepted;
    String reason;
}  

也许这些框架有一个你绝对需要的特性,但对我来说,它应该是足够果断的,值得额外的语言的麻烦。

正如一位法国作家安托万·德圣·埃克斯伯里所说:

“完美不是在没有什么可补充的时候,而是在没有什么东西可以带走的时候”。

我带着杰克逊去接近它:)

(是的,我不得不承认,我用过GSON,但它是一个小罐子,不需要任何配置)。

票数 7
EN

Stack Overflow用户

发布于 2014-02-21 23:41:49

首先,我会考虑用两个具有"Hello“servlet的应用程序来设置一个简单的测试--一个是纯servlet,一个是Spring或Apache,或者是您选择的框架。然后运行一个性能测试,以证明(希望)性能影响是微不足道的。

另外,序列化器和反序列化器是一个很好的例子,但是这些框架中可用的拦截器/过滤器模式对于其他方面也非常有用:

  • 认证/安全
  • 需要时记录原始请求
  • 可以与业务逻辑分离的标头和内容转换

此外,还有一些工具可以插入到这些框架中,从而生成文档(WADL/WSDLs/注解)和客户端类库。还有一些测试库可以用来根据众所周知的框架生成自动化测试。

我以前也经常发明轮子。但这已不再有意义(如果曾经如此的话)。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/21947300

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档