配色: 字号:
JavaWeb——模拟Servlet3
2016-08-22 | 阅:  转:  |  分享 
  
JavaWeb——模拟Servlet3.0使用注解的方式配置Servlet



一、Servlet的传统配置方式



在JavaWeb开发中,每次编写一个Servlet都需要在web.xml文件中进行配置,如下所示:



复制代码

1

2ActionServlet

3me.gacl.web.controller.ActionServlet

4


5

6

7ActionServlet

8/servlet/ActionServlet

9


复制代码

每开发一个Servlet,都要在web.xml中配置Servlet才能够使用,这实在是很头疼的事情,所以Servlet3.0之后提供了注解(annotation),使得不再需要在web.xml文件中进行Servlet的部署描述,简化开发流程。本文所讲的基于注解方式配置Servlet不是针对Servlet3.0的,而是基于Servlet2.5的,通过开发自定义注解和注解处理器来实现类似于Servlet3.0的注解方式配置Servlet。



二、基于注解的方式配置Servlet



JDK1.5版本之后,JAVA提供了一种叫做Annotation的新数据类型,中文译为注解或标注,它的出现为铺天盖地的XML配置文件提供了一个完美的解决方案,让JAVAEE开发更加方便快速,也更加干净了。不过Servlet2.5默认情况下是不支持注解方式的配置的,但是我们可以开发自定义注解,然后将注解标注到Servlet上,再针对我们自定义的注解写一个注解处理器,具体的做法如下:



2.1、开发用于配置Servlet的相关注解



1、开发WebServlet注解,用于标注处理请求的Servlet类



复制代码

1packageme.gacl.annotation;

2

3importjava.lang.annotation.ElementType;

4importjava.lang.annotation.Retention;

5importjava.lang.annotation.RetentionPolicy;

6importjava.lang.annotation.Target;

7

8/

9自定义WebServlet注解,模拟Servlet3.0的WebServlet注解

10@Target注解的属性值表明了@WebServlet注解只能用于类或接口定义声明的前面,

11@WebServlet注解有一个必填的属性value。

12调用方式为:@WebServlet(value="/xxxx"),

13因语法规定如果属性名为value且只填value属性值时,可以省略value属性名,即也可以写作:@WebServlet("/xxxx")

14/

15@Retention(RetentionPolicy.RUNTIME)

16@Target(ElementType.TYPE)

17public@interfaceWebServlet{

18//Servlet的访问URL

19Stringvalue();

20//Servlet的访问URL

21String[]urlPatterns()default{""};

22//Servlet的描述

23Stringdescription()default"";

24//Servlet的显示名称

25StringdisplayName()default"";

26//Servlet的名称

27Stringname()default"";

28//Servlet的init参数

29WebInitParam[]initParams()default{};

30}

复制代码

将Servlet在web.xml中的配置信息使用WebServlet注解来表示,使用注解后,只需要在相应Servlet类的前面使用类似@WebServlet("/servlet/LoginServlet")注解就可以达到和上述web.xml文件中配置信息一样的目的。注解@WebServlet中的属性值"/servlet/LoginServlet"表示了web.xml配置文件中元素的子元素里的值。通过这样的注解能简化在XML文件中配置Servlet信息,整个配置文件将会非常简洁干净,开发人员的工作也将大大减少。



2、开发WebInitParam注解,用于配置Servlet初始化时使用的参数



复制代码

1packageme.gacl.annotation;

2

3importjava.lang.annotation.ElementType;

4importjava.lang.annotation.Retention;

5importjava.lang.annotation.RetentionPolicy;

6importjava.lang.annotation.Target;

7

8/

9@ClassName:WebInitParam

10@Description:定义Servlet的初始化参数注解

11@author:孤傲苍狼

12@date:2014-10-1下午3:25:53

13

14/

15@Retention(RetentionPolicy.RUNTIME)

16@Target(ElementType.TYPE)

17public@interfaceWebInitParam{

18//参数名

19StringparamName()default"";

20//参数的值

21StringparamValue()default"";

22}

复制代码

2.2、编写处理注解的处理器



上面简要地介绍了注解的定义声明与使用方式,注解在后台需要一个处理器才能起作用,所以还得针对上面的注解编写处理器,在这里我们使用Filter作为注解的处理器,编写一个AnnotationHandleFilter,代码如下:



复制代码

1packageme.gacl.web.filter;

2

3importjava.io.IOException;

4importjava.lang.reflect.InvocationTargetException;

5importjava.lang.reflect.Method;

6importjava.lang.reflect.Modifier;

7importjava.util.HashMap;

8importjava.util.Map;

9importjava.util.Set;

10importjavax.servlet.Filter;

11importjavax.servlet.FilterChain;

12importjavax.servlet.FilterConfig;

13importjavax.servlet.ServletContext;

14importjavax.servlet.ServletException;

15importjavax.servlet.ServletRequest;

16importjavax.servlet.ServletResponse;

17importjavax.servlet.http.HttpServletRequest;

18importjavax.servlet.http.HttpServletResponse;

19importme.gacl.annotation.WebInitParam;

20importme.gacl.annotation.WebServlet;

21importme.gacl.util.ScanClassUtil;

22

23/

24@ClassName:AnnotationHandleFilter

25@Description:使用Filter作为注解的处理器

26@author:孤傲苍狼

27@date:2014-11-12下午10:15:19

28

29/

30publicclassAnnotationHandleFilterimplementsFilter{

31

32privateServletContextservletContext=null;

33

34/过滤器初始化时扫描指定的包下面使用了WebServlet注解的那些类

35@seejavax.servlet.Filter#init(javax.servlet.FilterConfig)

36/

37publicvoidinit(FilterConfigfilterConfig)throwsServletException{

38System.out.println("---AnnotationHandleFilter过滤器初始化开始---");

39servletContext=filterConfig.getServletContext();

40Map>classMap=newHashMap>();

41//获取web.xml中配置的要扫描的包

42StringbasePackage=filterConfig.getInitParameter("basePackage");

43//如果配置了多个包,例如:me.gacl.web.controller,me.gacl.web.UI

44if(basePackage.indexOf(",")>0){

45//按逗号进行分隔

46String[]packageNameArr=basePackage.split(",");

47for(StringpackageName:packageNameArr){

48addServletClassToServletContext(packageName,classMap);

49}

50}else{

51addServletClassToServletContext(basePackage,classMap);

52}

53System.out.println("----AnnotationHandleFilter过滤器初始化结束---");

54}

55

56/

57@Method:addServletClassToServletContext

58@Description:添加ServletClass到ServletContext中

59@Anthor:孤傲苍狼

60

61@parampackageName

62@paramclassMap

63/

64privatevoidaddServletClassToServletContext(StringpackageName,Map>classMap){

65Set>setClasses=ScanClassUtil.getClasses(packageName);

66for(Classclazz:setClasses){

67if(clazz.isAnnotationPresent(WebServlet.class)){

68//获取WebServlet这个Annotation的实例

69WebServletannotationInstance=clazz.getAnnotation(WebServlet.class);

70//获取Annotation的实例的value属性的值

71StringannotationAttrValue=annotationInstance.value();

72if(!annotationAttrValue.equals("")){

73classMap.put(annotationAttrValue,clazz);

74}

75//获取Annotation的实例的urlPatterns属性的值

76String[]urlPatterns=annotationInstance.urlPatterns();

77for(StringurlPattern:urlPatterns){

78classMap.put(urlPattern,clazz);

79

80servletContext.setAttribute("servletClassMap",classMap);

81System.out.println("annotationAttrValue:"+annotationAttrValue);

82String=www.wang027.com.targetClassNameannotationAttrValue.substring(annotationAttrValue.lastIndexOf("/")+1);

83System.out.println("targetClassName:"+targetClassName);

84System.out.println(clazz);

85}

86}

87}

88

89publicvoiddoFilter(ServletRequestrequest,ServletResponseresponse,

90FilterChainchain)throwsIOException,ServletException{

91System.out.println("---进入注解处理过滤器---");

92//将ServletRequest强制转换成HttpServletRequest

93HttpServletRequestreq=(HttpServletRequest)request;

94HttpServletResponseres=(HttpServletResponse)response;

95Map>classMap=(Map>)servletContext.getAttribute("servletClassMap");

96//获取contextPath

97StringcontextPath=req.getContextPath();

98//获取用户请求的URI资源

99Stringuri=req.getRequestURI();

100//如果没有指明要调用Servlet类中的哪个方法

101if(uri.indexOf("!")==-1){

102//获取用户使用的请求方式

103StringreqMethod=req.getMethod();

104//获取要请求的servlet路径

105StringrequestServletName=uri.substring(contextPath.length(),uri.lastIndexOf("."));

106//获取要使用的类

107Classclazz=classMap.get(requestServletName);

108//创建类的实例

109Objectobj=null;

110try{

111obj=clazz.newInstance();

112}catch(InstantiationExceptione1){

113e1.printStackTrace();

114}catch(IllegalAccessExceptione1){

115e1.printStackTrace();

116}

117MethodtargetMethod=null;

118if(reqMethod.equalsIgnoreCase("get")){

119try{

120targetMethod=clazz.getDeclaredMethod("doGet",HttpServletRequest.class,HttpServletResponse.class);

121}catch(SecurityExceptione){

122e.printStackTrace();

123}catch(NoSuchMethodExceptione){

124e.printStackTrace();

125}

126}else{

127try{

128targetMethod=clazz.getDeclaredMethod("doPost",HttpServletRequest.class,HttpServletResponse.class);

129}catch(SecurityExceptione){

130e.printStackTrace();

131}catch(NoSuchMethodExceptione){

132e.printStackTrace();

133}

134}

135

136try{

137//调用对象的方法进行处理

138targetMethod.invoke(obj,req,res);

139}catch(IllegalArgumentExceptione){

140e.printStackTrace();

141}catch(IllegalAccessExceptione){

142e.printStackTrace();

143}catch(InvocationTargetExceptione){

144e.printStackTrace();

145}

146}else{

147//获取要请求的servlet路径

148StringrequestServletName=uri.substring(contextPath.length(),uri.lastIndexOf("!"));

149//获取要调用的servlet的方法

150StringinvokeMethodName=uri.substring(uri.lastIndexOf("!")+1,uri.lastIndexOf("."));

151

152//获取要使用的类

153Classclazz=classMap.get(requestServletName);

154//创建类的实例

155Objectobj=null;

156try{

157obj=clazz.newInstance();

158}catch(InstantiationExceptione1){

159e1.printStackTrace();

160}catch(IllegalAccessExceptione1){

161e1.printStackTrace();

162}

163//获得clazz类定义的所有方法

164Method[]methods=clazz.getDeclaredMethods();

165//获取WebServlet这个Annotation的实例

166WebServletannotationInstance=clazz.getAnnotation(WebServlet.class);

167//获取注解上配置的初始化参数数组

168WebInitParam[]initParamArr=annotationInstance.initParams();

169MapinitParamMap=newHashMap();

170for(WebInitParaminitParam:initParamArr){

171initParamMap.put(initParam.paramName(),initParam.paramValue());

172}

173//遍历clazz类中的方法

174for(Methodmethod:methods){

175//该方法的返回类型

176ClassretType=method.getReturnType();

177//获得方法名

178StringmethodName=method.getName();

179//打印方法修饰符

180System.out.print(Modifier.toString(method.getModifiers()));

181System.out.print(""+retType.getName()+""+methodName+"(");

182//获得一个方法参数数组(getparameterTypes用于返回一个描述参数类型的Class对象数组)

183Class[]paramTypes=method.getParameterTypes();

184for(intj=0;j
185//如果有多个参数,中间则用逗号隔开,否则直接打印参数

186if(j>0){

187System.out.print(",");

188}

189System.out.print(paramTypes[j].getName());

190}

191System.out.println(");");

192if(method.getName().equalsIgnoreCase("init")){

193try{

194//调用Servlet的初始化方法

195method.invoke(obj,initParamMap);

196}catch(IllegalArgumentExceptione){

197e.printStackTrace();

198}catch(IllegalAccessExceptione){

199e.printStackTrace();

200}catch(InvocationTargetExceptione){

201e.printStackTrace();

202}

203}

204}

205//获取WebServlet这个Annotation的实例

206System.out.println("invokeMethodName:"+invokeMethodName);

207try{

208try{

209//利用反射获取方法实例,方法的签名必须符合:

210//publicvoid方法名(HttpServletRequestrequest,HttpServletResponseresponse)

211//例如:publicvoidloginHandle(HttpServletRequestrequest,HttpServletResponseresponse)

212MethodtargetMethod=clazz.getDeclaredMethod(invokeMethodName,HttpServletRequest.class,HttpServletResponse.class);

213//调用对象的方法进行处理

214targetMethod.invoke(obj,req,res);

215}catch(SecurityExceptione){

216e.printStackTrace();

217}catch(NoSuchMethodExceptione){

218e.printStackTrace();

219}catch(IllegalArgumentExceptione){

220e.printStackTrace();

221}catch(InvocationTargetExceptione){

222e.printStackTrace();

223}

224}catch(IllegalAccessExceptione){

225e.printStackTrace();

226}

227}

228}

229

230publicvoiddestroy(){

231

232}

233}

复制代码

AnnotationHandleFilter过滤器初始化时扫描指定的包下面使用了WebServlet注解的那些类,然后将类存储到一个Map集合中,再将Map集合存储到servletContext对象中。







在web.xml文件中配置AnnotationHandleFilter过滤器和需要扫描的包



复制代码

1

2注解处理过滤器

3AnnotationHandleFilter

4me.gacl.web.filter.AnnotationHandleFilter

5

6配置要扫描包及其子包,如果有多个包,以逗号分隔

7basePackage

8me.gacl.web.controller,me.gacl.web.UI

9

10


11


12

13

14AnnotationHandleFilter

15

16.do

17


复制代码

AnnotationHandleFilter过滤器初始化方法init(FilterConfigfilterConfig)使用到了一个用于扫描某个包下面的类的工具类ScanClassUtil,ScanClassUtil的代码如下:



复制代码

1packageme.gacl.util;

2

3importjava.io.File;

4importjava.io.FileFilter;

5importjava.io.IOException;

6importjava.net.JarURLConnection;

7importjava.net.URL;

8importjava.net.URLDecoder;

9importjava.util.Enumeration;

10importjava.util.LinkedHashSet;

11importjava.util.Set;

12importjava.util.jar.JarEntry;

13importjava.util.jar.JarFile;

14

15publicclassScanClassUtil{

16

17/

18从包package中获取所有的Class

19

20@parampack

21@return

22/

23publicstaticSet>getClasses(Stringpack){

24

25//第一个class类的集合

26Set>classes=newLinkedHashSet>();

27//是否循环迭代

28booleanrecursive=true;

29//获取包的名字并进行替换

30StringpackageName=pack;

31StringpackageDirName=packageName.replace(''.'',''/'');

32//定义一个枚举的集合并进行循环来处理这个目录下的things

33Enumerationdirs;

34try{

35dirs=Thread.currentThread().getContextClassLoader().getResources(

36packageDirName);

37//循环迭代下去

38while(dirs.hasMoreElements()){

39//获取下一个元素

40URLurl=dirs.nextElement();

41//得到协议的名称

42Stringprotocol=url.getProtocol();

43//如果是以文件的形式保存在服务器上

44if("file".equals(protocol)){

45System.err.println("file类型的扫描");

46//获取包的物理路径

47StringfilePath=URLDecoder.decode(url.getFile(),"UTF-8");

48//以文件的方式扫描整个包下的文件并添加到集合中

49findAndAddClassesInPackageByFile(packageName,filePath,

50recursive,classes);

51}elseif("jar".equals(protocol)){

52//如果是jar包文件

53//定义一个JarFile

54System.err.println("jar类型的扫描");

55JarFilejar;

56try{

57//获取jar

58jar=((JarURLConnection)url.openConnection())

59.getJarFile();

60//从此jar包得到一个枚举类

61Enumerationentries=jar.entries();

62//同样的进行循环迭代

63while(entries.hasMoreElements()){

64//获取jar里的一个实体可以是目录和一些jar包里的其他文件如META-INF等文件

65JarEntryentry=entries.nextElement();

66Stringname=entry.getName();

67//如果是以/开头的

68if(name.charAt(0)==''/''){

69//获取后面的字符串

70name=name.substring(1);

71}

72//如果前半部分和定义的包名相同

73if(name.startsWith(packageDirName)){

74intidx=name.lastIndexOf(''/'');

75//如果以"/"结尾是一个包

76if(idx!=-1){

77//获取包名把"/"替换成"."

78packageName=name.substring(0,idx)

79.replace(''/'',''.'');

80}

81//如果可以迭代下去并且是一个包

82if((idx!=-1)||recursive){

83//如果是一个.class文件而且不是目录

84if(name.endsWith(".class")

85&&!entry.isDirectory()){

86//去掉后面的".class"获取真正的类名

87StringclassName=name.substring(

88packageName.length()+1,name

89.length()-6);

90try{

91//添加到classes

92classes.add(Class

93.forName(packageName+''.''

94+className));

95}catch(ClassNotFoundExceptione){

96//log

97//.error("添加用户自定义视图类错误找不到此类的.class文件");

98e.printStackTrace();

99}

100}

101}

102}

103}

104}catch(IOExceptione){

105//log.error("在扫描用户定义视图时从jar包获取文件出错");

106e.printStackTrace();

107}

108}

109}

110}catch(IOExceptione){

111e.printStackTrace();

112}

113

114returnclasses;

115}

116

117/

118以文件的形式来获取包下的所有Class

119

120@parampackageName

121@parampackagePath

122@paramrecursive

123@paramclasses

124/

125publicstaticvoidfindAndAddClassesInPackageByFile(StringpackageName,

126StringpackagePath,finalbooleanrecursive,Set>classes){

127//获取此包的目录建立一个File

128Filedir=newFile(packagePath);

129//如果不存在或者也不是目录就直接返回

130if(!dir.exists()||!dir.isDirectory()){

131//log.warn("用户定义包名"+packageName+"下没有任何文件");

132return;

133}

134//如果存在就获取包下的所有文件包括目录

135File[]dirfiles=dir.listFiles(newFileFilter(){

136//自定义过滤规则如果可以循环(包含子目录)或则是以.class结尾的文件(编译好的java类文件)

137publicbooleanaccept(Filefile){

138return(recursive&&file.isDirectory())

139||(file.getName().endsWith(".class"));

140}

141});

142//循环所有文件

143for(Filefile:dirfiles){

144//如果是目录则继续扫描

145if(file.isDirectory()){

146findAndAddClassesInPackageByFile(packageName+"."

147+file.getName(),file.getAbsolutePath(),recursive,

148classes);

149}else{

150//如果是java类文件去掉后面的.class只留下类名

151StringclassName=file.getName().substring(0,

152file.getName().length()-6);

153try{

154//添加到集合中去

155//classes.add(Class.forName(packageName+''.''+className));

156//经过回复同学的提醒,这里用forName有一些不好,会触发static方法,没有使用classLoader的load干净

157classes.add(Thread.currentThread().getContextClassLoader().loadClass(packageName+''.''+className));

158}catch(ClassNotFoundExceptione){

159//log.error("添加用户自定义视图类错误找不到此类的.class文件");

160e.printStackTrace();

161}

162}

163}

164}

165}

复制代码

经过以上两步,我们的自定义注解和针对注解的处理器都开发好了。



2.3、WebServlet注解简单测试



编写一个用于跳转到Login.jsp页面的LoginUIServlet,LoginUIServlet就是一个普通的java类,不是一个真正的Servlet,然后使用WebServlet注解标注LoginUIServlet类,代码如下:



复制代码

1packageme.gacl.web.UI;

2

3importjava.io.IOException;

4importjavax.servlet.ServletException;

5importjavax.servlet.http.HttpServletRequest;

6importjavax.servlet.http.HttpServletResponse;

7importme.gacl.annotation.WebServlet;

8

9@WebServlet("/servlet/LoginUI")

10publicclassLoginUIServlet{

11

12publicvoiddoGet(HttpServletRequestrequest,HttpServletResponseresponse)

13throwsServletException,IOException{

14request.getRequestDispatcher("/Login.jsp").forward(request,response);

15}

16

17publicvoiddoPost(HttpServletRequestrequest,HttpServletResponseresponse)

18throwsServletException,IOException{

19doGet(request,response);

20}

21}

复制代码

在浏览器中输入访问地址:http://gacl-pc:8080/AnnotationConfigServlet/servlet/Login.do,根据web.xml文件的配置,所有后缀名为.do请求,都会经过AnnotationHandleFilter过滤器的doFilter方法,在doFilter方法的实现代码中,从HttpServletRequest请求对象中得到请求的方式类型(GET/POST)和请求的URI。如有请求http://gacl-pc:8080/AnnotationConfigServlet/servlet/LoginUI.do,此时请求方法类型为GET,URI值为/AnnotationConfigServlet/servlet/LoginUI.do。从ServletConext对象中获取到在过滤器中保存的Map结构,根据URI获得一个Key=”/servlet/LoginUI”,从Map结构中根据此Key得到Value,此时Value就是要请求调用的那个Servlet类,根据Servlet类创建对象实例,再根据前面得到的请求方法类型,能决定调用此Servlet对象实例的doGet或doPost方法。最终客户端发生的后缀为.do请求,经由AnnotationHandleFilter对请求对象(HttpServletRequest)的分析,从而调用相应某Servlet的doGet或doPost方法,完成了一次客户端请求到服务器响应的过程。



使用注解后程序流程如下所示:







运行结果如下:







从运行结果中可以看到,我们的注解处理器成功调用了目标Servlet处理用户的请求,通过@WebServlet注解,Servlet不用再在web.xml文件中进行繁冗的注册,这就是使用@WebServlet注解的方便之处。



2.3、WebServlet注解复杂测试



编写Login.jsp页面,代码如下:



复制代码

1<%@pagelanguage="java"pageEncoding="UTF-8"%>

2

3

4

5登录页面

6

7

8

9


10用户登录

11

12用户名:

13


14密码:

15


16

17

18


19


20${msg}

21

22

复制代码

form表单中的action属性的URL="${pageContext.request.contextPath}/servlet/LoginServlet!loginHandle.do",/servlet/LoginServlet表示要访问的是LoginServlet,!后面的loginHandle表示要调用LoginServlet中的loginHandle方法处理此次的请求,也就是说,我们在访问Servlet时,可以在URL中指明要访问Servlet的哪个方法,AnnotationHandleFilter过滤器的doFilter方法在拦截到用户的请求之后,首先获取用户要访问的URI,根据URI判断用户要访问的Servlet,然后再判断URI中是否包含了"!",如果有,那么就说明用户显示指明了要访问Servlet的哪个方法,遍历Servlet类中定义的所有方法,如果找到了URI中的那个方法,那么就调用对应的方法处理用户请求!



LoginServlet的代码如下:



复制代码

1packageme.gacl.web.controller;

2

3importjava.io.IOException;

4importjava.util.Map;

5importjavax.servlet.ServletException;

6importjavax.servlet.http.HttpServletRequest;

7importjavax.servlet.http.HttpServletResponse;

8importme.gacl.annotation.WebInitParam;

9importme.gacl.annotation.WebServlet;

10

11/

12

13@ClassName:LoginServlet

14@Description:处理用户登录的Servlet,

15LoginServlet现在就是一个普通的java类,不是一个真正的Servlet

16@author:孤傲苍狼

17@date:2014-10-8上午12:07:58

18

19/

20//将开发好的WebServlet注解标注到LoginServlet类上

21@WebServlet(

22//Servlet的访问URL

23value="/servlet/LoginServlet",

24//Servlet的访问URL,可以使用数组的方式配置多个访问路径

25urlPatterns={"/gacl/LoginServlet","/xdp/LoginServlet"},

26//Servlet的初始化参数

27initParams={

28@WebInitParam(paramName="gacl",paramValue="孤傲苍狼"),

29@WebInitParam(paramName="bhsh",paramValue="白虎神皇")

30},

31name="LoginServlet",

32description="处理用户登录的Servlet"

33)

34publicclassLoginServlet{

35

36publicvoidloginHandle(HttpServletRequestrequest,HttpServletResponseresponse)

37throwsServletException,IOException{

38Stringusername=request.getParameter("usename");

39Stringpwd=request.getParameter("pwd");

40if(username.equals("gacl")&&pwd.equals("xdp")){

41request.getSession().setAttribute("usename",username);

42request.setAttribute("msg","欢迎您!"+username);

43request.getRequestDispatcher("/index.jsp").forward(request,response);

44}else{

45request.setAttribute("msg","登录失败,请检查用户名和密码是否正确!");

46request.getRequestDispatcher("/Login.jsp").forward(request,response);

47}

48}

49

50

51/

52@Method:init

53@Description:Servlet初始化

54@Anthor:孤傲苍狼

55

56@paramconfig

57/

58publicvoidinit(MapinitParamMap){

59System.out.println("--LoginServlet初始化--");

60System.out.println(initParamMap.get("gacl"));

61System.out.println(initParamMap.get("bhsh"));

62}

63}

献花(0)
+1
(本文系thedust79首藏)