有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java不直接编写servlet来创建REST API的原因

在我目前的公司,我们正在启动一个新项目,它将是Java中的REST API,部署在像Tomcat这样的servlet容器中。在我之前使用诸如Jersey的JAX-RS、JBOSS REST Easy、Spring MVC等REST框架的经验中,我知道使用这种框架比直接编写servlet来处理请求有哪些优点

(当然,我们知道上述框架仍在幕后使用servlet)

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

以下是我的理由:

1)更少的样板文件和更简洁的代码(更易于维护和测试)。使用JAX-RS框架或SpringMVC,您可以通过编写带有注释的方法来非常轻松地定义REST资源,这些注释指示资源的路径、要使用的http方法、查询和url参数、接受的编码等标题

例如:

@GET
@Path("/users")
@Produces({MediaType.APPLICATION_JSON}) 
public UserList getUsers(@QueryParam("group") String group) {
    return userService.findUsers(group);
}

使用servlets,您至少需要以下内容:

映射web中每个servlet的url。xml(Servlet 3.0及以上版本中不需要):

<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类中:

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和Jersey这样的框架使得为您的请求、响应配置序列化程序/反序列化程序变得非常容易

3)休息最佳实践。通常,这些框架是基于对REST API所遵循的最佳实践的坚实理解而构建的,并且是基于REST体系结构的标准定义的,这使得构建一个坚实且符合标准的应用程序变得更加容易。另一方面,Servlets在如何处理请求/响应方面为您提供了非常高的自由度,因此很难意识到您根本没有被RESTfull

还有别的吗


共 (2) 个答案

  1. # 1 楼答案

    对我来说,使用Spring MVC的真正优势在于提高了生产率。如果你需要一个真正定制的应用程序,从零开始编写所有东西来调整是有意义的。虽然在没有框架的情况下创建新的东西很酷,但当它变得更大时,你将面临数百个该死的优秀开发人员已经解决的问题。使用Spring MVC将为您节省大量时间,而这些时间可能会浪费在重新发明轮子上,当您需要培训某人处理您的优秀自定义代码时,甚至会节省更多时间

  2. # 2 楼答案

    几个月前,我发表评论说,我确实支持纯Servlet 3.0解决方案,反对使用REST MVC框架

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

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

    以下是我的工作示例:

    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;
    }  
    

    也许这些框架有一个你绝对需要的特性,但对我来说,它应该足够决定性,值得额外的lib的麻烦

    正如法国作家Antoine de Saint Exupery所说:

    “完美不是在没有更多东西可添加时实现的,而是在没有任何东西可带走时实现的”

    我把杰克逊带走是为了更接近它:-)

    (是的,我必须承认,我使用了GSON,但它是一个小罐子,不需要任何配置)