2019独角兽企业重金招聘Python工程师标准>>>

一、理解Struts2拦截器

1. Struts2拦截器是在访问某个Action或Action的某个方法,字段之前或之后实施拦截,并且Struts2拦截器是可插拔的,拦截器是AOP的一种实现.

2. 拦截器栈(Interceptor Stack)。Struts2拦截器栈就是将拦截器按一定的顺序联结成一条链。在访问被拦截的方法或字段时,Struts2拦截器链中的拦截器就会按其之前定义的顺序被调用。

二、实现Struts2拦截器原理

Struts2拦截器的实现原理相对简单,当请求struts2的action时,Struts 2会查找配置文件,并根据其配置实例化相对的    拦截器对象,然后串成一个列表,最后一个一个地调用列表中的拦截器

三、定义Struts2拦截器。

Struts2规定用户自定义拦截器必须实现com.opensymphony.xwork2.interceptor.Interceptor接口。该接口声明了3个方法,

void init();

void destroy();

String intercept(ActionInvocation invocation) throws Exception;

其中,init和destroy方法会在程序开始和结束时各执行一遍,不管使用了该拦截器与否,只要在struts.xml中声明了该Struts2拦截器就会被执行。

intercept方法就是拦截的主体了,每次拦截器生效时都会执行其中的逻辑。

不过,struts中又提供了几个抽象类来简化这一步骤。

public abstract class AbstractInterceptor implements Interceptor;

public abstract class MethodFilterInterceptor extends AbstractInterceptor;

都是模板方法实现的。

其中AbstractInterceptor提供了init()和destroy()的空实现,使用时只需要覆盖intercept()方法;

而MethodFilterInterceptor则提供了includeMethods和excludeMethods两个属性,用来过滤执行该过滤器的action的方法。可以通过param来加入或者排除需要过滤的方法。

一般来说,拦截器的写法都差不多。看下面的示例:

package interceptor;

import com.opensymphony.xwork2.ActionInvocation;

import com.opensymphony.xwork2.interceptor.Interceptor;

public class MyInterceptor implements Interceptor {

public void destroy() {

// TODO Auto-generated method stub

}

public void init() {

// TODO Auto-generated method stub

}

public String intercept(ActionInvocation invocation) throws Exception {

System.out.println("Action执行前插入 代码");

//执行目标方法 (调用下一个拦截器, 或执行Action)

final String res = invocation.invoke();

System.out.println("Action执行后插入 代码");

return res;

}

}

四、配置Struts2拦截器

Struts2拦截器需要在struts.xml中声明,如下struts.xml配置文件

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE struts PUBLIC

"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"

"http://struts.apache.org/dtds/struts-2.0.dtd">

<struts>

<constant name="struts.objectFactory" value="spring" />

<package name="default" extends="struts-default">

<interceptors>

<interceptor name="MyInterceptor" class="interceptor.MyInterceptor"></interceptor>

<interceptor-stack name="myInterceptorStack">

<interceptor-ref name="MyInterceptor"/>

<interceptor-ref name="defaultStack"/>

</interceptor-stack>

</interceptors>

<action name="loginAction" class="loginAction">

<result name="fail">/index.jsp </result>

<result name="success">/success.jsp</result>

<interceptor-ref name="myInterceptorStack"></interceptor-ref>

</action>

</package>

</struts>

拦截器

名字

说明

Alias Interceptor

alias

在不同请求之间将请求参数在不同名字件转换,请求内容不变

Chaining Interceptor

chain

让前一个Action的属性可以被后一个Action访问,现在和chain类型的result()结合使用。

Checkbox Interceptor

checkbox

添加了checkbox自动处理代码,将没有选中的checkbox的内容设定为false,而html默认情况下不提交没有选中的checkbox。

Cookies Interceptor

cookies

使用配置的name,value来是指cookies

Conversion Error Interceptor

conversionError

将错误从ActionContext中添加到Action的属性字段中。

Create Session Interceptor

createSession

自动的创建HttpSession,用来为需要使用到HttpSession的拦截器服务。

Debugging Interceptor

debugging

提供不同的调试用的页面来展现内部的数据状况。

Execute and Wait Interceptor

execAndWait

在后台执行Action,同时将用户带到一个中间的等待页面。

Exception Interceptor

exception

将异常定位到一个画面

File Upload Interceptor

fileUpload

提供文件上传功能

I18n Interceptor

i18n

记录用户选择的locale

Logger Interceptor

logger

输出Action的名字

Message Store Interceptor

store

存储或者访问实现ValidationAware接口的Action类出现的消息,错误,字段错误等。

Model Driven Interceptor

model-driven

如果一个类实现了ModelDriven,将getModel得到的结果放在Value Stack中。

Scoped Model Driven

scoped-model-driven

如果一个Action实现了ScopedModelDriven,则这个拦截器会从相应的Scope中取出model调用Action的setModel方法将其放入Action内部。

Parameters Interceptor

params

将请求中的参数设置到Action中去。

Prepare Interceptor

prepare

如果Acton实现了Preparable,则该拦截器调用Action类的prepare方法。

Scope Interceptor

scope

将Action状态存入session和application的简单方法。

Servlet Config Interceptor

servletConfig

提供访问HttpServletRequest和HttpServletResponse的方法,以Map的方式访问。

Static Parameters Interceptor

staticParams

从struts.xml文件中将ION>中的

中的内容设置到对应的Action中。

Roles Interceptor

roles

确定用户是否具有JAAS指定的Role,否则不予执行。

Timer Interceptor

timer

输出Action执行的时间

Token Interceptor

token

通过Token来避免双击

Token Session Interceptor

tokenSession

和Token Interceptor一样,不过双击的时候把请求的数据存储在Session中

Validation Interceptor

validation

使用action-validation.xml文件中定义的内容校验提交的数据。

Workflow Interceptor

workflow

调用Action的validate方法,一旦有错误返回,重新定位到INPUT画面

Parameter Filter Interceptor

N/A

从参数列表中删除不必要的参数

Profiling Interceptor

profiling

通过参数激活profile

提到拦截器,使我不得不想起武侠剧中劫匪们常说的一句话:“此山是我开,此树是我栽,要打此路过,留下买路财!”。难不成程序中也有“打劫”的,说的没错,拦截器就是个打劫的。在现实生活中,劫匪劫的大都是钱财,当然也有别的什么,那么程序中的“劫匪”劫的又是什么呢?或者说程序中为什么需要它?在我们的日常编程中少不了写一些重复的代码,例如在一个地方中写了一段代码,后来发现这段代码在其它地方中同样需要,在传统的编程中我们一定会采取复制、粘贴的办法。如果这段代码只在这一两个处需要,我们采取这种办法,还说的过去,但是如果系统对这段代码过于依赖,也就是这段代码在系统中出现的过多,如果那一天我们发现这段代码中在某些地方还需要完善,我们是不是要着个修改它们呢?我估计没有人会这么做,它严重违反了软件开发中一条非常重要的DRY规则,不写重复代码。说了这么多你一定知道我们为什么需要在程序中弄一个“劫匪”了吧。这个“劫匪”就是并不是劫取什么东西,只是为了在某个程序执行前后,动态的增加一些功能(以前所写通用代码块)或进行一些检查工作。那么这个拦截器到底是怎么实现的呢?实际上它是用Java中的动态代理来实现的,具体可以参考《设计模式学习笔记(十六)—Proxy模式》。

二、拦截器在Struts2中的应用

对于Struts2框架而言,正是大量的内置拦截器完成了大部分操作。像params拦截器将http请求中参数解析出来赋值给Action中对应的属性。Servlet-config拦截器负责把请求中HttpServletRequest实例和HttpServletResponse实例传递给Action……struts2内置的拦截器有很多,在此我就不一一列举了,具体可以参考《Struts2中有关struts-default.xml,struts.xml,struts.properties文件详解》。

那么怎么在struts2中定义自己的拦截器呢?

很简单Struts2为我们提供了一个Interceptor接口,该接口源代码如下:

publicinterface Interceptor extends Serializable {

void destroy();

void init();

String intercept(ActionInvocation invocation) throws Exception;

}

1)    init():在拦截器执行之前调用,主要用于初始化系统资源。

2)    destroty():与init()对应,用于拦截器执行之后销毁资源。

3)    intercept():拦截器的核心方法,实现具体的拦截操作。与action一样,该方法也返回一个字符串作为逻辑视图。如果拦截器成功调用了action,则返回一个真正的,也就是该action中execute()方法返回的逻辑视图,反之,则返回一个自定义的逻辑视图。

通常我们使用拦截器并不需要申请资源,为此Struts2还为我们提供了一个AbstractInterceptor类,该类的init()和destroy()都是空实现。我们开发自己的拦截器只需要继承这个类就行了。

下面创建一个判断用户是否登录的拦截器。代码如下:

struts.xml中配置一下。

/** *//**
 *
 * @author <a href="flustarmailto:flustar2008@163.com">flustar</a>
 * @version 1.0
 * Creation date: Feb 12, 2008 5:05:28 PM
 */

import java.util.Map;
import com.opensymphony.xwork2.Action;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;

@SuppressWarnings("serial")
public class CheckLoginInterceptor extends AbstractInterceptor {

@SuppressWarnings("unchecked")
    public String intercept(ActionInvocation actionInvocation) throws Exception {
         System.out.println("begin check login interceptor!");

// 检查Session中是否存在user

Map session = actionInvocation.getInvocationContext().getSession();

String username = (String) session.get("user");

if (username != null && username.length() > 0) {

// 存在的情况下进行后续操作。

System.out.println("already login!");

return actionInvocation.invoke();

} else {

// 否则终止后续操作,返回LOGIN

System.out.println("no login, forward login page!");

return Action.LOGIN;

}

}

}

创建好拦截器后,还不能使用,还需要我们在

下面看一下怎么配置拦截器。

<interceptors>

<interceptor name="checkLogin" class="com.myblog.interceptor.CheckLoginInterceptor" />

</interceptors>

这个定义好的拦截器在Action中怎么使用呢?使用方法很简单,如下:

<action name=" " class=" " >

<result> </result>

<interceptor-ref name="checkLogin" />

</action>

一旦我们为某个action引用了自定义的拦截器,struts2默认的拦截器就不会再起作用,因此还需要引用默认拦截器。

<action name=" " class=" " >

<result> </result>

<interceptor-ref name="checkLogin" />

<interceptor-ref name="defaultStack" />

</action>

但是我们这么做似乎也不太方便,因为如果拦截器checkLogin需要被多个action引用的话,每一个都要配置一遍太麻烦了。我们可以把它定义成默认的拦截器。

<interceptors>

<interceptor name="checkLogin" class="com.myblog.interceptor.CheckLoginInterceptor" />

<!—-定义一个拦截器栈-->

<interceptor-stack name="mydefault">

<interceptor-ref name="defaultStack" />

<interceptor-ref name="checkLogin" />

</interceptor-stack>

</interceptors>

<default-interceptor-ref name="mydefault" />

另外,struts2还为我们提供了一个方法过滤的拦截器MethodFilterInterceptor类,该类继承AbstractInterceptor类,重写了intercept(ActionInvocation invocation)并提供了一个新的方法doInterceptor(ActionInvocation invocation)抽象方法。该类的使用方法很简单,就不举例了。这个拦截器与以往的拦截器配置有所不同。那就是可以指定哪些方法需要被拦截,那些不需要。通常在引用该拦截器时指定。

<interceptor-ref name="  ">

<param name="exculdeMethods"></param>

<param name="includeMethods"></param>

</interceptor-ref>

exculdeMethods:是不被拦截的方法,如果有多个以逗号分隔。

includeMethods:需要被拦截的方法,如果有多个以逗号分隔。

拦截器-Exception
<interceptor name="exception" class="com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor"/>

配置Exception,如果出现什么样的异常就跳转到对应的页面。

在action执行之后,抛出异常才会被调用的。

拦截器alias
在action执行之前执行

The aim of this Interceptor is to alias a named parameter to a different named parameter. By acting as the glue between actions sharing similiar parameters (but with different names), it can help greatly with action chaining.

主要用在chain的action,如果从一个action直接跳转到另外一个action,可能需要传递参数值,而参数的名称是不一样的,这个时候alias拦截器就起作用了。

拦截器-ServletConfig
在action执行之前执行

An interceptor which sets action properties based on the interfaces an action implements. For example, if the action implements ParameterAware then the action context's parameter map will be set on it.

配置了这个拦截器后,action可以实现某些接口,就可以自动获取到某些对象,例如request和response对象。

详细的例子:com.work.core.action.OurActionSupport

拦截器-prepare
在action执行之前执行

必须实现Preparable接口,com.opensymphony.xwork2.Preparable

<interceptor name="prepare" class="com.opensymphony.xwork2.interceptor.PrepareInterceptor"/>

可以通过setAlwaysInvokePrepare方法,来决定prepare()是否要被执行。

和validate方法一样,你可以在action中设定prepareList()方法,那么这个方法就会被首先执行,然后在执行prepare方法。(prepareDoList也可以)。

先执行prepareList如果这个找不到就寻找prepareDoList方法,如果都找不到就不执行。

需要测试。

(注意:需要使用呢params prepare params 拦截器的配置方式)

Prepare方法,当前action中的任何方法执行都会执行到他;

import com.opensymphony.xwork2.Preparable;

public void prepare() throws Exception {

if(log.isInfoEnabled())

log.info("执行prepare()方法了");

}

/**

* 测试失败!

* @throws Exception

*/

public void prepareLoadForEdit() throws Exception {

if(log.isInfoEnabled())

log.info("执行prepareLoadForEdit()方法了");

try {

if (labid == null) {

//lab = null;

log.debug("labid==null");

} else {

lab = labServiceDao.loadForEditById(labid);

log.debug("lab="+lab);

}

} catch (DataAccessException e) {

if (log.isErrorEnabled()) {

log.error("根据labid"+labid+"查询出错。", e);

}

}

}

拦截器-i18n
在action执行之前执行

<interceptor name="i18n" class="com.opensymphony.xwork2.interceptor.I18nInterceptor"/>

实现国际化的功能。

拦截器-chain
在action执行之前执行

如果action实现了接口com.opensymphony.xwork2.Unchainable,那么对应的属性将不再拷贝。

An interceptor that copies all the properties of every object in the value stack to the currently executing object, except for any object that implements Unchainable. A collection of optional includes and excludes may be provided to control how and which parameters are copied. Only includes or excludes may be specified. Specifying both results in undefined behavior. See the javadocs for OgnlUtil.copy(Object, Object, java.util.Map, java.util.Collection, java.util.Collection) for more information.

It is important to remember that this interceptor does nothing if there are no objects already on the stack. This means two things: One, you can safely apply it to all your actions without any worry of adverse affects. Two, it is up to you to ensure an object exists in the stack prior to invoking this action. The most typical way this is done is through the use of the chain result type, which combines with this interceptor to make up the action chaining feature.

拦截器- scopedModelDriven
在action执行之前执行

你的action实现com.opensymphony.xwork2.interceptor. ScopedModelDriven接口;

如果一个Action实现了ScopedModelDriven,则这个拦截器会从相应的Scope中取出model调用Action的setModel方法将其放入Action内部。

拦截器- modelDriven
在action执行之前执行

实现ModelDriven接口

Watches for ModelDriven actions and adds the action's model on to the value stack.

Note: The ModelDrivenInterceptor must come before the both StaticParametersInterceptor and ParametersInterceptor if you want the parameters to be applied to the model.

拦截器- fileUpload
上传文件的代码,在action执行之前执行,清除临时文件在action之后执行。

<interceptor name="fileUpload" class="org.apache.struts2.interceptor.FileUploadInterceptor"/>

拦截器- checkbox(还需要测试,不是很明白)
在action执行之前执行

org.apache.struts2.interceptor.CheckboxInterceptor

如果使用了checkbox标签,才使用这个吧?

这个拦截器的功能比较奇怪啊,看了源代码,也不明白为什么要将checkbox没有选中的设置为false。

public String intercept(ActionInvocation ai) throws Exception {

Map parameters = ai.getInvocationContext().getParameters();

Map<String, String> newParams = new HashMap<String, String>();

Set<String> keys = parameters.keySet();

for (Iterator<String> iterator = keys.iterator(); iterator.hasNext();) {

String key = iterator.next();

if (key.startsWith("__checkbox_")) {

String name = key.substring("__checkbox_".length());

iterator.remove();

// is this checkbox checked/submitted?

if (!parameters.containsKey(name)) {

// if not, let's be sure to default the value to false

newParams.put(name, uncheckedValue);

}

}

}

parameters.putAll(newParams);

return ai.invoke();

}

设置checkbox标签不被选中的时候的默认值

<interceptor-ref name="checkbox">
          <param name="uncheckedValue">0</param>
       </interceptor-ref>

拦截器- staticParams
在action执行之前执行

<interceptor name="staticParams" class="com.opensymphony.xwork2.interceptor.StaticParametersInterceptor"/>

This interceptor populates the action with the static parameters defined in the action configuration. If the action implements Parameterizable, a map of the static parameters will be also be passed directly to the action.

在struts的xml配置文件中配置的参数

拦截器-params
在action执行之前执行

<interceptor name="params"

class="com.opensymphony.xwork2.interceptor.ParametersInterceptor"/>

将所有的参数值放入到stack中去。(Ognl)

ParameterNameAware接口

com.opensymphony.xwork2.interceptor.ParameteraNameAware

实现了此接口,可以设定允许哪些action的属性的值被放入stack中去。

拦截器-conversionError
在action执行之前执行

转换器

<interceptor name="conversionError" class="org.apache.struts2.interceptor.StrutsConversionErrorInterceptor"/>

将错误从ActionContext中添加到Action的属性字段中

拦截器- validation(xml自动校验配置文件)
在action执行之前执行

使用action-validation.xml文件中定义的内容校验提交的数据。

拦截器-workflow(执行action中的validate方法)
在action执行之前执行

调用Action的validate方法,一旦有错误返回,重新定位到INPUT画面

<interceptor name="workflow" class="com.opensymphony.xwork2.interceptor.DefaultWorkflowInterceptor"/>

和prepare拦截器类似啊

顺序查找并执行下面的方法。

ValidateSave  validateDoSave  validate

===拦截器必须是线程安全的==========================
拦截器-cookie
将cookie的值,放到valuestack中去,

你也可以实现接口CookiesAware,在程序中编程设置。

拦截器- createSession
org.apache.struts2.interceptor.CreateSessionInterceptor

This interceptor creates the HttpSession.

This is particular usefull when using the <@s.token> tag in freemarker templates. The tag do require that a HttpSession is already created since freemarker commits the response to the client immediately.

拦截器-其他
Debugging Interceptor
 debugging
 提供不同的调试用的页面来展现内部的数据状况。
 
Execute and Wait Interceptor
 execAndWait
 在后台执行Action,同时将用户带到一个中间的等待页面。
 
Message Store Interceptor
 store
 存储或者访问实现ValidationAware接口的Action类出现的消息,错误,字段错误等。
 
Scope Interceptor
 scope
 将Action状态存入session和application的简单方法。
 
Roles Interceptor
 roles
 确定用户是否具有JAAS指定的Role,否则不予执行。
 
Token Interceptor
 token
 通过Token来避免双击
 
Token Session Interceptor
 tokenSession
 和Token Interceptor一样,不过双击的时候把请求的数据存储在Session中
 
Parameter Filter Interceptor
 N/A
 从参数列表中删除不必要的参数
 
Profiling Interceptor
 profiling
 通过参数激活profile

在拦截器中获取action的属性值
// 找到对应的临时文件的路径

String tempFilePath = (String) invocation.getStack().findValue(

"tempFilePath");

给拦截器栈中的某个拦截器配置参数的方法
<!DOCTYPE xwork PUBLIC

"-//OpenSymphony Group//XWork 1.1.1//EN"

"http://www.opensymphony.com/xwork/xwork-1.1.1.dtd"

>

<xwork>

<include file="xwork-test-beans.xml" />

<package name="default">

<interceptors>

<interceptor name="timer" class="com.opensymphony.xwork2.interceptor.TimerInterceptor"/>

<interceptor name="test" class="com.opensymphony.xwork2.mock.MockInterceptor">

<param name="foo">fooDefault</param>

</interceptor>

<interceptor-stack name="defaultStack">

<interceptor-ref name="timer"/>

<interceptor-ref name="test"/>

</interceptor-stack>

</interceptors>

<default-interceptor-ref name="defaultStack" />

<action name="TestInterceptorParam" class="com.opensymphony.xwork2.SimpleAction">

<interceptor-ref name="defaultStack">

<param name="test.expectedFoo">expectedFooValue</param>

</interceptor-ref>

</action>

<action name="TestInterceptorParamOverride" class="com.opensymphony.xwork2.SimpleAction">

<interceptor-ref name="defaultStack">

<param name="test.foo">foo123</param>

<param name="test.expectedFoo">expectedFooValue2</param>

</interceptor-ref>

defaultStack中有个拦截器的名称为test,test拦截器中有配置参数的get和set方法。

</action>

</package>

</xwork>

转载于:https://my.oschina.net/u/1044955/blog/277111

struts2拦截器简介相关推荐

  1. Struts2拦截器和标签

    一.struts2拦截器 1.struts2是框架,封装了很多的功能,struts2里面封装的功能都是在拦截器里面. 2 struts2里面封装了很多的功能,有很多拦截器,不是每次这些拦截器都执行,每 ...

  2. Struts2拦截器的使用

    如何使用struts2拦截器,或者自定义拦截器.特别注意,在使用拦截器的时候,在Action里面必须最后一定要引用struts2自带的拦截器缺省堆栈defaultStack,如下(这里我是引用了str ...

  3. Struts2拦截器属性excludeMethods、includeMethods配置无效之解决方法

    参考:http://blog.csdn.net/coolcoffee168/article/details/7963251 在配置struts2 拦截器属性excludeMethods.include ...

  4. Struts2 拦截器 及如何获得 servlet 请求对象 以及Struts 基本配置 Session 超时设置...

    在拦截器中可以三种实现 一:继承 AbstractInterceptor 类 二:继承 MethodFilterInterceptor类 三:实现 Interceptor 接口 在实现Intercep ...

  5. 基于struts2拦截器实现用户操作日志记录

    2019独角兽企业重金招聘Python工程师标准>>> 这里基于struts2的拦截器来实现. 使用struts2拦截器拦截所有或者指定的请求,对用户操作过程中的:操作用户,操作时间 ...

  6. Struts2拦截器实现异常处理机制

    http://bbs.itcast.cn/thread-10364-1-1.html Struts2拦截器实现异常处理机制   在j2ee项目中,系统内部难免会出现一些异常,如果把异常放任不管直接打印 ...

  7. 从struts2拦截器到自定义拦截器

    http://www.cnblogs.com/withyou/p/3170440.html 拦截器可谓struts2的核心了,最基本的bean的注入就是通过默认的拦截器实现的,一般在struts2.x ...

  8. Struts2拦截器的使用 (详解)

    Struts2拦截器的使用 (详解) 如何使用struts2拦截器,或者自定义拦截器.特别注意,在使用拦截器的时候,在Action里面必须最后一定要引用struts2自带的拦截器缺省堆栈default ...

  9. struts2 拦截器_Struts2令牌拦截器示例

    struts2 拦截器 Struts 2 token interceptor can be used to handle multiple form submission problem. While ...

最新文章

  1. web前端(13)—— 了解JavaScript,JavaScript的引入方式
  2. 卫星覆盖分析品质 FOM
  3. CentOS7 下DNS的搭建
  4. linux操作系统原理_Linux内核分析-操作系统是如何工作的(二)
  5. Struts2中动态的指定返回的结果集
  6. 警惕“***性社工”现象
  7. awk命令过滤tomcat的访日日志中IP地址
  8. Windows Server2016+SQL Server 2016 Cluster安装及配置
  9. SSM订单数据管理系统
  10. 2022.3.6总结非线性系统线性化方法,第五章
  11. 2020年复旦电子信息专硕复试经验分享
  12. SnakeGame(贪吃蛇游戏)
  13. 小米手机 开发app python_一篇文章教会你用Python多线程获取小米应用商店App
  14. rap技术原理_那些你可能没有听到的技术特色Rap
  15. 在 unity中可以使用的直接设置音量大小的方法
  16. 这40款优质APP大合集,总有一个适合你!
  17. 总线 —— 总线标准
  18. 队列实现杨辉三角(附详细图解)
  19. [分享]错误“应用程序Xcode的这个版本不能与此版本的OS X配合使用”以及Mac源码和IOS开发资料分享
  20. 计算机英语什么等级考试,全国计算机等级考试是什么(概念篇)

热门文章

  1. 微机接口课设 汽车控制系统 C语言源代码 Proteus 8086
  2. 1月第2周全球域名总量TOP20:开曼群岛升至第九
  3. Nginx之负载均衡,正向代理和反向代理
  4. android snapshot作用,Heap Snapshot工具
  5. Jmeter察看结果树之Document使用
  6. 【数据库原理】关系代数
  7. 数据库原理与应用(5)——关系、关系模式、关系数据库与关系数据库模式
  8. iOS 判断设备是否越狱
  9. 使用google搜索引擎的技巧
  10. 蓝桥杯单片机第四届 省赛 模拟智能灌溉系统(第五届模拟赛)