背景:Struts1是一个高度成熟的框架,运行效率高,但其致命缺陷在于与JSP/Servlet的耦合非常紧密,因而导致了一些严重问题。其次,Struts1与Servlet API的严重耦合,使应用难以测试;Struts1代码严重依赖Struts1 API,属于侵入式框架。由于其种种局限性,才有了Struts2的诞生。

Struts2与1差别巨大,Struts2以WebWork为核心,采用拦截器的机制处理用户请求,这样的设计使业务逻辑控制器与Servlet API完全脱离开。

Part 1  Struts2快速入门

1. 安装与配置

下载struts-2.3.15.1-all.zip,这里采用该版本,打开后有文件夹:apps 实例代码 ,docs 帮助文档,lib jar包,src 源代码文件;

2.开始写项目

1.添加jar包;(可直接复制实例项目,复制jar)

2.在web.xml中加入struts2的 filter ,内容如下:

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <web-app id="WebApp_9",version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
  3. xmlns:xsi="http://www/w3/org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
  5. http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
  6. <filter>
  7. <filter-name>struts2</filter-name>
  8. <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
  9. </filter>
  10.  
  11. <filter-mapping>
  12. <filter-name>struts2</filter-name>
  13. <url-pattern>/*</url-pattern>
  14. </filter-mapping>
  15.  
  16. <welcome-file-list>
  17. <welcome-file>index.html<welcome-file>
  18. </welcome-file-list>
  19. </web-app>

从配置文件中,可以看出, Struts2 其实就是一个filter

3.在src文件夹下添加struts.xml配置文件

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!DOCTYPE struts PUBLIC
  3. "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
  4. "http://struts.apache.org/dtds/struts-2.3.dtd">
  5.  
  6. <struts>
  7. <package name="default" namespace="/" extends="struts-default">
  8. <action name="index">
  9. <result>/index.jsp</result>
  10. </action>
  11. </package>
  12. </struts>

4. 写jsp页面,或html页面;写java bean, action, dbutils(此实例为简明,省略了这些内容);

最简单的示例,在web文件夹下写 index.jsp

  1. <%@page language="java" import="java.util.*" pageEncoding="UTF-8">
  2. <%
  3. String path=request.getContextPath();
  4. String basePath=request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
  5. %>
  6.  
  7. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
  8.  
  9. <html>
  10. <head>
  11. <base href="<%=basePath%>">
  12. <title>My JSP 'index.jsp' starting page</title>
  13. </head>
  14. <body>
  15. First One
  16. </body>
  17. </html>

测试:部署tomcat或直接使用preview server,http://localhost:port/项目名/index.adtion

注意, .action

Part 2  Struts2工作流程和核心概念

Struts2使用了WebWork的设计核心(XWork),在内部使用拦截器处理用户请求,从而允许用户业务逻辑控制器和ServletAPI分离。Struts2内部是一个MVC架构,Struts2 的核心控制器是FilterDispatcher,客户端发送请求,而经过核心控制器FilterDispatcher处理,根据页面发送的请求,从而确定请求的是哪个action,而action是MVC中的Model,最后确定返回哪个页面(html或jsp)

具体工作流程:

(1)浏览器发送请求;

(2)核心拦截器FilterDispatcher根据请求决定调用合适的action;

(3)拦截器自动对应运用通用功能;

(4)回调用action上的execute()方法;

(5)action的execute()方法处理信息结果输出到浏览器。

2)核心概念:当浏览器发送请求到Servlet容器时,会经历一系列Filter过滤器,这些过滤器包括ActionContextCleanUp,接着FilterDispatcher被调用,通过参考ActionMapper决定一个请求和一个Action关联。FilterDispatcher参考框架的配置文件管理,ActionProxy生成一个ActionInvocation,它负责执行命令,并负责查找适当的结果以和struts.xml中的action result相比较,调用一个在JSP或FreeMarker中绘制的模板。而Action是需要与struts.xml配置文件一起结合使用的,下面将详细讲述配置文件使用:

[1] struts.xml文件配置

先来个实例:

login.jsp

  1. <%@page language="java" import="java.util.*" pageEncoding="utf-8"%>
  2.  
  3. <%
  4. String path=request.getContextPath();
  5. String basePath=request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
  6. %>
  7.  
  8. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
  9.  
  10. <html>
  11. <head>
  12. <base href="<%=basePath%>">
  13. <title></title>
  14. </head>
  15. <body>
  16. <form action="login" method="post">
  17. 用户名:<input type="text" name="uname"></br>
  18. 密码:<input type="password" name="pwd"></br>
  19. <input type="submit" value="登录">
  20. </form>
  21. </body>
  22. </heml>

LoginAction类

  1. public class LoginAction{
  2. private String uname;
  3. private String pwd;
  4. public String getUname(){
  5. return uname;
  6. }
  7. public void setUname(String uname){
  8. this.uname=uname;
  9. }
  10. public String getPwd(){
  11. return pwd;
  12. }
  13. public void setPwd(String pwd){
  14. this.pwd=pwd;
  15. }
  16. public String excute(){
  17. if("JokerJason".equals(uname)&&"12345".equals(pwd)){
  18. return "success";
  19. }
  20. return "fail";
  21. }
  22. }

注意:在上述LoginAction中,属性uname和pwd必须和页面保持一致,这是因为在Struts2中提供属性参数及set/get方法通过ioc的方式将页面参数注入到Action类里。

写完Action类,对其进行配置,在src目录下创建struts.xml文件,如下

  1. <struts>
  2. <package name="default" namespace="/" extends="struts-default">
  3. <action name="login" class="LoginAction">
  4. <result name="success">success.jsp</result>
  5. <result name="fail">fail.jsp</result>
  6. </action>
  7. </package>
  8. </struts>

(1)package: 包在java中是用来分类的,在Struts2中,也是用来分类的,在Struts2的配置文件中,一个文件可以有多个包;

package有很多属性,name是包名,namespace是命名空间,如果访问一个Action,则一定要是namespace+actionname;

如本例中,要访问LoginAction,则必须是:http://localhost:8080/项目名/login;最后的login就是namespace+action;

extends指定继承哪个Struts的组件,通常都是继承struts-default才能使用Struts中组件。当然如果想使用JSON,就需要继承JSON-default;

(2)action:action是核心控制器FilterDispatcher将要访问的具体action,name指定的是action的名称,class指定的是具体类名,通常是包名+类名;

(3)result:指的是返回的结果页面,name指定返回结果,在实际路径页面中一定要加"/"

[2]Action对象详解

Struts2中Action无须实现任何接口和任何类型,但是为了方便实现Action,大多数情况下采用下面两种方式对Action进行处理:

(1)继承com.opensymphony.xwork2.ActionSupport;

(2)实现com.opensymphony.xwork.Action;

默认情况下,都需要重载(Override)或者覆写(Overload)其中的String excute()throws exception方法。

下面对上面实例进行修改,两个环节进行:

1.将LoginAction继承ActionSupport

  1. import com.opensymphony.xwork2.ActionSupport;
  2.  
  3. public class LoginAction extends ActionSupport{
  4. private String uname;
  5. private String pwd;
  6. public String getUname(){
  7. return uname;
  8. }
  9. public void setUname(String uname){
  10. this.uname=uname;
  11. }
  12. public String getPwd(){
  13. return pwd;
  14. }
  15. public void setPwd(String pwd){
  16. this.pwd=pwd;
  17. }
  18. public String execute(){
  19. if("jokerjsaon"equals(uname)&&"1234"equals(pwd)){
  20. return "fail";//与struts.xml中配置的result相同
  21. }
  22. }
  23. }

2.在struts.xml中进行配置

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!DOCTYPE struts PUBLIC
  3. "-//Apache SoftWare Foundation//DTD Struts Configuration 2.3//EN "
  4. "http://struts.apache.org/dtds/struts-2.3.dtd">
  5. <struts>
  6. <package name="default" namespace="/" extends="struts-default">
  7. <action name="login" class="LoginAction">
  8. <result name="success">success.jsp</result>
  9. <result name="fail">fail.jsp</result>
  10. </action>
  11. </package>
  12. </struts>

这样修改并未看到太大变化,反而会因为继承一个ActionSupport类增加了累赘,但,先看一下Action接口的实现方式:

  1. package com.opensymphony.xwork2;
  2. public interface Action{
  3. public static final String SUCCESS="success";
  4. public static final String NONE="none";
  5. public static final String ERROR="error";
  6. public static final String INPUT="input";
  7. public static final String LOGIN="login";
  8. public String execute()throws Exception;
  9. }

表面上看实现Action接口没有什么好处,事实上实现改接口,有利于更好的实现Action类。Action接口中定义了五个字符串常量,因为ActionSupport是Action的实现类,所以继承了ActionSupport也就可以使用这五个常量了:如下

  1. import com.opensymphony.xwork2.ActionSupport;
  2.  
  3. public class LoginAction extends ActionSupport{
  4. private String uname;
  5. private String pwd;
  6. public String getUname(){
  7. return uname;
  8. }
  9. public void setUname(String uname){
  10. this.uname=uname;
  11. }
  12. public String getPwd(){
  13. return pwd;
  14. }
  15. public void setPwd(String pwd){
  16. this.pwd=pwd;
  17. }
  18. public String execute(){
  19. if("jokerjsaon"equals(uname)&&"1234"equals(pwd)){
  20. return ERROR;//注意此处
  21. }
  22. }
  23. }

Part 3 Struts2配置文件

 1.   Struts的配置文件类型

Struts2的配置文件分为内部使用和供开发人员使用两大类,内部配置文件由Struts2框架自动加载,对其自身进行配置,其他的配置文件由开发人员使用,用于对Web应用进行配置。Struts2所需的配置文件如下表:

文件 位置 用途
web.xml /WEB-INF/ Web部署描述文件 
struts.xml /WEB-INF/classes 包含result映射,action映射,拦截器配置等
struts.properties /WEB-INF/classses 与struts.xml作用一样,不同的配置文件罢了
struts-default.xml /WEB-INF/lib/struts-core.jar Struts2提供的默认配置,由框架提供
struts-plugin.xml  /WEB-INF/lib/struts-xxx-plugin.jar Struts2框架插件所提供的配置文件

下面对核心内容进行解释:

[1]  struts.xml配置文件:是该框架的核心配置文件,用于配置和管理开发人员编写的Action,在这个配置文件中,开发人员可以配置作用于Action的拦截器,Action和result的映射等。

[2]struts-default.xml: 基础配置文件,为框架提供默认设置,该文件包含在struts2-core-2.x.jar中,由框架自动加载。其会被自动包含在struts.xml中,以提供标准的配置设置而不需要复制其内容:

  1. <package name="default" extends="struts-default"/>

(其内容包括Servlet转发,Servlet重定向,FreeMarker模板输出,XSTL渲染,内置拦截器和不同拦截器组成的拦截器栈等等)

2. Struts2的包配置

               Struts2中的包类似于java中的包,提供了将action,result,拦截器和拦截器栈组织为一个逻辑单元的一种方式。Struts2中的包可以扩展另外的包,从而继承原有包的所有定义,并可以添加自己包的特有配置,以及修改原有包的部分配置。在struts.xml中庸package定义包,下面为属性:

+   name:(必须) 被其他包引用的key(键);

+   extends: (不必须) 指定需要扩展的包(如果需要扩展多个包,用","逗号隔开,父包必须在子包前面) ;

+   namespace:(不必须) 指定命名空间;

+   abstract :(不必须) 声明包为抽象(这样包内不能再有action的定义,比如前面struts-default.xml就是抽象包,可以使用抽象包进行一些默认配置,其他包继承以减少工作量);

实例:

  1. <package name="default" extends="struts-default">
  2. <action name="login" class="LoginAction">
  3. <result name="success">/success.jsp</result>
  4. <result name="error">/error.jsp</result>
  5. </action>
  6. </package>
  7. <package name="test" extends="default" namespace="/my">
  8. </package>

当发起/my/login.action的路径请求时,会先在test包内查找是否有合适的action,而在此时是在test包中存在LoginAction处理请求,因为test包继承了default包,某种意义上包的extends相当于java的extends。

 3.  名称空间配置

package的namespace属性可以将包中的action配置为不同的名称空间,这样在不同名称空间中可以使用同名action。Struts2框架使用action名字和它所在的名称空间来标识一个action

当Struts2接收到一个请求时,它会将请求URL分为namespace和action名字两个部分,然后Struts2从struts.xml中查询namespace/action这个命名对,如果没有找到,就会在默认的名称空间搜索相应的action名。默认名称空间用空字符串" "表示,如果在定义包时没有使用namespace,就指定了默认名称空间。

此外,Struts2还支持以"/"命名的根名称空间,如果直接请求Web应用上下文路径下的action,那么框架会在根名称空间查找相应的action,如果没有找到就在默认名称空间查找:

  1. <!--default包在默认名称空间中-->
  2. <package name="default" extends="struts-default">
  3. <action name="foo" class="LoginAction">
  4. <rfesult name="success">foo.jsp</result>
  5. </action>
  6. <action name="bar" class="LoginAction"></action>
  7.  
  8. <!--mypackage1包在根名称空间里-->
  9. <package name="mypackage1" namespace="/">
  10. <action name="moo" class="LoginActionTwo">
  11. <result name="success">/moo.jsp</result>
  12. </action>
  13. </package>
  14.  
  15. <!--mypackage2包在/accp名称空间中-->
  16. <package name="mypackage2" namespace="/accp">
  17. <action name="foo" class="LoginActionThree">
  18. <result name="success">/foo2.jsp</result>
  19. </action>
  20. </package>

当发起请求/moo.action时,框架会在根空间('/')查找moo.action,如果没有找到再在默认空间查找,此例中Mypackage中存在moo.action,因此它会被执行,结果转向moo.jsp。

 4. Action相关配置

struts2的核心功能是Action,对于开发人员来说,使用struts2框架主要的工作就是编写action类。Action类一般都要实现Action接口,并实现接口中的execute()方法:签名如下:

  1. public String execute()

Struts2并不要求自己编写的Action类一定实现Action接口,也可以编写普通java类作为Action,只要此类提供一个返回类型为String的无参public方法:

  1. public String xxx()

实际开发中,Action类很少使用Action接口,通常都是继承ActionSupport类。

开发好Action后,在struts.xml配置,以告诉Struts2框架,针对某个URL的请求应该交给哪个Action处理。

struts.xml中action元素属性如下:

+ name  必须   Action名称,用于匹配请求;

+ class   非必须   Action实现类的完整类名

+ method   非必须  执行Action调用的方法;

+ converter  非必需   应用于Action的类型转换器的完整类名;

! 注意 : 在为Action取名时,默认情况下不许出现斜杠("/"),如果必须使用,例如<action name="book/manage" class="LoginAction">,就需要在struts.xml中加入: <constant name="struts.enable.SlashesInActionNames" values="true"> 

                      此外,不在取名中使用"_"和"."避免一些莫名其妙的问题!

   前面讲述了在Struts2中可以使用一个普通的java类作为Action类,而且在此类中的方法没有特殊要求,对于此点Struts2如何处理?其实Action中有一个method属性可以自定义方法,而不需要使用默认的excute()方法。

例如在一个新闻发布系统中,对新闻有四种操作,添加,修改,删除,查询。在具体实现中,为了节约Action数量,通常在一个Action中编写四个方法实现CURD操作:

  1. public class CurdAction(){
  2. public String addNews(){return SUCCESS;}
  3. public String deleteNews(){return SUCCESS;}
  4. public String updateNews(){return SUCCESS;}
  5. public String selectNews(){return SUCCESS;}
  6. }

现在的问题是,如何才能让框架在不同请求到达时,去调用CurdAction里面的相应方法呢?在执行Action时,默认的调用方法是execute()方法。Action中的method属性可以指定不同的方法,如下配置:

  1. <package name="default" extends="struts-default">
  2. <!--请求/list时,调用CurdAction类上的selectNews方法-->
  3. <action name="list" class="CurdAction" method="selectNews">
  4. <result>/list.jsp</result>
  5. </action>
  6. <action name="edit" class="CurdAction" method="editNews">
  7. <result>/edit.jsp</result>
  8. </action>
  9. <action name="delete" class="CurdAction" method="deleteNews">
  10. <result>/delete.jsp</result>
  11. </action>
  12.  
  13. <action name="other" class="CurdAction">
  14. <result>/edit.jsp</result>
  15. </action>
  16. </package>

Struts2在根据Action元素的method属性查找方法时有两种途径:

+ 查找与method属性值完全一致的方法;

+ 查找doMethod()形式的方法;

在上例中,当请求/list时,Struts2首先查找selectNews()方法,如果找不到,则继续查找名为doCreate()的方法;

    [另外一种无须配置就可以直接调用Action中的非execute()方法的方式,就是直接使用struts2动态方法DMI,语法如下

  1. actionName!methodName.action

例如:

  1. <action name="list" class="action.CurdAction">
  2. ...
  3. </action>

当发起/list!selectNews.action时,将调用CurdAction类中的selectNews方法或doSelectNews().

注意:DIM存在安全隐患,可以在struts.xml中配置禁止使用:

  1. <constants name="struts.enable.DynamicMethodInvocation" value="false"/>

    ]

5.通配符简化配置

通常来说,应用越大,action配置数量越多,通过使用通配符,可以将一些相似的mapping绑在一起,用一个通用的mapping表示。

优势:大大减少配置文件内容;

劣势:可读性差;

使用原则:约定高于配置;在项目中,很多命名规则是约定的,使用通配符必须有一个约定,如下

  1. <action name="User_*" class="action.UserAction method="{1}"">
  2. <result>/{1}success.jsp</result>
  3. </action>

*表示匹配所有,在struts2中,{1}表示第一个*号。

此时如果UserAction里面有100个方法,只需要配置一次即可;但是如果有多种Action类,就需要如下修改:

  1. <action name="*_*" class="action.{1}Action" method="{2}">
  2. <result>/{1}_{2}_success.jsp</result>
  3. </action>

 注意:在开发前,约定优先于配置,大大降低工作量。

   

    6.返回结果的配置

         一个result代表了一个可能的输出。当Action类的方法执行完成后,返回一个字符串类型的结果码,框架根据这个结果选择对应的result向用户输出。

        result配置由两部分组成:(位于struts.xml中)

              + result映射

              + result类型

        result的属性如下:

属性 必要性 说明
name 指定result的逻辑名
type 指定result的类型,不同类型的result代表了不同类型的输出结果

具体配置方法有三种:

+ 最复杂的配置:

  1. <package name="default" namespace="/" extends="struts-default">
  2. <action name="login" class="action.LoginAction">
  3. <result name="success" type="dispatcher">
  4. <param name="location">/success.jsp</param>
  5. </result>
  6. </action>
  7. </package>

+ 精简版

  1. <package name="default" namespace="/" extends="struts-default">
  2. <action name="login" class="action.LoginAction">
  3. <result name="success">
  4. <param name="location">/success.jsp</param>
  5. </result>
  6. </action>
  7. </package>
  8.  
  9. <!--这里没有设定type属性,因为默认为dispatcher-->

+简化版

  1. <package name="default" namespace="/" extends="struts-default">
  2. <action name="login" class="action.LoginAction">
  3. <result name="success">/success.jsp
  4. </result>
  5. </action>
  6. </package>

上述的dispatcher是什么?下面看struts2-core.jar包下面的struts-default.xml,发现如下配置

  1. <result-types>
  2. <result-type name="chain" class="com.opensymphony.xwork2.ActionChainResult"/>
  3. <result-type name="dispatcher" class="org.apache.struts2.dispatcher.ServletDispatcherResult" default="true"/>
  4. <result-type name="freemarker" class="org.apache.struts2.views.freemarker.FreemarkerResult"/>
  5. <result-type name="httpheader" class="org.apache.struts2.dispatcher.HttpHeaderResult"/>
  6. <result-type name="redirect" class="org.apache.struts2.dispatcher.ServletRedirectResult"/>
  7. <result-type name="redirectAction" class="org.apache.struts2.dispatcher.ServletActionResult"/>
  8. <result-type name="stream" class="org.apache.struts2.dispatcher.StreamResult"/>
  9. <result-type name="velocity" class="org.apache.struts2.dispatcher.VelocityResult"/>
  10. <result-type name="xslt" class="org.apache.struts2.views.xslt.XSLTResult"/>
  11. <result-type name="plainText" class="org.apache.struts2.dispatcher.PlainTextResult"/>
  12. </result-types>

这些配置就代表了struts2中所有的result配置类型.

Struts2框架调用Action对请求处理后,就要向用户呈现一个结果视图。Struts2支持多种类型的视图,由不同的结果类型来管理。一个结果类型就是实现了com.opensymphony.xwork2.Result接口的类。

Strut2中预定义了多种结果类型,如下图:

结果类型 说明
chain 用于Action链式处理
dispatcher 用于web资源的集成,包括JSP的集成
freemarker 用于FreeMarker的集成
httpheader 用于控制特殊的HTTP行为
redirect 用于重定向到另外的URL(web资源)
redirectAction 用于重定向到另外的action映射
stream 用于向浏览器返回一个InputStream(用于文件下载)
velocity 用于velocity集成
xslt 英语XML/XSLTWYS DN
plaintext 用于显示某个特定页面(如jsp,html的原始内容)
   

                              下面对常见的result配置类型详细介绍:

                (1)dispatcher结果类型

最常见的结果类型主要是dispatcher类型,此结果类型也是要struts2中默认的结果类型。Struts2在后台使用Servlet API的RequestDispatcher来转发请求,因此在用户的整个请求过程中,目标Servlet API接收的request/response对象始终是同一个。Dispatcher结果类型实现类为ServletDispatcherResult,该类有两个属性:location和param.这两个属性通过struts.xml中的result元素的param子元素设置。如下配置:

  1. <result name="success" type="dispatcher">
  2. <param name="location">/success.jsp</param>
  3. <param name="parse">true</param>
  4. </result>

location参数用于指定action执行完毕后要转向的目标资源,location是默认的参数,可以不用给出.

parse用于指定是否能够解析location参数中的OGNL表达式。如果为false则不解析,默认为true.如下:

实例:一个新闻系统,每个新闻一个id,当用户点击新闻链接,一个带id参数的请求发送到Action类里,Action处理完后转跳到view.jsp

  1. <action name="view" class="ViewAction">
  2. <result name="success" type="dispatcher">
  3. <param name="location">/view.jsp?id=${id}</param>
  4. <param name="parse">true</param>
  5. </result>
  6. </action>

(2) redirect结果类型

在一次用户交互中,存在两次请求,一次是客户端发送给服务器,服务器sendRedirect(),然后客户端第二次访问redirect后的目标资源。这就意味着在目标资源中不能访问Action实例,解决方案如下:               +   数据保存在session里;

+   通过请求参数来传递;

如:用户登录页面里,登陆成功后使用redirect结果类型将其重定向到欢迎页面,在欢迎页面中显示出来。采取第二种方法:

  1. <action name="login" class="LoginAction">
  2. <resulttype="redirect">x.jsp?username=${username}</result>
  3. </action>

如果LoginAction里username属性值为JokerJason,则重定向后浏览器中显示的URL地址为hhtp://localhost:8080/..../x.jsp?username=JokerJason

(注意:加密处理)

(3) redirectAction结果类型

redirectAction与redirect的后台原理是一样的,都是利用HttpServletResponse的sendRedirect方法将请求重定向到指定的URL,那么两者的区别呢?

    (正在更新)

Struts2 技术全总结 (正在更新)的更多相关文章

  1. 中国.NET:各地微软技术俱乐部汇总(持续更新中...)

    中国.NET:各地微软技术俱乐部汇总(持续更新中...)   本文是转载文,源地址: https://www.cnblogs.com/panchun/p/JLBList.html by ​史记微软. ...

  2. RAID技术全解图解-RAID0、RAID1、RAID5、RAID100【转】

    图文并茂 RAID 技术全解 – RAID0.RAID1.RAID5.RAID100…… RAID 技术相信大家都有接触过,尤其是服务器运维人员,RAID 概念很多,有时候会概念混淆.这篇文章为网络转 ...

  3. RAID 技术全解

    图文并茂 RAID 技术全解 – RAID0.RAID1.RAID5.RAID100-- RAID 技术相信大家都有接触过,尤其是服务器运维人员,RAID 概念很多,有时候会概念混淆.这篇文章为网络转 ...

  4. Java基础面试题(史上最全、持续更新、吐血推荐)

    文章很长,建议收藏起来,慢慢读! 疯狂创客圈为小伙伴奉上以下珍贵的学习资源: 疯狂创客圈 经典图书 : <Netty Zookeeper Redis 高并发实战> 面试必备 + 大厂必备 ...

  5. SpringBoot面试题 (史上最全、持续更新、吐血推荐)

    文章很长,建议收藏起来,慢慢读! 疯狂创客圈为小伙伴奉上以下珍贵的学习资源: 疯狂创客圈 经典图书 : <Netty Zookeeper Redis 高并发实战> 面试必备 + 大厂必备 ...

  6. 消息队列面试题、RabbitMQ面试题、Kafka面试题、RocketMQ面试题 (史上最全、持续更新、吐血推荐)

    文章很长,建议收藏起来,慢慢读! 疯狂创客圈为小伙伴奉上以下珍贵的学习资源: 疯狂创客圈 经典图书 : <Netty Zookeeper Redis 高并发实战> 面试必备 + 大厂必备 ...

  7. Linux面试题(史上最全、持续更新、吐血推荐)

    文章很长,建议收藏起来,慢慢读! 疯狂创客圈为小伙伴奉上以下珍贵的学习资源: 疯狂创客圈 经典图书 : <Netty Zookeeper Redis 高并发实战> 面试必备 + 大厂必备 ...

  8. Netty 面试题 (史上最全、持续更新)

    文章很长,建议收藏起来,慢慢读! 疯狂创客圈为小伙伴奉上以下珍贵的学习资源: 疯狂创客圈 经典图书 : <Netty Zookeeper Redis 高并发实战> 面试必备 + 大厂必备 ...

  9. Moon.Orm3.8技术全攻略

    Moon.ORM技术全攻略  一.绪论 本文主要是针对Moon.ORM的技术的讨论及其使用使用指导.如有其它疑问,请留言.本文主要针对Moon.ORM3.9版本,同时将会对4.0做一个技术预览.本文从 ...

随机推荐

  1. MFC 点击改变文本 加法计时器 伸缩窗体

    1.添加所需控件,设置ID:labNum1,txtNum1.txtNum2.txtNum3.btnAdd,并将labNum1的属性Notify->true(控件在被单击或双击时可以发送消息) 2 ...

  2. uva 12626 - I ❤ Pizza

    #include <iostream> #include <cstdio> #include <string> #include <algorithm> ...

  3. C++ 知识点1

    typedef的陷阱 严格来说typedef并不是定义别名,而是定义类型,比如typedef int a;按照大部分书本说来,就是把a看做int,这种说法初学看来是正确的,也易于理解,但是遇到type ...

  4. SVG基础

    可缩放矢量图形(Scalable Vector Graphics)是基于可扩展标记语言(标准通用标记语言的子集),用于描述二维矢量图形的一种图形格式.它由万维网联盟制定,是一个开放标准.SVG 是使用 ...

  5. lnmp源码安装以及简单配置

    nginx 软件: a: openssl-1.0.1r.tar.gz tar zxf openssl-1.0.1r.tar.gz b: pcre-8.32.tar.gz tar zxf openssl ...

  6. ECSTORE日期时间控件转换为时间戳的方法

    如果你在后台使用<{input type=”time” name=”time”}>的话,后台获取到的表单数据为: ["_DTYPE_TIME"]=> array( ...

  7. JQ点击列表显示隐藏

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  8. php随机抽奖

    貌似有些不合理,麻烦大家帮忙指正指正!谢谢~ <?php header("content-type:text/html;charset=utf-8"); function g ...

  9. ubuntu下安装phpstrom

    安装JAVA环境包1,下载 java 的 JDK 包,去官网下载(http://www.oracle.com/technetwork/java/javase/downloads/index.html) ...

  10. Nexus Root Toolkit教程——刷机

    Nexus Root Toolkit是Nexus系列设备专属解锁.root.刷机.修复工具.本教程以Nexus7二代刷安卓5.0 Lollipop系统为实例演示刷机过程. 标签: 安卓5.0刷机教程 ...