好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

如何通过properties文件配置web.xml中的参数

前言

因为公司项目需要,目前有本地环境、测试环境、开发环境。每次在将项目打包成war包的时候,都需要修改多处的配置,而使用maven的profile打包项目的时候,可以根据执行打包命令时所带的参数来进行自动修改。

但是这种方式只对properties文件生效,即可以自动修改properties中的参数,但是公司的项目有一个web.xml中的配置参数也需要修改,这时候就要考虑如何通过properties文件动态修改web.xml中的参数了。

实现思路

web.xml中需要修改的部分

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

< 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创建的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 >

         <!--默认匹配所有请求 -->

         < 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行,这是过滤器的初始化参数。不同的环境这里的参数是不一样的,开始的思路是能否像application.xml中加载的properties文件一样,通过${username}这种方式获取properties中username对应的value。但是后来发现在web.xml中貌似是不好实现的。

在这样的需求下,web.xml就需要以编码的方式来实现配置。spring4.0以上的版本支持web.xml的编码配置。实现AbstractAnnotationConfigDispatcherServletInitializer接口,在servlet3.0中web.xml启动时会检测该接口实现类,从能够在实现类中去配置filter。

需要注意的是以上的实现,依赖servlet-api-3.0.jar和spring-webmvc-4.0以上版本jar包。

配置web.xml的类

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

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 {

          // 系统启动时注册filter

         FilterRegistration testFilter = servletContext.addFilter( "testFilter" , StringFilter. class );

         // 设置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两个方法没有自动添加进来,需要自己手动override。

其中onStartup在服务器启动的时候会根据配置修改web.xml,此处通过addFilter添加了一个叫做testFilter的过滤器,通过setInitParameter向过滤器中设置参数。而这里PropUtils是自己写的一个读取properties文件的工具类,这样就实现了将properties中的值动态添加到web.xml中了,最后打包修改properties的时候就可以修改web.xml了。

filter.properties文件

?

1

FILTER.NAME=HHH

PropUtils工具类

此工具类使用ResourceBundle读取properties文件,此工具类是java.util中的方法,其中还有一些stringUtils的方法,用来判断字符串是否为空,将字符串转换成大写等功能,就不写在上面了。

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

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 对应properties内的key

      * @return properties对应字符串

      */

     public static String getValueByKey(String key){

         return getValueByKey(key, null );

     }

     /**

      * @param key 对应properties内的key

      * @param param 参数下标0开始依次排列

      * @return properties内填入对应参数的字符串

      */

     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参数

在启动服务器的时候,会对过滤器进行初始化,我们可以在初始化的时候查看刚才配置的web.xml是否成功。

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

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" );

     }

}

启动服务器进行测试

启动服务器的时候报错了:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

八月 17 , 2018 2 : 48 : 27 下午 org.apache.catalina.core.ContainerBase startInternal

严重: 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

错误的意思大概是加载组件遇到了问题。这个问题是在想通过编码的方式来实现配置web.xml的时候出现的,即在之前是没有遇到这个问题的,实现继承AbstractAnnotationConfigDispatcherServletInitializer,并向web.xml中添加过滤器的时候遇到此问题的。

最终原因是通过编码添加的过滤器名称为testFilter,而web.xml中原先就有这个名称的过滤器,两个过滤器名称冲突,造成服务器启动失败。

解决方式:删除web.xml中原先的过滤器配置,通过编码添加此过滤器。

web.xml

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

< 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创建的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 >

         <!--默认匹配所有请求 -->

         < url-pattern >/</ url-pattern >

     </ servlet-mapping >

     < servlet-mapping >

         < servlet-name >default</ servlet-name >

         < url-pattern >*.html</ url-pattern >

     </ servlet-mapping >

</ web-app >

以上为个人经验,希望能给大家一个参考,也希望大家多多支持。

原文链接:https://blog.csdn.net/nb7474/article/details/81777655

查看更多关于如何通过properties文件配置web.xml中的参数的详细内容...

  阅读:17次