如何通過properties文件配置web.xml中的參數(shù)
前言
因為公司項目需要,目前有本地環(huán)境、測試環(huán)境、開發(fā)環(huán)境。每次在將項目打包成war包的時候,都需要修改多處的配置,而使用maven的profile打包項目的時候,可以根據(jù)執(zhí)行打包命令時所帶的參數(shù)來進(jìn)行自動修改。
但是這種方式只對properties文件生效,即可以自動修改properties中的參數(shù),但是公司的項目有一個web.xml中的配置參數(shù)也需要修改,這時候就要考慮如何通過properties文件動態(tài)修改web.xml中的參數(shù)了。
實現(xiàn)思路
web.xml中需要修改的部分
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0" metadata-complete="true">
<!--用maven創(chuàng)建的web-app需要修改servlet的版本為3.1 -->
<welcome-file-list>
<welcome-file>/index.jsp</welcome-file>
</welcome-file-list>
<!--配置DispatcherServlet -->
<servlet>
<servlet-name>mypage-dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 配置SpringMVC 需要配置的文件 spring-dao.xml,spring-service.xml,spring-web.xml
Mybites -> spring -> springMvc -->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/spring-*.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>mypage-dispatcher</servlet-name>
<!--默認(rèn)匹配所有請求 -->
<url-pattern>/</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.html</url-pattern>
</servlet-mapping>
<filter>
<filter-name>testFilter</filter-name>
<filter-class>com.solr.filter.StringFilter</filter-class>
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>
com.sgm.tac.tid.common.action;
</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>testFilter</filter-name>
<url-pattern>*.*</url-pattern>
</filter-mapping>
</web-app>
這里需要改動的是45行,這是過濾器的初始化參數(shù)。不同的環(huán)境這里的參數(shù)是不一樣的,開始的思路是能否像application.xml中加載的properties文件一樣,通過${username}這種方式獲取properties中username對應(yīng)的value。但是后來發(fā)現(xiàn)在web.xml中貌似是不好實現(xiàn)的。
在這樣的需求下,web.xml就需要以編碼的方式來實現(xiàn)配置。spring4.0以上的版本支持web.xml的編碼配置。實現(xiàn)AbstractAnnotationConfigDispatcherServletInitializer接口,在servlet3.0中web.xml啟動時會檢測該接口實現(xiàn)類,從能夠在實現(xiàn)類中去配置filter。
需要注意的是以上的實現(xiàn),依賴servlet-api-3.0.jar和spring-webmvc-4.0以上版本jar包。
配置web.xml的類
package com.solr.filter;
import java.util.EnumSet;
import javax.servlet.DispatcherType;
import javax.servlet.Filter;
import javax.servlet.FilterRegistration;
import javax.servlet.FilterRegistration.Dynamic;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
import com.solr.util.PropUtils;
public class WebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
// TODO Auto-generated method stub
return null;
}
@Override
protected Class<?>[] getServletConfigClasses() {
// TODO Auto-generated method stub
return null;
}
@Override
protected String[] getServletMappings() {
// TODO Auto-generated method stub
return null;
}
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
// 系統(tǒng)啟動時注冊filter
FilterRegistration testFilter = servletContext.addFilter("testFilter", StringFilter.class);
// 設(shè)置init param, param可以從properties文件中讀取或其他方式獲取,提供一個想法
testFilter.setInitParameter("jersey.config.server.provider.packages", PropUtils.getValueByKey("FILTER.NAME"));
testFilter.addMappingForUrlPatterns(EnumSet.allOf(DispatcherType.class) , true, "*.*");
super.onStartup(servletContext);
}
@Override
protected Dynamic registerServletFilter(ServletContext servletContext, Filter filter) {
// TODO Auto-generated method stub
return super.registerServletFilter(servletContext, filter);
}
}
在繼承AbstractAnnotationConfigDispatcherServletInitializer的時候onStartup和registerServletFilter兩個方法沒有自動添加進(jìn)來,需要自己手動override。
其中onStartup在服務(wù)器啟動的時候會根據(jù)配置修改web.xml,此處通過addFilter添加了一個叫做testFilter的過濾器,通過setInitParameter向過濾器中設(shè)置參數(shù)。而這里PropUtils是自己寫的一個讀取properties文件的工具類,這樣就實現(xiàn)了將properties中的值動態(tài)添加到web.xml中了,最后打包修改properties的時候就可以修改web.xml了。
filter.properties文件
FILTER.NAME=HHH
PropUtils工具類
此工具類使用ResourceBundle讀取properties文件,此工具類是java.util中的方法,其中還有一些stringUtils的方法,用來判斷字符串是否為空,將字符串轉(zhuǎn)換成大寫等功能,就不寫在上面了。
package com.solr.util;
import java.text.MessageFormat;
import java.util.Locale;
import java.util.ResourceBundle;
import org.apache.log4j.Logger;
public class PropUtils {
private static final String URL_RESOURCE_FILE_PATH = "props/filter";
private static final Logger LOG = Logger.getLogger(PropUtils.class);
private static final ResourceBundle rb = ResourceBundle.getBundle(URL_RESOURCE_FILE_PATH, Locale.getDefault(),PropUtils.class.getClassLoader());
/**
* @param key 對應(yīng)properties內(nèi)的key
* @return properties對應(yīng)字符串
*/
public static String getValueByKey(String key){
return getValueByKey(key,null);
}
/**
* @param key 對應(yīng)properties內(nèi)的key
* @param param 參數(shù)下標(biāo)0開始依次排列
* @return properties內(nèi)填入對應(yīng)參數(shù)的字符串
*/
public static String getValueByKey(String key,Object [] param){
String value = "";
try {
value = rb.getString(StringUtils.toUpper(key));
} catch (Exception e) {
LOG.info(e,e);
}
if (StringUtils.isBlank(value)){
return key;
}
String strReturn = "";
if (param == null || param.length == 0){
strReturn = MessageFormat.format(value, param);
}else {
strReturn = value;
}
return strReturn.trim();
}
}
查看web.xml參數(shù)
在啟動服務(wù)器的時候,會對過濾器進(jìn)行初始化,我們可以在初始化的時候查看剛才配置的web.xml是否成功。
package com.solr.filter;
import java.io.IOException;
import java.util.Enumeration;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public class StringFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
// TODO Auto-generated method stub
System.out.println("init");
Enumeration<String> initParameterNames = filterConfig.getInitParameterNames();
while (initParameterNames.hasMoreElements()) {
String param = (String) initParameterNames.nextElement();
System.out.println(param + ":" + filterConfig.getInitParameter(param));
}
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
// TODO Auto-generated method stub
System.out.println("dofilter");
}
@Override
public void destroy() {
// TODO Auto-generated method stub
System.out.println("destroy");
}
}
啟動服務(wù)器進(jìn)行測試
啟動服務(wù)器的時候報錯了:
八月 17, 2018 2:48:27 下午 org.apache.catalina.core.ContainerBase startInternal
嚴(yán)重: A child container failed during start
java.util.concurrent.ExecutionException: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost]]
at java.util.concurrent.FutureTask.report(FutureTask.java:122)
at java.util.concurrent.FutureTask.get(FutureTask.java:192)
at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:1241)
at org.apache.catalina.core.StandardEngine.startInternal(StandardEngine.java:300)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:145)
at org.apache.catalina.core.StandardService.startInternal(StandardService.java:444)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:145)
at org.apache.catalina.core.StandardServer.startInternal(StandardServer.java:758)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:145)
at org.apache.catalina.startup.Catalina.start(Catalina.java:705)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:294)
at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:428)
Caused by: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost]]
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:162)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1702)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1692)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
Caused by: org.apache.catalina.LifecycleException: A child container failed during start
at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:1249)
at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:819)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:145)
... 6 more
錯誤的意思大概是加載組件遇到了問題。這個問題是在想通過編碼的方式來實現(xiàn)配置web.xml的時候出現(xiàn)的,即在之前是沒有遇到這個問題的,實現(xiàn)繼承AbstractAnnotationConfigDispatcherServletInitializer,并向web.xml中添加過濾器的時候遇到此問題的。
最終原因是通過編碼添加的過濾器名稱為testFilter,而web.xml中原先就有這個名稱的過濾器,兩個過濾器名稱沖突,造成服務(wù)器啟動失敗。
解決方式:刪除web.xml中原先的過濾器配置,通過編碼添加此過濾器。
web.xml
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0" metadata-complete="true">
<!--用maven創(chuàng)建的web-app需要修改servlet的版本為3.1 -->
<welcome-file-list>
<welcome-file>/index.jsp</welcome-file>
</welcome-file-list>
<!--配置DispatcherServlet -->
<servlet>
<servlet-name>mypage-dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 配置SpringMVC 需要配置的文件 spring-dao.xml,spring-service.xml,spring-web.xml
Mybites -> spring -> springMvc -->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/spring-*.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>mypage-dispatcher</servlet-name>
<!--默認(rèn)匹配所有請求 -->
<url-pattern>/</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.html</url-pattern>
</servlet-mapping>
</web-app>
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
輕松理解Java面試和開發(fā)中的IoC(控制反轉(zhuǎn))
在Java開發(fā)中,IoC意 味著將你設(shè)計好的類交給系統(tǒng)去控制,而不是在你的類內(nèi)部控制。這稱為控制反轉(zhuǎn)。下文給大家介紹Java面試和開發(fā)中的IoC(控制反轉(zhuǎn))知識,需要的朋友參考下吧2017-07-07
SpringMVC + jquery.uploadify實現(xiàn)上傳文件功能
文件上傳是很多項目都會使用到的功能,SpringMVC當(dāng)然也提供了這個功能。不過小編不建議在項目中通過form表單來提交文件上傳,這樣做的局限性很大。下面這篇文章主要介紹了利用SpringMVC + jquery.uploadify實現(xiàn)上傳文件功能的相關(guān)資料,需要的朋友可以參考下。2017-06-06
SpringBoot部署到外部Tomcat無法注冊到Nacos服務(wù)端的解決思路
這篇文章主要介紹了SpringBoot部署到外部Tomcat無法注冊到Nacos服務(wù)端,本文給大家分享完美解決思路,結(jié)合實例代碼給大家講解的非常詳細(xì),需要的朋友可以參考下2023-03-03
java?常規(guī)輪詢長輪詢Long?polling實現(xiàn)示例詳解
這篇文章主要為大家介紹了java?常規(guī)輪詢長輪詢Long?polling實現(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-12-12
springboot配置多數(shù)據(jù)源的一款框架(dynamic-datasource-spring-boot-starter
dynamic-datasource-spring-boot-starter 是一個基于 springboot 的快速集成多數(shù)據(jù)源的啟動器,今天通過本文給大家分享這款框架配置springboot多數(shù)據(jù)源的方法,一起看看吧2021-09-09
Spring @Primary作用和實現(xiàn)原理詳解
今天分享一下Spring中的@Primary注解,Primary的意思是主要的,我們在使用spring的時候,難免會定義多個類型相同的bean,這時候如果不采取一些方法,那么是無法正常使用bean的,所以本就給大家介紹Spring @Primary的作用和實現(xiàn)原理2023-07-07
Java通過JNI 調(diào)用動態(tài)鏈接庫DLL操作
這篇文章主要介紹了Java通過JNI 調(diào)用動態(tài)鏈接庫DLL操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-11-11

