JavaEE高级-SpringMVC学习笔记

2019-08-16 10:38:43来源:博客园 阅读 ()

新老客户大回馈,云服务器低至5折

JavaEE高级-SpringMVC学习笔记

*SpringMVC概述

  - Spring为展示层提供的基于MVC设计理念的优秀Web框架,是目前最主流的MVC框架之一

  - Spring3.0后全面超越Struts2,成为最优秀的MVC框架

  - SpringMVC通过一套MVC注解,让POJO成为处理请求的控制器,而无需实现任何接口

  - 支持REST风格的URL请求

  - 采用了松散耦合可拔插组件结构,比其他MVC框架更具扩展性和灵活性

 

*HelloWorld

  - 步骤:

    - 加入jar包

      > commons-logging-1.1.3.jar

      > spring-aop-4.0.0.RELEASE.jar

      > spring-beans-4.0.0.RELEASE.jar

      > spring-context-4.0.0.RELEASE.jar

      > spring-core-4.0.0.RELEASE.jar

      > spring-expression-4.0.0.RELEASE.jar

      > spring-web-4.0.0.RELEASE.jar

      > spring-webmvc-4.0.0.RELEASE.jar

    - 在web.xml中配置DispatcherServlet

    - 加入SpringMVC的配置文件

    - 编写处理请求的处理器,并标识为处理器

    - 编写视图

 

*使用@RequestMapping映射请求

  - Spring MVC 使用@RequestMapping注解为控制器指定可以处理哪些URL请求

  - 在控制器的类定义及方法定义处都可标注

    @RequestMapping

    > 类定义处:提供初步的请求映射信息。相对于WEB应用的根目录

    > 方法处:提供进一步的细分映射信息。相对于类定义处的URL。若类定义处为标注@RequestMapping,则方法处标记的URL相对于WEB应用的根目录

  - DispatcherServlet截获请求后,就通过控制器上@RequestMapping提供的映射信息确定请求所对应的处理方法

  - @RequestMapping除了可以使用请求URL映射请求外,还可以使用请求方法、请求参数及请求头映射请求

  - @RequestMapping的value、method、params及heads分别表示URL、请求方法、请求参数及请求头的映射条件,它们之间是与的关系,

  - params和headers支持简单的表达式:

    > param1:表示请求必须包含名为param1的请求参数

    > !param1:表示请求不能包含名为param1的请求参数

    > param1!=value1:表示请求包含名为param1的参数,但其值不能为value1

    > {"param1=value1","param2"}:请求必须包含名为param1和param2的两个请求参数,且param1参数的值必须为value1

  - Ant风格资源地址支持3种匹配符:

    > ? :匹配文件名中的一个字符

    > * :匹配文件名中的任意字符

    > ** :**匹配多层路径

  - @RequestMapping还支持Ant风格的URL:

    - /user/*/createUser:匹配/user/aaa/createUser、/user/bbb/createUser、

    - /user/**/createUser:匹配/user/createUser、/user/aaa/bbb/createUser、

    - /user/createUser??:匹配/user/createUseraa、/user/createUserbb等URL

 

*@PathVariable映射URL绑定的占位符

  - 带占位符的URL是spring3.0新增的功能,该功能在SpringMVC向REST目标挺近发展过程中具有里程碑意义

  - 通过@PathVariable可以将URL中占位符参数绑定到控制器处理方法的入参中:URL中的{XXX}占位符可以通过@PathVariable("XXX")绑定到操作方法的入参中

    

 

*REST

  - REST:即Representational State Transfet。(资源)表现层状态转换。目前最流行的一种互联网软件架构。其结构清晰、符合标准、易于理解、扩展方便。

  - 资源(Resources):网络上的一个实体,或者说网络上的一个具体信息。可以用一个URI(统一资源定位符)指向它,每种资源对应一个特定的URI。要获取这个资源,访问它的URI即可。故URI为每个资源唯一的识别符

  - 表现层(Representation):把资源具体呈现出来。

  - 状态转化(State Transfer):每发出一个请求,就代表了客户端和服务器的一次交互过程。HTTP协议,是一个无状态协议,即所有的状态都保存在服务器端。因此,若客户端想要操作服务器,

                必须通过某种手段,让服务器发生“状态转化”(State Transfer)。而这中转化是建立在表现层之上的,所以就是“表现层状态转化”。具体而言,就是HTTP协议里面,

                四个表示操作方式的动词:GET、POST、PUT、DELETE,它们分别对应四种基本操作:GET用来获取资源,POST用来新建资源,PUT用来更新资源,DELETE用来删除资源

  - HiddenHttpMethodFilter:浏览器form表单只支持GET和POST请求,而DELETE、PUT等method并不支持,Spring3.0添加了一个过滤器,可将这些请求转化为标准的http方法,使得可以支持这四种请求。

 

*请求处理方法签名

  - Spring MVC通过分析处理方法的签名,将HTTP请求信息绑定到处理方法的相应入参中。

  - Spring MVC对控制器处理方法签名的限制是很宽松的,几乎可以按喜欢的任何方式对方法进行签名

  - 必要时可以对方法及方法入参标注相应的注解(@PathVariable、@RequestParam、@RequestHeader等)、SpringMVC框架会将HTTP请求的信息绑定到相应的方法入参中,并根据方法的返回值类型做出相应的后续处理

*使用@RequestParam绑定请求参数值

  - 在处理方法入参处使用@RequestParam可以把请求参数传递给请求方法:value---参数名,required---是否必须带参,默认为true,表示请求参数中必须包含对应的参数,若不存在,将抛异常。

     

*使用@RequestHeader绑定请求头的属性值

  - 请求头包含了若干个属性,服务器可据此获知客户端的信息,通过@RequestHeader即可将请求头中的属性值绑定到处理方法的入参中

    

*使用@CookieValue绑定请求中的Cookie值

  - @CookieValue可让处理方法入参绑定某个Cookie值

    

*使用POJO对象绑定请求参数值

  - Spring MVC会按请求参数名和POJO属性名进行自动匹配,自动为该对象填充属性值。支持级联属性。

    

 

*MVC的Handler方法可以接受哪些ServletAPI类型的参数?

  - HttpServletRequest

  - HttpServletResponse

  - HttpSession

  - java.security.Principal

  - Locale

  - InputStream

  - OutputStream

  - Reader

  - Writer

 

*处理模型数据

  - Spring MVC提供了以下几种途径输出模型数据:

    > ModelAndView:处理方法返回值类型为ModelAndView时,方法体即可通过该对象添加模型数据

      >> 控制器处理方法的返回值如果为ModelAndView,则其既包含视图信息,也包含模型数据信息

      >> 添加模型数据:1.ModelAndView addObject(String attributeName,Object attributeValue)

               2.ModelAndView addAllObject(Map<String,?>modelMap)

      >> 设置视图:1.void setView(View view)

             2.void setViewName(String viewName)

    > Map及Model:入参为org.springframework.ui.Model、org.springframework.ui.ModelMap或java.util.Map时,Map中的数据会自动添加到模型中

      >> Spring MVC在内部使用了一个org.springframework.ui.Model接口存储模型数据

      >> Spring MVC在调用方法前会创建一个隐含的模型对象作为模型数据的存储容器

      >> 如果方法的入参为Map或Model类型,Spring MVC会将隐含模型的引用传递给这些入参。在方法体内,开发者可以通过这个入参对象访问到模型中的所有数据,也可以向模型中添加新的属性数据

    > @SessionAttributes:将模型中的某个属性暂存到HttpSession中,以便多个请求之间可以共享这个属性

      >> 若希望在多个请求之间共用某个模型属性数据,则可以再控制器类上标注一个@SessionAttributes,SpringMVC将在模型中对应的属性暂存到HttpSession中

      >> @SessionAttributes除了可以通过属性名指定需要放到会话中的属性外,还可以通过模型属性的对象类型指定哪些模型属性需要放到会话中

        -- @SessionAttributes(types=User.class)会将隐含模型中所有类型为User.class的属性添加到会话中

        -- @SessionAttributes(value={“user1”,“user2”})

        -- @SessionAttributes(types={User.class,Dept.class})

        -- @SessionAttributes(value={“user1”,“user2”},types={Dept.class})

      >> 该注解只能放在类的上边,不能放在方法上进行修饰

    > @ModelAttribute:方法入参标注该注解后,入参的对象就会放到数据模型中

 

*视图和视图解析器

  - 请求处理方法执行完成后,最终返回一个ModelAndView对象。对于那些返回String,View或ModelMap等类型的处理方法,SpringMVC也会在内部将它们装配成一个ModelAndView对象,它包含了逻辑名和模型对象的视图

  - SpringMVC借助视图解析器(ViewResolver)得到最终的视图对象(View),最终的视图可以是JSP,也可以是Excel、JFreeChart等各种表现形式的视图

  - 对于最终究竟采取何种视图对象对模型数据进行渲染,处理器并不关心,处理器工作重点聚集在生产模型数据的工作上,从而实现MVC的充分解耦

  - 视图的作用是渲染模型数据,将模型里的数据以某种形式呈现给客户

  - 为了实现视图模型和具体实现技术的解耦,Spring在org.springframework.web.servlet包中定义了一个高度抽象的View接口:

        

  - 视图对象由视图解析器负责实例化,由于视图是无状态的,故其没有线程安全问题

  - 常用的视图实现类:

        

  - SpringMVC为逻辑视图名的解析提供了不同的策略,可以在Spring WEB 上下文中配置一种或多种解析策略,并指定它们之间的先后顺序。每一种映射策略对应一个具体的视图解析器实现类

  - 视图解析器的作用比较单一:将逻辑视图解析为一个具体的视图对象。

  - 所有的视图解析器都必须实现ViewResolver接口:

        

  - 常用的视图解析器实现类:

          

  - 程序员可以选择一种视图解析器或混用多种视图解析器

  - 每个视图解析器都实现了Ordered接口并开放出了一个order属性,可以通过order属性指定解析器的优先顺序,order越小优先级越高

  - SpringMVC会按视图解析器顺序的优先级对逻辑视图名进行解析,直到解析成功并返回视图对象,否则将抛出SerlvetException异常

  - InternalResourceViewResolver:JSP是最常见的视图技术,可以使用InternalResourceViewResolver作为视图解析器:

        

    >> 若项目中使用了JSTL,则SpringMVC会自动把视图由InternalResourceView转为JstlView

    >> 若使用JSTL的fmt标签则需要在SpringMVC的配置文件中配置国际化资源文件

    >> 若希望直接相应通过SpringMVC渲染的页面,可以使用mvc:view-controller标签实现

 

*关于重定向

  - 一般情况下,控制器方法返回字符串类型的值会被当成逻辑视图名处理

  - 如果返回的字符串中带forword:或redirect:前缀时,SpringMVC会对它们进行特殊处理----> 将forword:和redirect:当成指示符,其后的字符串作为URL来处理

 

*form标签

  - 一般情况下,通过GET请求获取表单页面,而通过POST请求提交表单页面,因此获取表单页面和提交表单页面的URL是相同的。只要瞒足该最佳条件的契约,<form:form>标签就无需通过action属性指定表单提交的URL

  - 可以通过modelAttribute属性指定绑定的模型属性,若没有指定该属性,则默认从request域对象中读取command的表单bean,若该属性值也不存在,则会报错

  - 通过SpringMVC的表单标签可以实现将模型数据中的属性和HTML表单元素相绑定,以实现表单数据更便捷和表单值的回显

  - SpringMVC提供了多个表单组件标签,如<form:input/>、<form:select/>等,用以绑定表单字段的属性值,它们的共有属性如下:

    > path:表单字段,对应html元素的name属性,支持级联属性

    > htmlEscape:是否对表单的HTML特殊字符进行转换,默认值为true

    > cssClass:表单组件对应的css样式类名

    > cssErrorClass:表单组件的数据存在错误时,采取的css样式

  - form:input、form:password、form:hidden、form:textarea:对应HTML表单的text、password、hidden、textarea标签

  - form:radiobutton:单选框组件标签,当表单bean对应的属性值和value值相等时,单选框被选中

  - form:radiobuttons:单选框组标签,用于构造多个单选框

    > items:可以是一个List、String[]或Map

    > itemValue:指定radio的value值,可以是集合中bean的一个属性值

    > itemLabel:指定radio的label值

    > delimiter:多个单选框可以通过delimiter指定分隔符

  - form:checkbox:复选框组件。用于构造单个复选框

  - form:checkboxs:用于构造多个复选框。使用方式同form:radiobuttons标签

  - form:select:用于构造下拉框组件。使用方式同form:radiobuttons标签

  - form:option:下拉框选项组件标签。使用方式同form:radiobuttons标签

  - form:errors:显示表单组件或数据效验所对应的错误

    > <form:errors path= “*” />:显示表单所有的错误

    > <form:errors path= “user*” />:显示所有以user为前缀的属性对应的错误

    > <form:errors path= "username" />:显示特定表单对象属性的错误

 

*处理静态资源

  - 优雅的REST风格的资源URL不希望带.html或.do等后缀

  - 若将DispatcherServlet请求映射配置为/,则SpringMVC将捕获WEB容器的所有请求,包括静态资源的请求,SpringMVC会将它们当成一个普通请求处理,因找不到对应处理器将导致错误

  - 可以在SpringMVC的配置文件中配置<mvc:default-servlet-handler/>的方式解决静态资源的问题

    > <mvc:default-servlet-handler/>将在SpringMVC上下文中定义一个DefaultServletHttpRequestHandler,它会对进入DispatcherServlet的请求进行排查,若发现是没有经过映射的请求,就将该请求交由

       WEB应用服务器默认的Servlet处理,如果不是静态资源的请求,才由DispatcherServlet继续处理

    > 一般WEB应用服务器默认的Servlet的名称都是default。若所使用的WEB服务器的默认Servlet名称不是default,则需要通过default-servlet-name属性指定

 

*数据绑定流程

  - Spring MVC主框架将ServletRequest对象及目标方法的入参实例传递给WebDataBinderFactory实例,以创建DataBinder实例对象

  - DataBinder调用装配在SpringMVC上下文中的ConversionService组件进行数据类型转换、数据格式化工作。将Servlet中的请求信息填充到入参对象中

  - 调用Validator组件对已经绑定了请求消息的入参对象进行数据合法性效验,并最终生成数据绑定结果BindingData对象

  - Spring MVC抽取BindingResult中的入参对象和效验错误对象,将它们赋给处理方法的响应入参

 

*自定义类型转换器

  - ConversionService是Spring类型转换体系的核心接口。

  - 可以利用ConversionServiceFactoryBean在Spring的IOC容器中定义一个ConversionService。Spring将自动识别出IOC容器中的ConversionService,并在Bean属性配置及SpringMVC处理方法入参绑定等场合使用它进行数据转换

  - 可通过ConversionServiceFactotyBean的converters属性注册自定义的类型转换器

    

  - Spring定义了3种类型的转换器接口,实现任意一个转换器接口都可以作为自定义转换器注册到ConversionServiceFactotyBean中:

    > Converter<S,T>:将S类型对象转为T类型对象

    > ConverterFactory:将相同系列多个“同质”Converter封装在一起。若希望将一种类型的对象转换为另一种类型及其子类的对象可以使用该转换器工厂类

    > GenericConverter:会根据源类对象及目标类对象所在的宿主类中的上下文信息进行类型转换

 

*mvc:annotation-driven

  - <mvc:annotation-driven />会自动注册RequestMappingHandlerMapping、RequestMappingHandlerAdapter与ExceptionHandlerExceptionResolver三个bean

  - 还将提供以下支持:

    > 支持使用ConversionService实例对表单参数进行类型转换

    > 支持使用@NumberFormatannotation、@DateTimeFormat注解完成数据类型的格式化

    > 支持使用@Valid注解对JavaBean实例进行JSR303验证

    > 支持使用@RequestBody和@ResponseBody注解

 

*@InitBinder

  - 由@InitBinder标识的方法,可以对WebDataBinder对象进行初始化。WebDataBinder是DataBinder的子类,用于完成由表单字段到JavaBean属性的绑定

  - @InitBinder方法不能有返回值,它必须声明为void。

  - @InitBinder方法的参数通常是WebDataBinder

 

*数据格式化

  - 对属性对象的输入/输出进行格式化,从其本质上讲依然属于“类型转换”的范畴

  - Spring在格式化模块中定义了一个实现ConversionService接口的FormattingConversionService实现类,该实现类扩展了GenericConversionService,因此它既有类型转换的功能,又具有格式化的功能

  - FormattingConversionService拥有一个FormattingConversionServiceFactoryBean工厂类,后者用于在Spring上下文中构造前者

  - FormattingConversionServiceFactroyBean(<mvc:annotation-driven/>默认创建的ConversionService实例)内部已经注册:

    > NumberFormatAnnotationFormatterFactroy:支持对数字类型的属性使用@NumberFormat注解

    > JodaDateTimeFormatAnnotationFormatterFactroy:支持对日期类型的属性使用@DateTimeFormat注解

  - 装配了FormattingConversionServiceFactroyBean后,就可以在SpringMVC入参绑定及模型数据输出时使用注解驱动

 

*日期格式化

  - @DateTimeFormat注解可对java.util.Date、java.util.Calendar、java.long.Long时间类型进行标注:

    - pattern属性:类型为字符串。指定解析/格式化字段数据的模式,如:“yyyy-MM-dd hh:mm:ss”

    - iso属性:类型为DateTimeFormat.ISO。指定解析/格式化字段数据的ISO模式,包括四种:ISO.NONE(不使用)--默认、ISO.DATE(yyyy-MM-dd)、ISO.TIME(hh:mm:ss.SSSZ)、ISO.DETE_TIME(yyyy-MM-dd hh:mm:ss.SSSZ)

  - style属性:字符串类型。通过样式指定日期时间的格式,由两位字符组成,第一位表示日期的格式,第二位表示时间的格式;S:短日期/时间格式、M:中日期/时间格式、L:长日期/时间格式、F:完整日期/时间格式、-:忽略日期或时间格式

 

*数值格式化

  - @NumberFormat可对类似数字类型的属性进行标注,它拥有两个互斥的属性:

    > style:类型为NumberFormat.Style。用于指定样式类型,包括三种:Style.NUMBER(正常数字类型)、Style.CURRENCY(货币类型)、Style.PERCENT(百分数类型)

    > pattern:类型为String,自定义样式,如pattern="#.###";

 

*JSR 303

  - JSR 303是Java为Bean数据合法性效验提供的标准框架,它已经包含在JavaEE 6.0中

  - JSR 303通过在Bean属性上标注类似于@NotNull、@Max等标准的注解指定效验规则,并通过标准的验证接口对Bean进行验证:

    > 注解               功能说明

    > @Null                被注释的元素必须为null

    > @NotNull             被注释的元素必须不为null

    > @AssertTrue            被注释的元素必须为true

    > @AssertFalse           被注释的元素必须为false

    > @Min(value)           被注释的元素必须是一个数字,其值必须大于等于指定的最小值

    > @Max(value)          被注释的元素必须是一个数字,其值必须小于等于指定的最大值

    > @DecimalMin(value)      被注释的元素必须是一个数字,其值必须大于等于指定的最小值

    > @DecimalMax(value)        被注释的元素必须是一个数字,其值必须小于等于指定的最大值

    > @Size(max,min)           被注释的元素的大小必须在指定的范围内

    > @Digits(integer,fraction)      被注释的元素必须是一个数字,其值必须在可接受的范围内

    > @Past                被注释的元素必须是一个过去的日期

    > @Future               被注释的元素必须是一个将来的日期

    > @Pattern(value)        被注释的元素必须符合指定的正则表达式

  - Hibernate Validator扩展注解

    > Hibernate Validator是JSR 303的一个参考实现,除支持所有标准的效验注解外,它还支持以下的扩展注解:

      >> 注解         功能说明

      >> @Email      被注释的元素必须是电子邮件

      >> @Length      被注释的字符串的大小必须在指定的范围内

      >> @NotEmpty    被注释的字符串必须非空

      >> @Range      被注释的元素必须在合适的范围内

 

*Spring MVC数据效验

  - Spring4.0拥有自己独立的数据效验框架,同时支持JSR 303标准的效验框架

  - Spring在进行数据绑定时,可同时调用效验框架完成数据效验工作。在SpringMVC中,可直接通过注解驱动的方式进行数据效验

  - Spring的LocalValidatorFactroyBean既实现了Spring的Validator接口,也实现了JSR303的Valdator接口。只要在Spring容器中定义一个LocalValdatorFactoryBean,即可将其注入到需要数据效验的Bean中

  - Spring本身并没有提供JSR 303的实现,故必须将JSR303的实现者的jar包放到类路径下。

  - <mvc:annotation-driven /> 会默认装配好一个LocalValidatorFactoryBean,通过在处理方法的入参上标注@valid注解即可让Spring MVC在完成数据绑定后执行数据效验工作

  - 在已经标注了JSR303注解的表单/命令对象前标注一个@Valid,Spring MVC框架在将请求参数绑定到该入参对象后,就会调用效验框架根据注解声明的效验规则实施效验

  - Spring MVC是通过对处理方法签名的规约来保存到随后的入参中,这个保存效验结果的入参必须是BindingResult或Errors类型,这两个类都位于org.springframework.validation包中

  - 提示消息的国际化:

    > 每个属性在数据绑定和数据效验发生错误时,都会生成一个对应的FieldError对象

    > 当一个属性效验失败后,效验框架会为该属性生成4个消息代码,这些代码以效验注解类名为前缀,结合modleAttribute、属性名及属性类型名生成多个对应的消息代码:

     例如:User类中的password属性标准了一个@Pattern注解,当该属性值不满足@Pattern所定义的规则时,就会产生以下4个错误代码:

        - Pattern.user.password

        - Pattern.password

        - Pattern.java.lang.String

        - Pattern

    > 当使用SpringMVC标签显示错误消息时,SpringMVC会查看WEB上下文是否装配了对应的国际化消息,若没有,则显示默认的错误消息,否则使用国际化消息

    > 若数据类型转换或数据格式转换时发生错误,或该有的参数不存在,或调用处理方法时发生错误,都会在隐含模型中创建错误消息。其错误代码前缀说明如下:

      >> required:必要的参数不存在。如@RequiredParam(“param1”)标注了一个入参,但是该参数不存在

      >> typeMismatch:在数据绑定时,发生数据类型不匹配的问题

      >> methodInvocation:SpringMVC在调用处理方法时发生了错误

 

*处理JSON

  - 1.加入jar包:jackson-annotations-2.2.2.jar、jackson-core-2.2.2.jar、jackson-databind-2.2.2.jar

  - 2.编写目标方法,使其返回JSON对应的对象或集合

  - 3.在方法上添加@ResponseBody注解

  - HttpMessageConverter<T>

    > HttpMessageConverter<T>是Spring3.0新添加的一个接口,负责将请求信息转换为一个对象(类型为T),将对象(类型为T)输出为响应信息

    > DispatcherServlet默认装配RequestMappingHandlerAdapter,而RequestMappingHandlerAdapter默认装配HttpMessageConverter

    > HttpMessageConverter<T>接口定义的方法:

      >> Boolean canRead(Class<?> clazz,MediaType,mediaType):指定转换器可以读取的对象类型,即转换器是否可将请求信息转换为clazz类型的对象,同时指定支持MIME类型(text/html,application/json等)

      >> Boolean canWrite(Class<?> clazz,MediaType mediaType):指定转换器是否可将clazz类型的对象写到响应流中,响应流支持的媒体类型在MediaType中定义

      >> List<MediaType> getSupportMediaType():该转换器支持的媒体类型

      >> T read(Class<? extends T> clazz,HttpInputMessage inputMessage):将请求信息流转换为T类型的对象

      >> void write(T t,MediaType contnetType,HttpOutputMessage outputMessage):将T类型的对象写到响应流中,同时指定响应的媒体类型为contentType

      

    > 使用HttpMessageConverter<T>将请求信息转化并绑定到处理方法的入参中或将响应结果转为对应类型的响应信息,Spring提供了两种途径:

      >> 1.使用@RequestBody/@ResponseBody对处理方法进行标注

      >> 2.使用HttpEntity<T>/ResponseEntity<T>作为处理方法的入参或返回值

    > 当控制器处理方法使用到@RequestBody/@ResponseBody或HttpEntity<T>/ResponseEntity<T>时,Spring首先根据请求头或响应头的Accept属性选择匹配的HttpMessageConverter,进而根据参数类型或泛型类型的

      过滤得到匹配的HttpMessageConverter,若找不到可用的HttpMessageConverter将报错

    > @RequestBody和@ResponseBody不需要成对出现

 


原文链接:https://www.cnblogs.com/LzMingYueShanPao/p/11206650.html
如有疑问请与原作者联系

标签:

版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有

上一篇:关于dom4j解析XML的问题分享

下一篇:设计模式