如今是否仍需使用web.xml与faces-config.xml?适用场景解析
Great question! Even with Java EE 8's robust annotation support, there are still plenty of scenarios where web.xml and faces-config.xml aren't just helpful—they're actually necessary. Let's break this down for each descriptor:
web.xml (Web Deployment Descriptor) Global application-wide settings annotations can't handle
Annotations are per-class or per-method, so they can't cover global app-level configurations. For example:- Setting session timeout for all users:
<session-config> <session-timeout>30</session-timeout> <!-- 30-minute sessions --> </session-config> - Defining context parameters like JSF's project stage (critical for production vs development behavior):
<context-param> <param-name>javax.faces.PROJECT_STAGE</param-name> <param-value>Production</param-value> </context-param>
- Setting session timeout for all users:
Integrating legacy or third-party libraries without annotations
Many older third-party tools (think legacy security frameworks, logging utilities, or custom servlets) weren't built with Java EE annotations in mind. If you need to register a listener, filter, or servlet that doesn't have@WebListener,@WebFilter, or@WebServletannotations,web.xmlis your only option. For example:<listener> <listener-class>com.legacy.security.SessionMonitorListener</listener-class> </listener>Overriding annotation-based configs across environments
Suppose you have a servlet annotated with@WebServlet("/api/v1/*"), but in your production environment you need to change the path to/prod/api/*. Instead of modifying code and redeploying, you can override the mapping directly inweb.xml—it takes precedence over annotations.Complex security constraints
While@ServletSecurityworks for simple cases, complex security rules (like restricting access to multiple URL patterns for specific roles, or configuring form-based login with custom error pages) are far easier to manage inweb.xml. For example:<security-constraint> <web-resource-collection> <web-resource-name>Admin Area</web-resource-name> <url-pattern>/admin/*</url-pattern> </web-resource-collection> <auth-constraint> <role-name>ADMIN</role-name> </auth-constraint> </security-constraint> <login-config> <auth-method>FORM</auth-method> <form-login-config> <form-login-page>/login.xhtml</form-login-page> <form-error-page>/login-error.xhtml</form-error-page> </form-login-config> </login-config>Global error page mapping
Customizing error pages for HTTP status codes (404, 500, etc.) or exceptions requiresweb.xml—there's no annotation that lets you define global error handlers. Example:<error-page> <error-code>404</error-code> <location>/404.xhtml</location> </error-page>
faces-config.xml (JSF Application Configuration Resource) Global JSF application settings
Annotations can't touch many core JSF global configurations. For instance:- Setting a default locale and resource bundle for the entire app:
<application> <locale-config> <default-locale>en</default-locale> <supported-locale>fr</supported-locale> </locale-config> <resource-bundle> <base-name>com.myapp.resources.Messages</base-name> <var>msg</var> </resource-bundle> </application> - Registering custom
ELResolvers orViewHandlers to extend JSF's core behavior.
- Setting a default locale and resource bundle for the entire app:
Registering converters/validators for third-party classes
If you need to add a JSF converter or validator to a class you don't own (like a third-party POJO), you can't use@FacesConverteror@FacesValidatorannotations. Instead, bind them infaces-config.xml:<converter> <converter-for-class>com.thirdparty.model.DateRange</converter-for-class> <converter-class>com.myapp.converters.DateRangeConverter</converter-class> </converter>Complex navigation rules
While JSF 2.x+ supports implicit navigation and@NavigationCaseannotations, intricate navigation logic (like conditional redirects based on user roles or view parameters) is much easier to visualize and maintain infaces-config.xml. Example:<navigation-rule> <from-view-id>/checkout.xhtml</from-view-id> <navigation-case> <from-outcome>success</from-outcome> <to-view-id>/confirmation.xhtml</to-view-id> <redirect/> </navigation-case> <navigation-case> <from-outcome>failure</from-outcome> <to-view-id>/checkout-error.xhtml</to-view-id> </navigation-case> </navigation-rule>Composite component and resource library contract configuration
JSF composite components often require registration infaces-config.xmlfor global access, and resource library contracts (a JSF 2.2+ feature for theming) can only be configured here:<resource-library-contract> <contract-name>dark-theme</contract-name> <contract-path>/themes/dark</contract-path> </resource-library-contract>Overriding built-in JSF component behavior
If you want to replace the renderer for a standard JSF component (like customizing howh:inputTextrenders), you need to register your custom renderer infaces-config.xml—annotations don't support this level of core component customization.
At the end of the day, annotations are fantastic for reducing boilerplate and keeping config close to your code, but these descriptors still excel at handling global, cross-cutting, legacy, or highly configurable scenarios. It's all about picking the right tool for the job!
内容的提问来源于stack exchange,提问作者David Ferreira

