struts2:拦截器
拦截器(Interceptor)是Struts 2的核心组件,Struts 2框架的大部分功能都是通过拦截器来完成的,例如数据校验,国际化,文件上传和下载等。为了实现这些功能,Struts 2框架提供了一个强大的拦截器策略。
- 拦截器是Struts 2框架中的重要组成部分,它是AOP(面向方向编程)思想的一种实现。使用拦截器给开发过程带来了很多好处:可以把大问题分解成多个小问题以便分别处理,同时可以使Action更专注于处理的事情,而把其他的一些相关功能分配给各个拦截器来进行处理。
- 在Struts 2中可将各个功能应的拦截器分开定义,每个拦截器完成单个功能,如果要运用某个功能就加入对应的拦截器,实现了拦截器的可插拔式的设计,即这些拦截器可以自由选择,灵活的组合在一起形成拦截器链(Interceptor Chain)或拦截器栈(Interceptor Stack)。
- 所谓拦截器链是指对应各个功能的拦截器组成的集合,它们按照一定的顺序排列在一起形成链,当有适配拦截器链访问的请求进来时,这些拦截器就会按照之前定义的顺序被调用。
使用Struts2拦截器
1. 配置拦截器
拦截器的配置是在struts.xml文件中完成的,拦截器通常使用<interceptor>标签来定义,该标签有两个属性name和class,分别用来指定拦截器名称及其实现类。
<interceptor name="interceptorName" class="interceptorClass">
<param name="paramName">paramValue</param>
</interceptor>
2. 拦截器栈
- 当开发的过程中需要定义多个拦截器时,可以将它们定义为一个拦截器栈。
- 当一个拦截器栈被附加到一个Action上面时,在执行该Action之前,必须先执行拦截器栈中的每一个拦截器。
- 使用拦截器栈不仅可以确定多个拦截器的执行顺序(拦截器栈中各个拦截器是按照其定义的顺序来执行的),同时,把相关的拦截器放在同一个栈中,管理起来也更为方便。
- 定义拦截器栈需要用到<interceptor-stack>标签,该标签内包含了一系列的<interceptor-ref>子标签,这些子标签用来定义拦截器栈中包含的多个拦截器引用。
<package name="default" extends="struts-default" >
<interceptors>
<!--定义两个拦截器,拦截器名分别为interceptor1和interceptor2-->
<interceptor name="interceptor1" class=”interceptorClass”/>
<interceptor name="interceptor2" class=”interceptorClass”/>
<!--定义一个拦截器栈,拦截器包含了两个拦截器-->
<interceptor-stack name="myStack">
<interceptor-ref name="interceptor1"/>
<interceptor-ref name="interceptor2"/>
</interceptor-stack>
</interceptors>
</package>
注意:在一个拦截器栈中也可以引用另一个拦截器栈。
3. 默认拦截器
- 如果想对一个包下的多个Action使用相同的拦截器,则需要为该包中每个Action都重复指定同一个拦截器,显然过于繁琐,解决这个问题的方法就是使用默认拦截器。
- 默认拦截器是指在一个包下定义的拦截器,该拦截器对包下所有的Action都起作用。
- 一旦为某一个包指定了默认拦截器且该包中的Action未显式的指定拦截器,则该默认拦截器会起作用。反之,若此包中的Action显式指定了某个拦截器,则该默认拦截器被屏蔽,不会起作用,此时,若仍想使用默认拦截器,则需要用户手动配置该默认拦截器的引用。
- 默认拦截器的配置需要使用<default-interceptor-ref>标签,在该标签中通过指定name属性来引用已经定义好的拦截器 。
- 需要注意的是,每个包下只能定义一个默认拦截器。如果确实需要指定多个拦截器共同作为默认拦截器,则可以将这些拦截器定义为一个拦截器栈,再将这个拦截器栈配置成默认拦截器就可以了。
- 实际上,拦截器类是定义在一个特殊的配置文件中的,这个配置文件就是struts-default.xml。当自定义包继承了struts-default默认包后,它不仅继承了其内置的各个拦截器,而且还继承了其默认拦截器栈,也就是说对于继承了struts-default包的某个自定义包下的所有的Action,struts-default包的默认拦截器栈会作用于所有这些Action。
<?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>
<package name="default" extends="struts-default">
<interceptors>
<!--定义两个拦截器-->
<interceptor name="interceptor1" class="interceptorClass"/>
<interceptor name="interceptor2" class="interceptorClass"/>
<!--定义一个拦截器栈-->
<interceptor-stack name="myStack">
<interceptor-ref name="interceptor1"/>
<interceptor-ref name="interceptor2"/>
<interceptor-ref name="defaultStack"/>
</interceptor-stack>
</interceptors>
<!--配置包下的默认拦截器,既可以是拦截器,也可以是拦截器栈-->
<default-interceptor-ref name="myStack"/>
<action name="login" class="tutorial.Login">
<result name="input">login.jsp</result>
</action>
</package>
</struts>
struts-default.xml文件位于:struts2-core-2.3.x.jar文件中。包struts-default内容参考如下(摘录自struts-default.xml):
<package name="struts-default" abstract="true">
<result-types>
<result-type name="chain" class="com.opensymphony.xwork2.ActionChainResult"/>
<result-type name="dispatcher" class="org.apache.struts2.dispatcher.ServletDispatcherResult" default="true"/>
<result-type name="freemarker" class="org.apache.struts2.views.freemarker.FreemarkerResult"/>
<result-type name="httpheader" class="org.apache.struts2.dispatcher.HttpHeaderResult"/>
<result-type name="redirect" class="org.apache.struts2.dispatcher.ServletRedirectResult"/>
<result-type name="redirectAction" class="org.apache.struts2.dispatcher.ServletActionRedirectResult"/>
<result-type name="stream" class="org.apache.struts2.dispatcher.StreamResult"/>
<result-type name="velocity" class="org.apache.struts2.dispatcher.VelocityResult"/>
<result-type name="xslt" class="org.apache.struts2.views.xslt.XSLTResult"/>
<result-type name="plainText" class="org.apache.struts2.dispatcher.PlainTextResult" />
</result-types> <interceptors>
<interceptor name="alias" class="com.opensymphony.xwork2.interceptor.AliasInterceptor"/>
<interceptor name="autowiring" class="com.opensymphony.xwork2.spring.interceptor.ActionAutowiringInterceptor"/>
<interceptor name="chain" class="com.opensymphony.xwork2.interceptor.ChainingInterceptor"/>
<interceptor name="conversionError" class="org.apache.struts2.interceptor.StrutsConversionErrorInterceptor"/>
<interceptor name="cookie" class="org.apache.struts2.interceptor.CookieInterceptor"/>
<interceptor name="clearSession" class="org.apache.struts2.interceptor.ClearSessionInterceptor" />
<interceptor name="createSession" class="org.apache.struts2.interceptor.CreateSessionInterceptor" />
<interceptor name="debugging" class="org.apache.struts2.interceptor.debugging.DebuggingInterceptor" />
<interceptor name="execAndWait" class="org.apache.struts2.interceptor.ExecuteAndWaitInterceptor"/>
<interceptor name="exception" class="com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor"/>
<interceptor name="fileUpload" class="org.apache.struts2.interceptor.FileUploadInterceptor"/>
<interceptor name="i18n" class="com.opensymphony.xwork2.interceptor.I18nInterceptor"/>
<interceptor name="logger" class="com.opensymphony.xwork2.interceptor.LoggingInterceptor"/>
<interceptor name="modelDriven" class="com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor"/>
<interceptor name="scopedModelDriven" class="com.opensymphony.xwork2.interceptor.ScopedModelDrivenInterceptor"/>
<interceptor name="params" class="com.opensymphony.xwork2.interceptor.ParametersInterceptor"/>
<interceptor name="actionMappingParams" class="org.apache.struts2.interceptor.ActionMappingParametersInteceptor"/>
<interceptor name="prepare" class="com.opensymphony.xwork2.interceptor.PrepareInterceptor"/>
<interceptor name="staticParams" class="com.opensymphony.xwork2.interceptor.StaticParametersInterceptor"/>
<interceptor name="scope" class="org.apache.struts2.interceptor.ScopeInterceptor"/>
<interceptor name="servletConfig" class="org.apache.struts2.interceptor.ServletConfigInterceptor"/>
<interceptor name="timer" class="com.opensymphony.xwork2.interceptor.TimerInterceptor"/>
<interceptor name="token" class="org.apache.struts2.interceptor.TokenInterceptor"/>
<interceptor name="tokenSession" class="org.apache.struts2.interceptor.TokenSessionStoreInterceptor"/>
<interceptor name="validation" class="org.apache.struts2.interceptor.validation.AnnotationValidationInterceptor"/>
<interceptor name="workflow" class="com.opensymphony.xwork2.interceptor.DefaultWorkflowInterceptor"/>
<interceptor name="store" class="org.apache.struts2.interceptor.MessageStoreInterceptor" />
<interceptor name="checkbox" class="org.apache.struts2.interceptor.CheckboxInterceptor" />
<interceptor name="profiling" class="org.apache.struts2.interceptor.ProfilingActivationInterceptor" />
<interceptor name="roles" class="org.apache.struts2.interceptor.RolesInterceptor" />
<interceptor name="annotationWorkflow" class="com.opensymphony.xwork2.interceptor.annotations.AnnotationWorkflowInterceptor" />
<interceptor name="multiselect" class="org.apache.struts2.interceptor.MultiselectInterceptor" /> <!-- Basic stack -->
<interceptor-stack name="basicStack">
<interceptor-ref name="exception"/>
<interceptor-ref name="servletConfig"/>
<interceptor-ref name="prepare"/>
<interceptor-ref name="checkbox"/>
<interceptor-ref name="multiselect"/>
<interceptor-ref name="actionMappingParams"/>
<interceptor-ref name="params">
<param name="excludeParams">dojo\..*,^struts\..*,^session\..*,^request\..*,^application\..*,^servlet(Request|Response)\..*,parameters\...*</param>
</interceptor-ref>
<interceptor-ref name="conversionError"/>
</interceptor-stack> <!-- Sample validation and workflow stack -->
<interceptor-stack name="validationWorkflowStack">
<interceptor-ref name="basicStack"/>
<interceptor-ref name="validation"/>
<interceptor-ref name="workflow"/>
</interceptor-stack> <!-- Sample file upload stack -->
<interceptor-stack name="fileUploadStack">
<interceptor-ref name="fileUpload"/>
<interceptor-ref name="basicStack"/>
</interceptor-stack> <!-- Sample model-driven stack -->
<interceptor-stack name="modelDrivenStack">
<interceptor-ref name="modelDriven"/>
<interceptor-ref name="basicStack"/>
</interceptor-stack> <!-- Sample action chaining stack -->
<interceptor-stack name="chainStack">
<interceptor-ref name="chain"/>
<interceptor-ref name="basicStack"/>
</interceptor-stack> <!-- Sample i18n stack -->
<interceptor-stack name="i18nStack">
<interceptor-ref name="i18n"/>
<interceptor-ref name="basicStack"/>
</interceptor-stack> <!-- An example of the paramsPrepareParams trick. This stack
is exactly the same as the defaultStack, except that it
includes one extra interceptor before the prepare interceptor:
the params interceptor. This is useful for when you wish to apply parameters directly
to an object that you wish to load externally (such as a DAO
or database or service layer), but can't load that object
until at least the ID parameter has been loaded. By loading
the parameters twice, you can retrieve the object in the
prepare() method, allowing the second params interceptor to
apply the values on the object. -->
<interceptor-stack name="paramsPrepareParamsStack">
<interceptor-ref name="exception"/>
<interceptor-ref name="alias"/>
<interceptor-ref name="i18n"/>
<interceptor-ref name="checkbox"/>
<interceptor-ref name="multiselect"/>
<interceptor-ref name="params">
<param name="excludeParams">dojo\..*,^struts\..*,^session\..*,^request\..*,^application\..*,^servlet(Request|Response)\..*,parameters\...*</param>
</interceptor-ref>
<interceptor-ref name="servletConfig"/>
<interceptor-ref name="prepare"/>
<interceptor-ref name="chain"/>
<interceptor-ref name="modelDriven"/>
<interceptor-ref name="fileUpload"/>
<interceptor-ref name="staticParams"/>
<interceptor-ref name="actionMappingParams"/>
<interceptor-ref name="params">
<param name="excludeParams">dojo\..*,^struts\..*,^session\..*,^request\..*,^application\..*,^servlet(Request|Response)\..*,parameters\...*</param>
</interceptor-ref>
<interceptor-ref name="conversionError"/>
<interceptor-ref name="validation">
<param name="excludeMethods">input,back,cancel,browse</param>
</interceptor-ref>
<interceptor-ref name="workflow">
<param name="excludeMethods">input,back,cancel,browse</param>
</interceptor-ref>
</interceptor-stack> <!-- A complete stack with all the common interceptors in place.
Generally, this stack should be the one you use, though it
may do more than you need. Also, the ordering can be
switched around (ex: if you wish to have your servlet-related
objects applied before prepare() is called, you'd need to move
servletConfig interceptor up. This stack also excludes from the normal validation and workflow
the method names input, back, and cancel. These typically are
associated with requests that should not be validated.
-->
<interceptor-stack name="defaultStack">
<interceptor-ref name="exception"/>
<interceptor-ref name="alias"/>
<interceptor-ref name="servletConfig"/>
<interceptor-ref name="i18n"/>
<interceptor-ref name="prepare"/>
<interceptor-ref name="chain"/>
<interceptor-ref name="scopedModelDriven"/>
<interceptor-ref name="modelDriven"/>
<interceptor-ref name="fileUpload"/>
<interceptor-ref name="checkbox"/>
<interceptor-ref name="multiselect"/>
<interceptor-ref name="staticParams"/>
<interceptor-ref name="actionMappingParams"/>
<interceptor-ref name="params">
<param name="excludeParams">dojo\..*,^struts\..*,^session\..*,^request\..*,^application\..*,^servlet(Request|Response)\..*,parameters\...*</param>
</interceptor-ref>
<interceptor-ref name="conversionError"/>
<interceptor-ref name="validation">
<param name="excludeMethods">input,back,cancel,browse</param>
</interceptor-ref>
<interceptor-ref name="workflow">
<param name="excludeMethods">input,back,cancel,browse</param>
</interceptor-ref>
<interceptor-ref name="debugging"/>
</interceptor-stack> <!-- The completeStack is here for backwards compatibility for
applications that still refer to the defaultStack by the
old name -->
<interceptor-stack name="completeStack">
<interceptor-ref name="defaultStack"/>
</interceptor-stack> <!-- Sample execute and wait stack.
Note: execAndWait should always be the *last* interceptor. -->
<interceptor-stack name="executeAndWaitStack">
<interceptor-ref name="execAndWait">
<param name="excludeMethods">input,back,cancel</param>
</interceptor-ref>
<interceptor-ref name="defaultStack"/>
<interceptor-ref name="execAndWait">
<param name="excludeMethods">input,back,cancel</param>
</interceptor-ref>
</interceptor-stack> </interceptors> <default-interceptor-ref name="defaultStack"/> <default-class-ref class="com.opensymphony.xwork2.ActionSupport" />
</package>
4. 使用拦截器
- 将拦截器和拦截器栈定义好以后,就可以使用这些已定义的拦截器或拦截器栈来拦截Action了,拦截器或拦截器栈会先拦截并处理用户请求,然后再执行Action的execute方法。
- 使用拦截器时需要在Action中进行配置,通过<interceptor-ref>标签来指定在Action中使用的拦截器。
<package name="default" extends="struts-default">
<interceptors>
<!--定义三个拦截器-->
<interceptor name="interceptor1" class="interceptorClass"/>
<interceptor name="interceptor2" class="interceptorClass"/>
<interceptor name="interceptor3" class="interceptorClass">
<param name="paramName">paranValue1</param>
</interceptor>
<!--定义一个拦截器栈-->
<interceptor-stack name="myStack">
<interceptor-ref name="interceptor1"/>
<interceptor-ref name="interceptor2"/>
<interceptor-ref name="defaultStack"/>
</interceptor-stack>
</interceptors>
<action name="login" class="tutorial.Login">
<result name="input">login.jsp</result>
<!--在名为login的Action中使用已经定义的拦截器-->
<interceptor-ref name="interceptor1"/>
<interceptor-ref name="interceptor2"/>
<interceptor-ref name="interceptor3">
<param name="paramName">paramValue2</param>
</interceptor-ref>
<interceptor-ref name="myStack"/>
</action>
</package>
注意:拦截器的参数指定有两种方式,一种是在定义拦截器时指定参数,该种方式指定的参数是默认参数;另一种是在使用拦截器时指定参数,该种方式指定的参数将会覆盖默认参数值。
上述内容摘录自:《Java Web整合开发实战》第8章
实例,未登录用户不予查看明细
1. JSP页面
login.jsp,登录界面
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%@ page isELIgnored="false"%>
<%@ taglib uri="/struts-tags" prefix="s"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<body>
<font style="color:red"><s:property value="errorMessage"/></font>
<s:form action="intercepLogin" method="post">
账号:<s:textfield name="username"></s:textfield>
<br />
密码:<s:textfield name="password"></s:textfield>
<br />
<s:submit value="提交"></s:submit>
</s:form>
</body>
</html>
showDetail.jsp,显示详细信息页面
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%@ page isELIgnored="false"%>
<%@ taglib uri="/struts-tags" prefix="s"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<body>
Hello, we are here!
</body>
</html>
2. Action类与Interceptor类
InptercepLoginAction.java,处理登录请求
package com.clzhang.struts2.demo11; import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport; public class InptercepLoginAction extends ActionSupport {
private String username;
private String password; public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
} public String execute() {
System.out.println(username + "\t" + password); // 一到登录页面,即移除session中变量
ActionContext.getContext().getSession().remove("userInfo"); // 只要用户名与密码长度大于等于4,都认为是合法用户
if (username.trim().length() >= 4 && password.trim().length() >= 4) {
ActionContext.getContext().getSession().put("userInfo", username); return SUCCESS;
} return INPUT;
}
}
ShowAction.java,处理显示详细信息请求
package com.clzhang.struts2.demo11; import com.opensymphony.xwork2.ActionSupport; public class ShowAction extends ActionSupport {
public String execute() {
return SUCCESS;
}
}
LoginInterceptor.java,拦截器类,处理检查用户是否已经登录
package com.clzhang.struts2.demo11; import java.util.Map; import com.opensymphony.xwork2.Action;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor; public class LoginInterceptor extends AbstractInterceptor { @Override
public String intercept(ActionInvocation invocation) throws Exception {
// 取得请求相关的ActionContext实例
ActionContext ctx = invocation.getInvocationContext();
Map session = ctx.getSession();
String user = (String)session.get("userInfo"); // 如果没有登陆
if (user != null) {
System.out.println("当前用户已经登录,继续处理请求..."); return invocation.invoke();
} ctx.put("errorMessage", "你还没有登录,或者登录超时,请重新登录后继续操作!"); return Action.LOGIN;
}
}
3. struts.xml文件修改如下内容
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
<package name="myStruts" extends="struts-default">
<interceptors>
<interceptor name="authority" class="com.clzhang.struts2.demo11.LoginInterceptor">
</interceptor>
<!-- 拦截器栈 -->
<interceptor-stack name="myDefault">
<interceptor-ref name="defaultStack" />
<interceptor-ref name="authority"/>
</interceptor-stack>
</interceptors> <global-results>
<result name="login">/struts2/demo11/login.jsp</result>
</global-results> <action name="intercepLogin" class="com.clzhang.struts2.demo11.InptercepLoginAction">
<result name="input">/struts2/demo11/login.jsp</result>
<result name="success" type="redirectAction">
<param name="actionName">intercepShow</param>
</result>
</action> <action name="intercepShow" class="com.clzhang.struts2.demo11.ShowAction">
<result>/struts2/demo11/showDetail.jsp</result>
<interceptor-ref name="myDefault"/>
</action>
</package>
</struts>
4. 测试
打开IE,输入地址:http://127.0.0.1:8080/st/struts2/intercepShow.action
结果如下:
任意输入4位长度用户名与密码,登录,即可以显示详细页面。
struts2:拦截器的更多相关文章
- Struts2 拦截器配置以及实现
@(Java ThirdParty)[Struts|Interceptor] Struts2 拦截器配置以及实现 Struts2的拦截器应用于Action,可以在执行Action的方法之前,之后或者两 ...
- struts2 拦截器
拦截器:对Action的访问.可以拦截到Action中某个方法.与过滤器不同,过滤器过滤的是请求.过滤JSP.html.但是拦截器不能拦截jsp.html的访问. Struts2 拦截器在访问某个 A ...
- Struts2拦截器的使用 (详解)
Struts2拦截器的使用 (详解) 如何使用struts2拦截器,或者自定义拦截器.特别注意,在使用拦截器的时候,在Action里面必须最后一定要引用struts2自带的拦截器缺省堆栈default ...
- struts2拦截器
一.自定义拦截器 struts2拦截器类似于servlet过滤器 首先定义一个拦截器这个拦截器实现了Interceptor接口: package cn.orlion.interceptor; impo ...
- Struts2拦截器模拟
前言: 接触Struts2已经有一段时间,Student核心内容就是通过拦截器对接Action,实现View层的控制跳转.本文根据自身理解对Struts2进行一个Java实例的模拟,方便大家理解! 示 ...
- Struts2拦截器初涉
Struts2拦截器初涉 正在练习struts,本例是从一个pdf上摘抄的例子,那本pdf都不知道叫什么名字,不过感觉很适合初学者. 在这里要实现一个简单的拦截器"GreetingInter ...
- 浅谈Struts2拦截器的原理与实现
拦截器与过滤器 拦截器是对调用的Action起作用,它提供了一种机制可以使开发者定义在一个action执行的前后执行的代码,也可以在一个action执行前阻止其执行.同时也是提供了 ...
- 基于SSH2框架Struts2拦截器的登录验证实现(转)
大象在这里假设你已经弄清楚了Struts2拦截器的基本概念,可以进入实际运用了.那么我们在之前的基础上只需要做下小小的改变,就可以使用Struts2的拦截器机制实现登录的验证. 修改数 ...
- struts2拦截器interceptor的三种配置方法
1.struts2拦截器interceptor的三种配置方法 方法1. 普通配置法 <struts> <package name="struts2" extend ...
- Struts2拦截器原理以及实例
一.Struts2拦截器定义 1. Struts2拦截器是在访问某个Action或Action的某个方法,字段之前或之后实施拦截,并且Struts2拦截器是可插拔的,拦截器是AOP的一种实现. 2. ...
随机推荐
- Hibernate SQL 方言(hibernate.dialect)
RDBMS Dialect DB2 org.hibernate.dialect.DB2Dialect DB2 AS/400 org.hibernate.dialect.DB2400Dialect DB ...
- QT中QProcess调用命令行的痛苦经历
在QT程序中需要将某些目录和文件压缩为一个rar的压缩包,于是想到了在QT中通过QProcess类调用命令行的rar.exe来达到效果,但是没想到QProcess类用起来很麻烦,而且达不到效果,折腾了 ...
- Web Api 中返回JSON的正确做法
在使用Web Api的时候,有时候只想返回JSON:实现这一功能有多种方法,本文提供两种方式,一种传统的,一种作者认为是正确的方法. JSON in Web API – the formatter b ...
- 控制反转(Inversion of Control)之我的理解
关于控制反转(Inversion of Control),在具体实现上也有许多其它的叫法,如依赖倒置(Dependency Inversion Principles, DIP).依赖注入(Depend ...
- Helios与Katana的区别
Helios与Katana都是微软开发的基于IIS的OWIN实现. 它们之间的区别很简单:Helios不依赖于ASP.NET Runtime,Katana依赖于ASP.NET Runtime. Hel ...
- JQuery中动态生成元素的绑定事件(坑死宝宝了)
今天在做项目的时候,遇到了一个前端的问题,坑了我好长时间没有解决,今天就记录于此,也分享给大家. 问题是这样的,首先看看我的界面,有一个初始印象: 下面是操作列所对应的JS代码: { "da ...
- .NET面试题大全,包括微软、华为、中兴等大企业的面试真题
简要地写出一个.NET Remoting的示例 [考点].NET Remoting程序的原理,.NET Remoting的基本编写方法.[出现频率]★★☆☆☆[解答]在VS 2008中添加新的类库项目 ...
- SQL Server转发记录指针的坏味道
什么是转发记录指针? 转发记录指针是堆表中特有的数据存储机制. 当你修改了某个数据页中的一行时,如果该行所在的数据页已经无法存放其修改后的行, SQL Server会把这行数据移动到一个新的数据页上面 ...
- 【Android UI设计与开发】9:滑动菜单栏(一)开源项目SlidingMenu的使用和示例
一.SlidingMenu简介 相信大家对SlidingMenu都不陌生了,它是一种比较新的设置界面或配置界面的效果,在主界面左滑或者右滑出现设置界面效果,能方便的进行各种操作.很多优秀的应用都采用了 ...
- [游戏模版17] Win32 推箱子 迷宫
>_<:Here introduce a simple game: >_<:resource >_<:only can push a box and finally ...