『译』Java EE 六 Pocket.Guide— Servlets3.0(三)

『译』Java EE 6 Pocket.Guide— Servlets3.0(三)

Web Fragments

 

  一个web fragment是包含在一个库或框架JAR的META-INF目录中的web.xml的一部分或全部,如果这个框架绑定在WEB-INF/lib目录中,容器将选择和配置的框架,而不需要开发人员明确的做什么。几乎所有的元素,可以在web.xml中指定,然而,顶层元素必须是web-fragment,相应的文件必须被称为web-fragment.xml,这使得Web应用程序的配置逻辑分开:

<web-fragment>
  <filter>
    <filter-name>MyFilter</filter-name>
    <filter-class>org.example.MyFilter</filter-class>
    <init-param>
      <param-name>myInitParam</param-name>
      <param-value>...</param-value>
    </init-param>
  </filter>
  <filter-mapping>
    <filter-name>MyFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
</web-fragment>
 

  在web.xml和web-fragment.xml中开发人员可以指定需要加载资源的顺序。web.xml文件中的<absolute-ordering>元素用于指定应该被加载的资源的确切顺序,web-fragment.xml内的<ordering>元素用于指定相对顺序。这两个命令是互斥的,绝对顺序覆盖相对顺序。绝对排序的<name>元素包含一个或多个需要被加载的指定名称和资源的顺序,<others/>允许为其他资源按未指定的顺序加载:

 

<web-app>
  <name>MyApp</name>
  <absolute-ordering>
    <name>MyServlet</name>
    <name>MyFilter</name>
  </absolute-ordering>
</web-app>

  在这段代码中,加载在web.xml中指定的资源,然后是MyServlet和MyFilter。

 

  <ordering>元素可以用零个或一个<before>和<after>元素,分别指定web-fragment被加载之前或加载之后需要的资源:

 

<web-fragment>
  <name>MyFilter</name>
  <ordering>
    <after>MyServlet</after>
  </ordering>
</web-fragment>

  这段代码将需要在容器的的资源MyServlet(在其他地方定义)被加载后,加载资源MyFilter。

 

  如果web.xml中metadata-complete设置为true,那么webfragment.xml不被处理,web.xml中具有最高优先级,这解决了web.xml和web-fragment.xml之间冲突。如果一个的web-fragment.xml没有一个<ordering>元素或者web.xml不具有<absolute-ordering>元素,资源被假设为没有任何顺序依赖性。

 

Security

 

  Servlet通常是通过互联网访问,因此具有安全性要求。servlet的安全模型,包括角色、访问控制和认证需求,可以使用注解或在web.xml中指定。@ServletSecurity用于指定servlet实现类的所有方法或特定的doXXX方法安全约束。容器执行相应的doXXX信息可以被特定的角色用户所调用:

 

@WebServlet("/account")
@ServletSecurity(value=@HttpConstraint(rolesAllowed = {"R1"}),httpMethodConstraints={@HttpMethodConstraint(value="GET",rolesAllowed="R2"),@HttpMethodConstraint(value="POST",
rolesAllowed={"R3", "R4"})})
public class AccountServlet extends javax.servlet.http.HttpServlet {
  //. . .
}

     在这段代码中,@HttpMethodConstraint用于指定R2可以调用doGet()方法,R3和R4角色可以调用doPost()方法。@HttpConstraint指定R1可以调用所有的方法,角色映射容器中的安全主体或团体。

 

  安全限制,也可以使用在web.xml中指定的<security-constraint>元素;<webresource-collection>用于指定HTTP操作和网络资源的限制,<auth-constraint>用于指定允许访问该资源的角色,<user-data-constraint>的子元素<transportguarantee>表示数据如何在客户端和服务器之间应受到保护:

 

<security-constraint>
  <web-resource-collection>
    <url-pattern>/account/*</url-pattern>
    <http-method>GET</http-method>
  </web-resource-collection>
  <auth-constraint>
    <role-name>manager</role-name>
  </auth-constraint>
  <user-data-constraint>
    <transport-guarantee>INTEGRITY</transport-guarantee>
  </user-data-constraint>
</security-constraint>

  此部署描述符明确doGet()方法只能由经理角色用户访问。

 

  @ RolesAllowed、@ DenyAll、PermitAll和@Transport注释,来指定提供另一套保护机制,限制访问一个特定的资源或资源方法:

 

@RolesAllowed("R2")
protected void doGet(HttpServletRequest request,HttpServletResponse response) {
  //. . .
}

    如果一个注解在类和方法级别上都指定,方法指定将覆盖类中指定。在大多数的情况下,一个@RolesAllowed、@DenyAll、@PermitAll可以指定一个目标,@TransportProtected注解中可能出现任意组合的@RolesAllowed或@PermitAll注解。

 

  servlets可配置HTTP基本信息、HTTP摘要、HTTPS客户端以及基于表单的身份验证:

 

<form method="POST" action="j_security_check">
  <input type="text" name="j_username">
  <input type="password" name="j_password">
  <input type="button" value="submit">
</form>
  这段代码显示了如何实现基于表单的验证。登录表单域必须包含输入用户名和密码,这些字段必须被命名为 j_userj_password,form表单的action是 j_security_check
  HttpServletRequest还提供了编程式的安全登录、注销和验证方法,登录方法通过配置在ServletContext中的密码验证框架(特定于容器)验证用户名和密码,确保getUser()、getRemoteUser(),getAuthType()等方法返回校验值,登录验证方法可以替换基于表单的验证。
  验证方法使用配置在为ServletContext容器中的登录机制对要登录的用户进行身份验证。

 

Resource Packaging

 

  在.war文件内置的资源文件,可以使用Servlet的Context.getResource()和Context.getResourceAsStream()方法进行访问,资源路径由前面有一个“/”的字符串所指定。访问路径是上下文路径的根路径,或者是相对于META-INF/resources目录,WEB-INF/lib目录下的JAR文件所在的目录:

 

myApplication.war
  WEB-INF
    lib
      library.jar

 

library.jar构造如下:

library.jar
  MyClass1.class
  MyClass2.class
  stylesheets
    common.css
  images
    header.png
    footer.png
 

  如果捆绑在样式表和图像目录的资源文件,需要在servlet中被访问,则需要手动的获取Web应用程序的根目录。库可以打包,资源文件放在META-INF/resources目录:

 

library.jar
  MyClass1.class
  MyClass2.class
  META-INF
    resources
      stylesheets
        common.css
      images
        header.png
        footer.png

  在这个例子中,资源文件不需要解压到application的根目录也可以被访问。这就允许第三方jar包的资源文件可以被直接访问,而不需要手动解压到实际路径。

  资源总是在先寻找application的根目录,再扫描WEB-INF/lib目录中的JAR文件。在WEB-INF/lib目录下的JAR文件扫描的顺序是不确定的。

 

Error Mapping

 

  应用程序中当一个servlet产生一个错误,HTTP错误代码或serlvet抛出的异常可以映射到一个自定义内容界面的绑定资源。这允许从您的Web应用程序的自定义页面,细粒度的映射错误,这些页面定义使用<error-page>:

 

<error-page>
  <error-code>404</error-code>
  <location>/error-404.jsp</location>
</error-page>

    将上述片段添加到web.xml中,如果访问一个不存在的资源,将显示/error-404.jsp的页面给客户端。同时这个映射可以很容易地通过添加其他<error-page>元素获取其他的HTTP状态码。

 

  <exception-type>元素用于映射由Web应用程序中servlet抛出的异常的资源文件:

 

<error-page>
  <exception-type>org.example.MyException</exception-type>
  <location>/error.jsp</location>
</error-page>

  上述片段添加到web.xml中,如果servlet抛出的org.example.MyException异常,将显示/error.jsp页面给客户端。这可以很容易地映射其他异常,以及添加其他<errorpage>元素。

  每个类的名字名和HTTP状态码,<error-page>声明必须是唯一的。

 

Handling Multipart Requests

 

  在一个servlet可以指定@MultipartConfig注解,它准备接受一个multipart/form-data的类型请求。HttpServletRequest.getParts()和HttpServletRequest.getPart()方法,得到multipart请求的每个parts:

 

@WebServlet(urlPatterns = {"/FileUploadServlet"})
@MultipartConfig(location="/tmp")
public class FileUploadServlet extends HttpServlet {
  @Override
  protected void doPost(HttpServletRequest request,HttpServletResponse response)throws ServletException, IOException {
    for (Part part : request.getParts()) {
      part.write("myFile");
    }
  }
}

 

  代码中:

  • @MultipartConfig指定类的doPost方法,接受一个multipart/form-data的请求类型

  • 属性location用于指定的文件存储的目录位置

  • getParts()方法提供一个multipart 请求的parts集合

  • part.write() 用于写入上传的part到磁盘

  可以从JSP页面调用这个servlet

 

<form action="FileUploadServlet" enctype="multipart/form-data" method="POST">
  <input type="file" name="myFile"><br>
  <input type="Submit" value="Upload File"><br>
</form>

  这段代码表示, 表单用multipart/form-data格式编码以post方式提交给FileUploadServlet。