zoukankan      html  css  js  c++  java
  • Struts2利用验证框架实现数据验证(十一)

    勿以恶小而为之,勿以善小而不为--------------------------刘备

    劝诸君,多行善事积福报,莫作恶

    上一章简单介绍了Struts2实现单文件上传,多文件上传与下载(十),如果没有看过,请观看上一章

    数据验证,分为前端验证和后端验证。

    前端验证主要是通过JavaScript和jQuery来实现,目的是: 减少客户等待的时间,减轻服务器端的压力,用户输入的错误数据,直接提示。

    后端验证的目的是: 防止“绕过”客户端,提交非法数据。 在服务器端处理数据之前,确认数据的正确性。

    这里只讲后端的验证。

    在验证的时候,需要将提示信息展示给前端, Struts2框架提供了两种方式,进行提示信息。 addFieldError() 方法和 addActionError() 方法。

    一. addFieldError() 方法和addActionError()方法

    一.一 简单小提示

    addFiledError(String name,String message) 添加字段范围内的具体的错误。

    addActionError(String message) 在Action中添加具体的错误。

    在Servlet开发阶段时,返回错误信息 通常用的是 request.setAttribute("message","具体的错误信息"),

    现在可以用addFieldError()来进行处理。

    对于类中的错误,用addActionError()进行处理。

    两者所反映的级别是不一样的. field为字段级别的,action为Action级别的。

    一.二 提示错误小例子

    一.二.一 编写验证 UserAction

    package com.yjl.web.action;
    import com.opensymphony.xwork2.ActionSupport;
    /**
    * @author 两个蝴蝶飞
    * @version 创建时间:Aug 30, 2018 8:21:09 PM
    * User的验证类
    */
    public class UserAction extends ActionSupport{
    	private static final long serialVersionUID = 1L;
    	/**
    	 * 用addFiledError()方法处理
    	 * 也是用key--value的形式进行展示的.
    	 */
    	public String field(){
    		this.addFieldError("nameErr","姓名只能是中文");
    		this.addFieldError("sexErr","性别只能选择男或者女");
    		this.addFieldError("passwordErr","密码错误");
    		return SUCCESS;
    	}
    	/**
    	 *用 addActionError()方法处理。
    	 */
    	public String action(){
    		//通常只写一个错误提示 
    		this.addActionError("第一个类中大错误");
    		return SUCCESS;
    	}
    }
    

    一.二.二 配置struts.xml文件

    <!--修改ui样式表,不用这一个,用默认的 -->
    <!--<constant name="struts.ui.theme" value="simple"></constant>-->
    <package name="validate" extends="struts-default" namespace="/">
    		
    		<action name="User_*" class="com.yjl.web.action.UserAction" method="{1}">
    				<result name="success">/WEB-INF/content/message.jsp</result>
    		</action>
    		<!-- 配置跳转页面 -->
    		<action name="*">
    			<result>/WEB-INF/content/{1}.jsp</result>
    		</action>
    </package>
    

    一.二.三 编写 /content/message.jsp

    <body>
    <h3>显示Field错误</h3>
    <!-- 会显示全部的错误 -->
    <s:fielderror></s:fielderror>
    <h3>显示单个错误</h3>
    <s:fielderror>
    	<!-- 只显示name的错误信息 -->
    	<s:param>nameErr</s:param>
    </s:fielderror>
    
    <h3>显示Action错误</h3>
    <s:actionerror/>
    
    </body>
    

    一.二.四 重启服务器,运行

    输入网址: http://localhost:8080/Struts_Validate/User_field, 显示field 域错误:

    在这里插入图片描述

    输入网址: http://localhost:8080/Struts_Validate/User_action, 显示action 域错误

    有图片

    显示字段错误时,如用户名 name是否填写错误,密码 password是否填写错误,手机号 phone是否填写错误,通常会显示全部的错误信息。

    故一般常用:

    <s:fielderror></s:fielderror>
    
    

    来直接显示所有字段的错误。

    一.二.五 hasFieldErrors() 和 hasActionErrors() 进行判断显示

    访问 filed 错误时,没有action 错误,但却将Action的提示语都显示出来了,

    访问action 错误时,没有filed 错误,但却将 Field的提示语都 显示出来了。

    常常需要在 显示错误之前,进行一下判断, 如果有错误,才显示,如果没有错误的话,就不显示 。

    用 hasFieldErrors() 用于验证是否有 field 级别的错误。

    用 hasActionErrors() 用于验证是否有 action 级别的错误。

    一.二.六 重写 /content/message.jsp 页面, 添加判断

    <body>
    <!-- 判断一下,是否有field 范围的错误 -->
    <s:if test="hasFieldErrors()">
    	<h3>显示Field错误</h3>
    	<!-- 会显示全部的错误 -->
    	<s:fielderror></s:fielderror>
    	<h3>显示单个错误</h3>
    	<s:fielderror cssErrorStyle="color:red;font-size:20px;">
    		<!-- 只显示name的错误信息 -->
    		<s:param>nameErr</s:param>
    	</s:fielderror>
    </s:if>
    <!--判断一下,是否有 action范围的错误 -->
    <s:if test="hasActionErrors()">
    	<h3>显示Action错误</h3>
    	<s:actionerror/>
    </s:if>
    </body>
    

    再次进行测试:

    输入网址: http://localhost:8080/Struts_Validate/User_field, 显示field 域错误:

    有图片

    输入网址: http://localhost:8080/Struts_Validate/User_action, 显示action 域错误

    有图片

    二 业务方法中验证

    我们希望用户在前端表单填写数据,进行提交,如果错误了,就返回相应的错误信息,如果没有任何错误,就通过。

    业务方法验证可以分为三个部分。

    二.一 开发者自己手动验证

    如用户登录时的验证:

    //第一种情况: 在登录方法中直接进行验证
    public String login(){
    	//1. 接收到各个数据,如用户名,密码,邮箱等.
    	String userName="两个蝴蝶飞";
    	String password="yjl";
    	String email="1290513799@qq.com";
    	//2. 判断用户名是否错误,如果出现了错误,就this.addFieldError("userName","用户名错误");
    	if(!"两个蝴蝶飞".equals(userName)){
    		this.addFieldError("userName","用户名错误");
    	}
    	//3. 判断密码是否错误,如果出现了错误,就this.addFieldError("password","密码错误");
    	if(!"yjl".equals(password)){
    		this.addFieldError("password","密码错误");
    	}
    	//4. 判断邮箱是否错误,如果出现了错误,就this.addFieldError("email","邮箱错误");
    	if(!"1290513799@qq.com".equals(email)){
    		this.addFieldError("email","邮箱错误");
    	}
    	//5. 判断在这个action中是否出现了错误,如果有错误,将其添加到Action中,返回输入的界面
    	if(this.hasErrors()){ 
    	 //也有hasFieldErrors()和hasActionErrors(), hasErrors()包括field错误和action错误
    		this.addActionError("登录的输入数据不对");
    		return "loginUI";
    	}
    	//6.现在才是进行正常的逻辑操作,上面都是数据的检测(第一步获取数据除外)
    	//判断是否登录成功,如果成功返回到成功界面, 如果不成功,返回到登录的界面,
    	//... 登录业务
    	return SUCCESS;
    }
    

    需要我们自己写验证代码,且不具有通过性,每一个方法,如注册方法register() 也需要进行验证。

    二.二 重写 validate() 方法

    二.二.一 Validateable 接口定义

    ActionSupport 的类定义如下:

    public class ActionSupport
    implements Action, Validateable, ValidationAware, TextProvider, LocaleProvider, Serializable{
    	
    }
    

    里面实现了一个验证接口 Validateable
    该接口 Validateable 里面有一个validate()方法

    public interface Validateable {
    
        /**
         * Performs validation.
         */
        void validate();
    
    }
    

    UserAction 继承了ActionSupport类,故继承了validate()方法,开发者 需要重写validate()方法即可。

    数据验证,写在了 validate() 方法里面,正常的登录代码写在了 login() 方法里面,

    数据验证与业务逻辑进行了分离。

    那么此时,登录的逻辑判断就可以写成:

    二.二.二 重写 validate() 方法进行验证

    //第二种方式,重写validate()方法进行验证
    public String login(){
    	//1. 接收到各个数据,如用户名,密码,邮箱等.
    	String userName="两个蝴蝶飞";
    	String password="yjl";
    	String email="1290513799@qq.com";
    	
    	//5. 判断在这个action中是否出现了错误,如果有错误,将其添加到Action中,返回输入的界面
    	if(this.hasErrors()){ //也有hasFieldErrors()和hasActionErrors(), 这是两个方法的错误相加
    		this.addActionError("登录的输入数据不对");
    		return "loginUI";
    	}
    	//直接判断型业务逻辑,不用管数据验证。(当然前面有一个检测的操作)
    	//判断是否登录成功,如果成功返回到成功界面, 如果不成功,返回到登录的界面,
    	//用addFieldError或者addActionError添加错误信息
    	return SUCCESS;
    }
    @Override
    public void validate() {
    	//只关注数据的验证
    	//1. 接收到各个数据,如用户名,密码,邮箱等.
    	String userName="两个蝴蝶飞";
    	String password="yjl";
    	String email="1290513799@qq.com";
    	//2. 判断用户名是否错误,如果出现了错误,就this.addFieldError("userName","用户名错误");
    	if(!"两个蝴蝶飞".equals(userName)){
    		this.addFieldError("userName","用户名错误");
    	}
    	//3. 判断密码是否错误,如果出现了错误,就this.addFieldError("password","密码错误");
    	if(!"yjl".equals(password)){
    		this.addFieldError("password","密码错误");
    	}
    	//4. 判断邮箱是否错误,如果出现了错误,就this.addFieldError("email","邮箱错误");
    	if(!"1290513799@qq.com".equals(email)){
    		this.addFieldError("email","邮箱错误");
    	}
    }
    

    二.二.三 流程处理

    在进入login()方法之前,首先会调用validate()方法,进行数据验证。

    相比较第一种方式,这个时候便处理上简单了一些。

    但还是有一些特别严重的问题。 那就是在访问UserAction时,在进入每一个方法之前,都会先调用validate()方法。

    如: UserAction 中 还存在 toLogin 和 register() 方法:

        public String toLogin(){
    		//先调用validate()方法
    		return "login";
    	}
    	public String register(){
    		//先调用validate()方法
    		return "register";
    	}
    

    然而,实际生活中, 登录时的验证与注册时的验证,验证数据的多少是不一样的,如注册时验证性别不为空,居住地不为空,
    在登录时是不需要验证的,还有确认密码登录时是没有的。
    更有的情况,登录和注册时对同一数据的验证规则是不一样的(根据具体业务情况分析),
    如注册时需要验证用户名是否存在,登录时不需要验证用户名是否存在。
    这个时候,需要在validate()方法中进行大量的判断,如果方法名login,走哪个验证,是register(),起哪个验证,是toLogin()的话,不走验证。

    二.三 针对单个方法分别进行验证

    需要注意,这个时候,验证数据的方法名称必须符合validateXxx()的形式。

    如果是对login() 方法进行验证,那么验证login数据是否正确的方法名称必须是 validateLogin(),

    如果是对register() 方法进行验证,那么验证reigster 数据是否正确的方法名称必须是 validateRegister().

    对login()和register()方法分别进行验证:

    public String login(){
    	if(this.hasErrors()){
    		this.addActionError("登录的输入数据不对");
    		return "loginUI";
    	}
    	return "login";
    }
    public String register(){
    	if(this.hasErrors()){
    		this.addActionError("注册的输入数据不对");
    		return "loginUI";
    	}
    	return "register";
    }
    public void validateLogin(){
    	//对登录表单中的数据进行验证
    }
    public void validateRegister(){
    	//对注册表单中的数据进行验证
    }
    
    

    有人会问,在注册时出现了错误,已经将数据放入到Action中了,即hasErrors()为true了,那么进入login()方法,取出的数据不就是true吗? 这是一个误区。
    Strtus2是多实例的,在进入register()方法时,会重新实例化对象,所有的数据都会清空(静态属性和代码块除外),包括错误信息。
    在进入login()时,也会重新实例化一下,会清空的。 需要设置 scope="prototype"。

    这种方式相对于第二种来说,可读性大大增强,但每一个方法都要验证数据,都需要写一个validateXxx()方法,会导致验证方法过多。

    注意,当Action既有 validate()方法,也有validateLogin()方法时,如果执行的是login操作时,
    那么会先执行validateLogin()方法,
    再执行validate()方法,有一个先后的顺序,但是两者均起作用的。

    (图片摘自森林森前辈的Struts2(十二),本章图片均来自于此,谢谢。
    源址为:https://www.cnblogs.com/liunanjava/p/4383237.html

    在这里插入图片描述

    常常用 Validate 框架进行验证。

    三. validate框架验证数据

    使用验证框架的好处, 1.验证实现的部分方便复用和扩展,2.验证的实现和业务处理分离。

    验证里的配置需要在 xml文件中进行相应的配置。

    这里验证一些常见的属性,用User类进行相应的包装。

    三.一 未使用框架验证之前

    三.一.一 编写 User.java

    /**
    * @author 两个蝴蝶飞
    * @version 创建时间:Sep 8, 2018 2:46:59 PM
    * 用于包装框架数据的实体类,没有实际意义
    */
    public class User {
    	/**
    	 * @param id 编号id
    	 * @param userName 用户名
    	 * @param password 密码
    	 * @param name 真实姓名
    	 * @param sex 性别
    	 * @param age 年龄
    	 */
    	private Integer id;
    	private String userName;
    	private String password;
    	private String name;
    	private String sex;
    	private int age;
    }
    

    属性需要实现setter和getter方法,也添加一个 toString() 方法。

    三.一.二 编写 RegisterAction 类

    里面定义跳转到注册和注册的两个方法:

    /**
    * @author 两个蝴蝶飞
    * @version 创建时间:Aug 30, 2018 8:21:09 PM
    * User的相关验证
    */
    public class RegisterAction extends ActionSupport{
    	private static final long serialVersionUID = 1L;
    	private static Logger logger=Logger.getLogger(UserAction.class);
    	private User user;
    	public User getUser() {
    		return user;
    	}
    	public void setUser(User user) {
    		this.user = user;
    	}
    	public String toRegister(){
    		logger.info("跳转到注册页面");
    		return "registerUI";
    	}
    	public String register(){
    		logger.info("执行注册的功能");
    		logger.info("用户名是:"+user.getUserName()+",密码是:"+user.getPassword());
    		return "register";
    	}
    }
    
    

    三.一.三 配置 struts.xml

    <action name="Register_*" class="com.yjl.web.action.RegisterAction" method="{1}">
    			<result name="registerUI">/WEB-INF/content/register.jsp</result>
    			<result name="register">/WEB-INF/content/success.jsp</result>
    			<!--错误后,跳转到此页面-->
    			<result name="input">/WEB-INF/content/register.jsp</result>
    </action>
    

    三.一.四 编写 /content/register.jsp

    <body>
    	<h3>这是一个注册框架的页面</h3>
        <s:if test="hasFieldErrors()">
    		<s:fielderror></s:fielderror>
    	</s:if>
    	<s:form action="Register_register" method="post" namespace="/">
    		<s:textfield label="编号" name="user.id"></s:textfield>
    		<s:textfield label="用户名" name="user.userName"></s:textfield>
    		<s:textfield label="密码" name="user.password"></s:textfield>
    		<s:textfield label="确认密码" name="repassword"></s:textfield>
    		<s:textfield label="真实姓名" name="user.name"></s:textfield>
    		<s:radio label="性别" list="#{'m':'男','f':'女'}" name="user.sex"></s:radio>
    		<s:textfield label="年龄" name="user.age"></s:textfield>
    		<s:submit value="提交"/>
    	</s:form>
    </body>
    
    

    /content/success.jsp 的内容显示 注册成功

    <body>
    	注册成功
    </body>
    

    三.一.五 重启服务器,进行验证

    网址是: http://localhost:8080/Struts_Validate/Register_toRegister

    在这里插入图片描述

    点击提交,页面正常跳转


    在这里插入图片描述

    日志打印输出:


    在这里插入图片描述


    这个时候,环境已经搭建成功了。

    现在并没有进行相应的验证操作。

    接下来就是具体的验证。

    三.二 validate验证框架的具体详细使用

    三.二.一 创建 Xxx.xml 验证文件

    在action包下,创建 .xml 配置文件,该配置文件的文件名称 action名-validation.xml。

    如UserAction的验证配置文件是UserAction-validation.xml,注意连接符是-,并不是下划线_

    该例子用的是 RegisterAction, 那么创建的配置文件名称就是 RegisterAction-validation.xml

    有图片

    三.二.二 配置约束

    在UserAction-validation.xml中引入相关的约束

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE validators PUBLIC "-//Apache Struts//XWork Validator 1.0.2//EN" "http://struts.apache.org/dtds/xwork-validator-1.0.2.dtd">
    <validators>
    	<!-- 里面写具体的验证描述 -->
    </validators>
    
    

    三.二.三 添加id 的约束

    <!-- field中的name指定的是要验证的哪一个属性-->
    <field name="user.id"> 
    		<!-- field-validator 中type指定类型 -->
    		<field-validator type="required"> 
    			<!-- message指定错误的信息 -->
    			<message>必须存在id</message> 
    		</field-validator>
    </field>
    

    三.二.四 重启服务器,验证

    重启服务器,发现出错了。

    再次输入网址: http://localhost:8080/Struts_Validate/Register_toRegister

    有图片

    提示,必须输入id的值。

    当我们在前端 get 方式传入id的值后, (注意,传入的是user.id的值)

    有图片

    没有提示任何错误,可以正确的进行跳转到注册的页面了。

    当我们输入一些值,但不输入编号时:

    有图片

    点击提交按钮后,

    有图片

    说明,验证框架起作用了,验证了 id不能为空。

    三.二.五 验证 user.name的类型

    配置user.userName 必须是字符串类型,且不能为空

    在RegisterAction-validation.xml 中配置user.userName的验证

    <!-- 配置user.userName的类型 -->
    	 <field name="user.userName">
    		<field-validator type="requiredstring">
    			<message>用户名不能为空,且必须是字母类型</message>
    		</field-validator>
    </field>
    

    重启服务器,进行测试,验证框架也同样起作用(这儿就不贴图了)

    三.二.六 验证user.password

    必须是字符串类型,且有长度限制。

    在RegisterAction-validation.xml 中配置user.password 的验证

        <field name="user.password">
    		<field-validator type="requiredstring">
    			<message>密码不能为空</message>
    		</field-validator>
    		<!-- 多添加一个验证 -->
    		<field-validator type="stringlength">
    			<!-- 去除两边的空格 -->
    			<param name="trim">true</param>
    			<!-- 设置最小和最大的长度, 注意是大写Length -->
    			<param name="minLength">6</param>
    			<param name="maxLength">15</param>
    			<!-- 设置显示的信息  可以用ognl表达式来显示-->
    			<message>密码的长度应该在${minLength}~${maxLength}之间</message>
    		</field-validator>
    	</field>
    

    可以在一个字段中,添加多个验证。 注意参数trim,maxLength,minLength的写法。

    验证长度用type="stringlength" 这里是小写。

    三.二.七 配置确认密码与user.password密码值一样

    常用于字段表达式

    前端jsp 设置:

     <s:textfield label="密码" name="user.password"></s:textfield>
     <s:textfield label="确认密码" name="repassword"></s:textfield>
    

    在RegisterAction-validation.xml 中配置repassword 的验证

    <field name="repassword">
    		<field-validator type="fieldexpression" short-circuit="true">
    			<param name="trim">true</param>
    			<param name="expression"><![CDATA[(#parameters.password[0] == #parameters.repassword[0])]]></param>
    			<message>确认密码必须与原先密码相同</message>
    		</field-validator>
    </field>
    

    这个时候,才算是达到了要达到的效果。

    三.二.八 配置真实姓名的中文验证

    必须是2~4个中文,用regex类型,演示正则表达式

    <field name="user.name">
    		<field-validator type="regex">
    			<!-- 记住中文的验证规则 -->
    			<param name="regexExpression"><![CDATA[([u4E00-u9FA5]{2,4})]]></param>
    			<message>必须是两个汉字~四个汉字</message>
    		</field-validator>
    	</field>
    

    三.二.九 对age的int类型配置

    需要指定其最大和最小值 用int

    <field name="user.age">
    	 	<field-validator type="int">
    	 		<!-- 最小值和最大值 min,max-->
    	 		<param name="min">18</param>
    	 		<param name="max">58</param>
    	 		<message>注册年龄必须在${min}~${max}岁之间</message>
    	 	</field-validator>
    	</field>
    

    三.二.十 对money的double类型配置

    用double类型

    <field name="user.money">
    	 	<field-validator type="double">
    	 		<message>金钱必须是小数</message>
    	 	</field-validator>
    	</field>
    

    输入整数或者浮点数是可以通过,但是输入字母是出错的。 另

    外,输入1.2d,或者1.2f是正确的。

    如果出错,显示的信息是:

    在这里插入图片描述

    三.三 验证文件所在的位置

    在UserAction-validator.xml验证文件中,那些type="int",type="required",并不是随便写的,而是已经定义好的。它在

    Struts2下载目录Struts2srcappsportletsrcmain esources目录下

    在这里插入图片描述

    该文件,其中内容主要是:

    validators.xml文件:

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE validators PUBLIC
            "-//Apache Struts//XWork Validator Config 1.0//EN"
            "http://struts.apache.org/dtds/xwork-validator-config-1.0.dtd">
    <validators>
        <validator name="required" class="com.opensymphony.xwork2.validator.validators.RequiredFieldValidator"/>
        <validator name="requiredstring" class="com.opensymphony.xwork2.validator.validators.RequiredStringValidator"/>
        <validator name="int" class="com.opensymphony.xwork2.validator.validators.IntRangeFieldValidator"/>
        <validator name="short" class="com.opensymphony.xwork2.validator.validators.ShortRangeFieldValidator"/>
        <validator name="double" class="com.opensymphony.xwork2.validator.validators.DoubleRangeFieldValidator"/>
        <validator name="date" class="com.opensymphony.xwork2.validator.validators.DateRangeFieldValidator"/>
        <validator name="expression" class="com.opensymphony.xwork2.validator.validators.ExpressionValidator"/>
        <validator name="fieldexpression" class="com.opensymphony.xwork2.validator.validators.FieldExpressionValidator"/>
        <validator name="email" class="com.opensymphony.xwork2.validator.validators.EmailValidator"/>
        <validator name="url" class="com.opensymphony.xwork2.validator.validators.URLValidator"/>
        <validator name="visitor" class="com.opensymphony.xwork2.validator.validators.VisitorFieldValidator"/>
        <validator name="conversion" class="com.opensymphony.xwork2.validator.validators.ConversionErrorFieldValidator"/>
    </validators>
    

    可以点击进入查看源代码,其中<param></param>中就是那些属性。

    在这里插入图片描述

    四. 为每一个方法写单独验证,

    上面t每一个Action写了一个xml验证文件,这个是相对于整个Action来说的。

    即这个Action中的每一个方法,都会进行这些统一的验证。

    做一个简单的小例子。

    在UserAction中添加一个转到登录的方法,在Action 写入方法,

    public String toLogin(){
    		logger.info("跳转到登录的页面");
    		return "toLogin";
    	}
    
    

    其相应的 struts.xml 配置文件 :

    <result name="toLogin">/login.jsp</result>
    

    访问toLogin方法时: http://localhost:8090/Struts_validate/User_toLogin.action

    会跳转到注册的页面,(跳转到注册页面是因为出错了,配置了result 中name="input")

    日志也没有输出

    在这里插入图片描述

    在执行toLogin()方法之前,也对user.id,user.name 等属性 进行了相应的验证。

    四.一 创建业务性验证

    在与要验证的Action同级目录下,创建一个验证文件,命名方式必须是: ActionName-要验证方法名-validation.xml。

    故新建一个UserAction-register-validation.xml文件,添加上面的一些验证,原先的UserAction-validation.xml文件保留,但去除验证配置。
    在这里插入图片描述

    重启服务器,进入http://localhost:8090/Struts_validate/User_toLogin.action,发现可以正常进入,会跳转到相应的login.jsp页面,而且日志也可以打印输出。

    在这里插入图片描述

    这样就完成了单个业务验证的处理。

    有时候,一个Action中有很多方法,特别是toXXX页面的方法,这个时候就不建议对整个Action进行验证了,而是对每一个方法即业务进行单独的验证。但可能会造成一个Action中的验证文件过多的情况。根据业务需求进行相应的取舍。

    即如果是多个方法,可以:

    在这里插入图片描述

    对add,login,register 三个方法进行单独的验证。

    五. 验证框架的图像总结

    验证顺序:

    在这里插入图片描述

    验证知识点总结

    在这里插入图片描述

    本章节代码链接为:

    链接:https://pan.baidu.com/s/1_8Uo0YgGt9DLh1GRum0_uw 
    提取码:yi71 
    

    谢谢您的观看!!!

  • 相关阅读:
    基于Enterprise Library 6 的AOP实现
    命行下的查询与替换字符串
    软件架构中质量特性
    【redis】突然流量增大,不定时挂死排障记录
    Heritrix 3.1.0 源码解析(二)
    Apache Jackrabbit源码研究(四)
    Heritrix 3.1.0 源码解析(三)
    Apache Jackrabbit源码研究(五)
    Heritrix 3.1.0 源码解析(一)
    JVM 自定义的类加载器的实现和使用
  • 原文地址:https://www.cnblogs.com/yjltx/p/13071765.html
Copyright © 2011-2022 走看看