流程介绍


我们模拟一个请求/响应的情景,来介绍Struts的工作流程。注意,下面的序号和图中的序号没有严格的对应关系。

  1. 浏览器向系统发出请求,请求的地址是ac.action
  2. 请求被StrutsPreparedExecuteFilter拦截,去掉.action后缀,所得结果ac作为action的name。
    在Struts框架中,负责处理用户请求的称为action,这里的name用于获取action,找到他,让他干活。
  3. StrutsPreparedExecuteFilter在struts.xml中查找action映射相关的配置,根据ac查到action的类pkg.AcAction。
  4. StrutsPreparedExecuteFilter实例化pkg.AcAction,并调用其execute方法。
  5. pkg.AcAction工作完成之后,汇报工作结果:返回一个字符串success,称之为result。
  6. StrutsPreparedExecuteFilter使用success去查struts.xml中的结果映射部分,获取到对应的物理视图资源是ac-success.jsp。
  7. StrutsPreparedExecuteFilter使用forward的方式,将ac-success.jsp展示给用户。

仔细看一下上面的图和内容,在脑海中回忆一下整个流程,最好能够闭眼将整个流程复述一遍,然后再继续。

我们的工作

在上述的流程描述中,几乎都是框架要做的事,但是为了能让框架顺利的工作,我们要提供支持性的工作。使用框架基本都是这样,我们按照框架的模式提供支持,框架自行工作。
接下来看一下我们需要做的事:

  1. 配置StrutsPreparedExecuteFilter。
    StrutsPreparedExecuteFilter是整个流程中的核心,这个指挥中心不是自行启动的,我们需要在web.xml中启动它。这件事只需要做一次。
  2. 创建Action类
    action负责处理用户的请求,具体怎么处理,需要我们创建一个Action类来实现。
  3. 创建视图
    Action实现之后,我们要考虑返回怎样的视图给用户。在这里,我们需要创建1到多个jsp文件,担任视图的角色。
  4. 配置action映射
    配置name和class的对应关系,让Struts知道该把哪些请求分派给哪个action。
  5. 配置result映射
    Action返回的是一个普通的字符串,我们称之为处理结果或者逻辑视图,不管叫什么,总之它不是物理视图,不指定任何视图文件。Struts为了将Action类和视图文件解耦,将返回结果和物理视图的对应关系,我们称之为result映射,在配置文件中配置。

上面五个工作,第一个只需要做一次,相对的,后面四个每创建一个action都需要做一次。

在上面五个工作中,视图文件是jsp,我们将之视为基本知识,并不打算介绍。result映射一般是在action映射内部配置的,所以配置result将包含在配置actioin中。所以,我计划分下面三个主题,介绍上面的工作:

  1. 配置核心过滤器
  2. 创建Action
  3. 配置action

1.配置核心过滤器


这里使用Maven管理项目,如果要使用Struts框架,你需要引入依赖。你可以在http://mvnrepository.com/中输入struts2-core来查找可用的版本,从中选择一个并获取其依赖配置:

<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-core</artifactId>
<version>2.3.28</version>
</dependency>

在web.xml中配置下面的内容:

 <filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

2.创建Action


2.1.参数获取

既然要在Action中处理用户请求,那么Action就需要获取用户的请求参数。我们需要为此在Action中添加对应的属性,属性的name和请求参数的name一致,类型是基本类型;另外,我们要为这个属性添加setter方法。
如果为Action的属性提供getter方法,在jsp可以从request的属性中获取该属性。

2.2.创建Action

有三种方式可以创建Action。
  1. POJO
    Action不需要实现任何接口,不需要继承任何类,但是需要包含一个方法:public String execute() throws Exception。这个方法是处理请求的入口,由Struts框架调用。这个方法的名字可以自行定义,但是execute是默认的名字,使用这个可以省去一项属性配置。
  2. 实现Action接口
    全称com.opensymphony.xwork2.Action,这个接口定义了几个字符串常量,作为result;还定义了execute方法。
  3. 继承ActionSupport
    全称com.opensymphony.xwork2.ActionSupport,实现了Action。

2.3.demo设计

为了介绍上面3种方式,这里设计一个demo。

以登录为例,用户填写账号和密码,提交登录请求。Action对账号密码进行权限验证,通过则跳转到首页,否则依旧跳转到登录页面。
所以对于Action来说,就是获取请求参数:账号、密码。判断账号是否存在,密码是否正确。如果通过返回一个"success"的逻辑结果,否则返回"login"的逻辑结果。
为了添加一点人性化的元素,我们将区分“账号不存在”和“密码错误”两种情况,并分别进行提示。
好了,我们开始吧。

2.3.1.POJO

 package cn.ljl.note.struts2.login.actions;

 public class LoginPOJO {
private static final String VALID_USER = "admin";
private static final String VALID_PWD = "admin"; private static final String SUCCESS = "success";
private static final String LOGIN = "login"; private String username;
private String password;
private String tip; public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getTip() {
return tip;
}
public void setTip(String tip) {
this.tip = tip;
} public String execute() throws Exception {
boolean validUser = VALID_USER.equals(getUsername());
boolean validPwd = VALID_PWD.equals(getPassword()); if (!validUser) {
setTip("用户不存在!");
return LOGIN;
} if (!validPwd) {
setTip("密码不正确!");
return LOGIN;
} setTip(null);
return SUCCESS;
}
}

2.3.2.实现Action接口

Action接口的类图如下:

源代码:

 package cn.ljl.note.struts2.login.actions;

 import com.opensymphony.xwork2.Action;

 public class LoginAction implements Action{
private static final String VALID_USER = "admin";
private static final String VALID_PWD = "admin"; private String username;
private String password;
private String tip; public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getTip() {
return tip;
}
public void setTip(String tip) {
this.tip = tip;
} @Override
public String execute() throws Exception {
boolean validUser = VALID_USER.equals(getUsername());
boolean validPwd = VALID_PWD.equals(getPassword()); if (!validUser) {
setTip("用户不存在!");
return LOGIN;
} if (!validPwd) {
setTip("密码不正确!");
return LOGIN;
} setTip(null);
return SUCCESS;
} }

LoginAction

2.3.3.继承ActionSupport类

com.opensymphony.xwork2.ActionSupport是一个复杂的类,它提供了很多其他的功能,而这些我们目前还不需要关注。所以这里只要把它当成Action接口的默认实现类就好了,这里也不再贴出其类图。
demo的源代码:
 package cn.ljl.note.struts2.login.actions;

 import com.opensymphony.xwork2.ActionSupport;

 public class LoginActionSupport extends ActionSupport {

   private static final long serialVersionUID = 8451980703294866793L;

   private static final String VALID_USER = "admin";
private static final String VALID_PWD = "admin"; private String username;
private String password;
private String tip; public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getTip() {
return tip;
}
public void setTip(String tip) {
this.tip = tip;
} @Override
public String execute() throws Exception {
boolean validUser = VALID_USER.equals(getUsername());
boolean validPwd = VALID_PWD.equals(getPassword()); if (!validUser) {
setTip("用户不存在!");
return LOGIN;
} if (!validPwd) {
setTip("密码不正确!");
return LOGIN;
} setTip(null);
return SUCCESS;
} }

LoginActionSupport

2.4.三种方式的比较

比较上述三种方式的源代码,大部分代码都是重复的。实现Action接口或者继承ActionSupport类,可以直接使用已经定义好的逻辑结果,而这些一般是比较常用的。
通过继承ActionSupport来开发Action,这是建议的方式。

3.配置action


3.1.配置文件

Struts2的常规配置文件是struts.xml,这个文件放在源文件夹的根目录。比如使用maven,应该把它放在src/main/resources下。
配置文件的结构像下面这样:
 <?xml version="1.0" encoding="GBK"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd">
<struts> </struts>
其中,文档声明中的版本号与当前使用的struts2的版本有关。也可以从struts2-core相关jar包中拷贝。
下面将要介绍的内容,基本是在这里配置的,否则会特别说明。另外,如果你修改了这里的配置,编译部署之后,需要重启服务器。

3.2.命名空间

一次请求的地址,像这个样子:

http://localhost:8080/note-struts2/login/check.action
在Struts2看来,/login称为命名空间;check称为action-name;.action是后缀,在解析的时候会自动去掉。
命名空间可以多级,就像目录结构一样,一层层;action-name就像是文件名。
在struts.xml中,使用<package>的namespace属性来指定命名空间,所以action的定义都是在<package>下定义的。比如,我们可以这样定义:
<package name="login" extends="struts-default" namespace="/login">
......
</package>
上述代码片段,涉及到3个package属性:
  • name
    name唯一标识一个package
  • extends
    package有继承的特性,使用extends指定另一个package的name,就会继承彼package下所定义的内容。
    这里继承的struts-default是在struts2-core的struts-default.xml中定义的。通常,建议继承struts-default。
  • namespace
    配置命名空间。

默认的命名空间

namespace不是必需的属性,如果没有配置,那就是默认的命名空间。默认的命名空间有特殊的作用:如果在请求的URL中解析出来的命名空间里找不到对应的action,就到默认的命名空间里找。默认命名空间是一个抽象的概念,不是默认值,你不能说“我可以通过配置namespace等于默认值,来指定默认命名空间”。比如"/"被称为根命名空间,但是它不是默认命名空间,它也没有任何特殊的性质,就和其他命名空间一样。

3.3.action

即配置action映射,struts框架需要查找这个映射,才能根据URL找到实际的处理Action。action是在<package>元素内配置的,下面是一个demo:

<action name="check" class="cn.ljl.note.struts2.login.actions.LoginActionSupport" method="execute">
......
</action>
<action>元素有3个基本的属性:
  • name
    它同时也是action的url请求地址的一部分,同一个命名空间下,action的name要唯一
  • class
    它是Action类,负责处理用户的请求。这是一个非必需的属性,默认为com.opensymphony.xwork2.ActionSupport;你可以看下这个类的execute方法,只是直接返回SUCCESS。
  • method
    它是Action的方法名,对于框架来说,相当于回调方法。框架会调用这个方法,以达到通知请求到达的效果。这是一个非必需的属性,默认值为execute,所以上面的demo完全不用配置这个属性。

3.4.result

即配置result映射,根据这个映射,struts框架才能根据Action返回的逻辑结果(字符串)找到对应的视图资源。result是在<action>元素内配置的,下面是一个demo:

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

<result>元素的属性name代表Action返回的逻辑结果;<result>体的内容,代表物理视图的路径。其中name的默认值是"success",所以第1行不用配置name属性。

3.5.异常

在Action中出现异常,可能希望根据不同的异常类型跳转到不同的物理视图。
结合Struts2框架的工作流程,我们可以Action中捕获异常,根据不同的类型返回不同的字符串,并在struts.xml中根据这些返回的结果配置不同的物理视图。比如我们可能会这样写Action的方法:
 public String execute() {
try {
// ...
} catch(异常1 e1) {
return 结果1;
} catch(异常2 e2) {
return 结果2;
}
}

然后我们会在struts.xml中这样配置result映射:

<result name="结果1">视图1.jsp</result>
<result name="结果2">视图2.jsp</result>

这样是可以的,实际上在我们已知的知识上,想到这种方式来解决新的问题,能体现我们是会灵活变通的。不过Struts也提供了正统的配置方法,让我们只需要配置异常和返回结果的映射关系,而不需要捕获Action处理方法中抛出的异常。

3.5.1.异常映射

在<action>元素下,使用<exception-mapping>元素来配置,下面上一个demo:

<result name="exception">/exception/exception.jsp</result>
<exception-mapping result="exception" exception="java.lang.Exception" />
这个demo的意思是,如果处理方法抛出了java.lang.Exception异常,就返回"exception"的逻辑结果,它对应的物理视图是/exception/exception.jsp。
<exception>有两个属性:
  • result
    对应的异常类型发生时,要返回什么逻辑结果
  • exception
    配置什么类型的异常
留两个有趣的问题:
  1. 配置的异常类型,对其子类型异常是否有效?
  2. 两种异常类型(继承关系)配置的先后顺序,对异常抛出的返回结果是否有影响?
    抛出的异常可以是父类型、子类型、两者的子类型。
这两个是比较细节、相对啰嗦的问题,我不喜欢这样的问题,实际遇到的时候,我会顺手测一下,但是目前,我还不关心它们的答案。

3.5.2.拦截器

我们虽然提供了异常到逻辑结果的映射,但是还需要一个拦截器来做这样的工作:拦截抛出的异常,查映射关系,改为返回对应的逻辑结果。这样的拦截器已经在struts-default中使用了,所以只需要保证定义的<package>,直接或间接的继承了struts-default就好了

3.5.3.输出异常

我们可以在jsp中使用el来输出异常,像这样${exception }。不过,Struts2也提供了相关的标签,下面是一个demo:

 <%@ page language="java" contentType="text/html; charset=GBK"
pageEncoding="GBK"%>
<%@ taglib uri="/struts-tags" prefix="s" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<body>
<s:property value="exceptionStack"/>
</body>
</html>
line 3,引入了struts的标签库,定义了前缀为s。
line 7,使用<property>标签,输出了异常的堆栈信息。
<property>标签在用于输出异常信息是,value属性有下面几个选择:
  • exception
    输出异常本身,相当于${exception }
  • exception.message
    输出异常的信息,相当于${exception.message }
  • exceptionStack
    输出异常的堆栈信息,正是demo中所用到的。

3.6.总结

好了,让之前出现过的几位也上来吧,我们来张合照:struts.xml

 <?xml version="1.0" encoding="GBK"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
<package name="login" extends="struts-default" namespace="/login">
<action name="check" class="cn.ljl.note.struts2.login.actions.LoginActionSupport">
<result name="success">/index.jsp</result>
<result name="login">/login/login.jsp</result>
<result name="exception">/exception/exception.jsp</result>
<exception-mapping result="exception" exception="java.lang.Exception" />
</action>
</package>
</struts>

4.使用config-browser查看配置


你可能想浏览配置的情况,当然对于一个简单的项目,直接看struts.xml可能更快、更专业。接下来要出场的是一个插件,config-browser,它可以提供通过前台查看配置情况的功能。这不是它唯一的优点,但是我们不需要为其优点列一个清单,暂时知道这一个吧,剩下的自己体会。

4.1.添加依赖

我们使用的struts2-core是2.3.28版本,我们也使用相同版本的config-browser:

<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-config-browser-plugin</artifactId>
<version>2.3.28</version>
</dependency>

4.2.使用

重新打包、部署,重启服务,输入访问地址:http://localhost:8080/note-struts2/config-browser/actionNames.action,可以看到下面的内容:

注意左侧导航栏,Namespaces下是所有的命名空间,其中/config-browser是插件定义的,/login是我们之前定义的。右侧默认显示默认命名空间下的action。

点击左侧Namespaces/login链接,可以看到:

右侧列出了这个命名空间下的action,点进去会看到:

注意:这里的内容是按照标签页组织的,默认显示的是Results标签页,切换到Eception Mappings,可以看到:

我们关于config-browser入门的介绍就到这里了,其他的靠大家自己了。

5.扩展


前面已经对框架的基本流程中涉及到的工作,做了基本的介绍,下面这些内容会深入一下。

5.1.action

5.1.1.多个处理方法

一个Action类中可以有多个处理方法,只需要在配置<action>的时候使用method指定不同的方法名,就可以定义多个action。比如,我们假想一个Action,它的类图是这样的:

我们可以在struts.xml中这样配置:

 <package name="imagination" extends="struts-default" namespace="/imagination">
<action name="addUser" class="cn.ljl.note.struts.imaginary.actions.UserAction" method="add">
...
</action>
<action name="saveUser" class="cn.ljl.note.struts.imaginary.actions.UserAction" method="save">
...
</action>
<action name="deleteUser" class="cn.ljl.note.struts.imaginary.actions.UserAction" method="delete">
...
</action>
</package>

5.1.2.使用通配符

在满足一定的模式的情况下,使用通配符可以使用最少的配置量,配置多个action。比如对于上面的情况,也可以使用下面的配置:

 <package name="imagination" extends="struts-default" namespace="/imagination">
<action name="*User" class="cn.ljl.note.struts.imaginary.actions.UserAction" method="{1}">
...
</action>
</package>

line 2,name属性值中使用了*,method属性值中的{1}表示使用第1个*所匹配的字符串。这个配置和上文的配置效果是一样的,但是配置工作更少。

class也可以和name满足一定的模式,比如下面的配置:

 <package name="imagination" extends="struts-default" namespace="/imagination">
<action name="*User" class="cn.ljl.note.struts.imaginary.actions.{1}UserAction">
...
</action>
</package>
此时,AddUser将映射到cn.ljl.note.struts.imaginary.actions.AddUserAction。
其实,上述两种配置,体现了两种思想:将不同的业务交给Action的不同的处理方法,或者干脆使用不同的Action。
 
优先级
使用通配符会存在这样的问题:请求的地址为addUser.action,struts.xml中同时有addUser、*User、*可以匹配这个请求,会选择哪一个来处理请求呢?
如果我们称不使用通配符的为完全匹配,称使用通配符的为模式匹配,那么有下面两个规则:
  • 完全匹配优先于模式匹配
  • 模式匹配中,前面的优先
所以,会选择addUser。如果没有这个配置,则在*User、*中,哪一个出现在struts.xml的前面,哪一个被选择。
所以,建议把范围更广的配置放在后面。

5.1.3.默认的action

*可以匹配一切,所以我们可以使用*来配置默认的action。另外,我们还可以像下面这样配置:

 <package name="imagination" extends="struts-default" namespace="/imagination">
<default-action-ref name="default" />
<action name="default" class="...">
...
</action>
...
</package>

在特定命名空间下配置,只能作为当前命名空间的默认action;在默认的命名空间下配置,可以作为全局的默认action。

5.1.4.默认的class

配置<action>时,默认的class是com.opensymphony.xwork2.ActionSupport,你可以修改这项配置:在<package>下添加<default-class-ref class="" />。

5.1.5.动态方法调用

在form标签的action属性,可以同时指定action的name和方法,比如:

<form action="user!add">
...
</form>

就指定name为user的action的add方法,来处理请求。

这种方式,前台依赖于服务端的API,这样是不好的。

5.2.result

Struts2支持多种result-type,基本的result-type都是在struts2-core的struts-default.xml中配置的。

5.2.1.多种结果类型

1.dispatcher

disparcher是默认的result-type,以指定的jsp作为视图。最原始的配置方式是这样的:

<result name="success" type="dispatcher">
<param name="location">/success.jsp</param>
</result>

因为result的name默认就是success,type默认就是dispatcher,而视图的location可以直接在<result>的体配置。所以可以简化成这个样子:

<result>/success.jsp</result>

2.plainText

plainText将指定的视图以文本的形式显示给浏览器。使用这种方式,需要指定视图的location;如果视图文件中包含非西欧字符,还要指定charSet。

<result name="success" type="plainText">
<param name="location">/success.jsp</param>
<param name="charSet">GBK</param>
</result>

3.redirect

重定向。这个类型可以指定一个location,浏览器重定向到指定的视图。

<result name="success" type="redirect">/index.jsp</result>

4.redirectAction

重定向到Action。这个类型专门重定向到Action,与redirect算是被包含关系。这个类型可以指定namespace和actionName:

<result type="redirectAction">
<param name="namespace">/login</param>
<param name="actionName">check</param>
</result>

暂时,就介绍这几种吧。

5.2.2.使用通配符

在配置result映射的时候,也可以使用通配符,比如:

<package name="imagination" extends="struts-default" namespace="/imagination">
<action name="*User" class="cn.ljl.note.struts.imaginary.actions.UserAction" method="{1}">
<result>/imagination/result-{1}.jsp</result>
</action>
</package>

按照上面的配置,addUser对应cn.ljl.note.struts.imaginary.actions.UserAction的add方法,返回的视图是/imagination/result-add.jsp。

5.2.3.使用OGNL表达式

OGNL表达式的具体内容,计划放在后面讲,这里只介绍几个简单的用法。配置result映射时,可以使用action的属性值(要提供getter方法),比如:

<result>/imagination/result-add.jsp?username=${username}</result>

在计算物理视图时,就会使用action的username属性,替换其中的${username}。

如果属性是复杂属性,比如bean,而在result中需要的是属性bean的属性,也可以按照这样的方式获取:${user.name}。

5.2.4.全局配置

在之前的配置里,都是针对action的一个逻辑结果进行配置;全局配置是在<package>范围,提供一个配置,对所有action都有效。

全局配置是在<package>下,使用<global-results> - <result>来配置,比如:

 <package ...>
<global-results>
<result name="exception">/exception.jsp</result>
</global-results>
...
</package>

这样一来,这个package下所有的action,如果没有指定"exception"的映射,就使用全局的映射;如果指定了,就覆盖全局的配置。

5.3.异常的全局配置

在<package>范围,异常也可以使用全局配置。使用<global-exception-mappings> - <exception-mapping>。异常映射是把异常的类型映射到result,所以它依赖于result,全局的异常映射应该只使用全局的result,像下面这样:

 <package ...>
<global-results>
<result name="exception">/exception.jsp</result>
</global-results>
<global-exception-mappings>
<exception-mapping exception="java.lang.Exception" result="exception" />
</global-exception-mappings>
...
</package>

Struts2 MVC基础介绍的更多相关文章

  1. Struts2框架基础

    Struts2框架基础 1.Java的框架 1.1.框架简介 在大型项目开发过程中,经常会使用到一些框架,这样做好的好处是能够提高工作效率,在java中最常用的的框架就是SSH,这其实是三个框架的简称 ...

  2. Spring MVC 使用介绍(十三)数据验证 (一)基本介绍

    一.消息处理功能 Spring提供MessageSource接口用于提供消息处理功能: public interface MessageSource { String getMessage(Strin ...

  3. 重温MVC基础入门

    重温MVC基础入门   简介 本文主要是作者回顾MVC基础的文章,整合个人认为基础且重点的信息,通过简单实践进行复习. 相关代码地址:https://github.com/OtherRuan/Revi ...

  4. laravel基础课程---1、laravel安装及基础介绍(laravel如何安装)

    laravel基础课程---1.laravel安装及基础介绍(laravel如何安装) 一.总结 一句话总结: [修改composer镜像地址].[明确laravel的安装要求].[安装指定版本的la ...

  5. ASP.NET MVC 学习笔记-2.Razor语法 ASP.NET MVC 学习笔记-1.ASP.NET MVC 基础 反射的具体应用 策略模式的具体应用 责任链模式的具体应用 ServiceStack.Redis订阅发布服务的调用 C#读取XML文件的基类实现

    ASP.NET MVC 学习笔记-2.Razor语法   1.         表达式 表达式必须跟在“@”符号之后, 2.         代码块 代码块必须位于“@{}”中,并且每行代码必须以“: ...

  6. Spring MVC基础了解

    参考网址:https://www.yiibai.com/spring_mvc/springmvc_overview.html Spring框架相关 Spring Security 一个灵活强大的身份验 ...

  7. XML基础介绍【一】

    XML基础介绍[一] 1.XML简介(Extensible Markup Language)[可扩展标记语言] XML全称为Extensible Markup Language, 意思是可扩展的标记语 ...

  8. Web3D编程入门总结——WebGL与Three.js基础介绍

    /*在这里对这段时间学习的3D编程知识做个总结,以备再次出发.计划分成“webgl与three.js基础介绍”.“面向对象的基础3D场景框架编写”.“模型导入与简单3D游戏编写”三个部分,其他零散知识 ...

  9. jsp学习---mvc模式介绍和el表达式,jstl标签库的使用入门

    一.mvc模式介绍 下图是常用的mvc分层模式: 项目中的包命名规则,一般如下: com.amos.domain 封装JavaBean,一般我喜欢用model命名这个包com.amos.dao 封装d ...

随机推荐

  1. org.hibernate.HibernateException: getFlushMode is not valid without active transaction

    Spring & Hibernate 整合异常记录: org.hibernate.HibernateException: getFlushMode is not valid without a ...

  2. 字符串:AC自动机

    给出一个字典和一个模式串,问模式串中出现几个字典中的单词 最后一行是大串,之前输入的是小串 #include<iostream> #include<cstdio> using ...

  3. STL在算法比赛中简单应用

    STL基础 和 简单的贪心问题 STL(Standard Template Library) 即 标准模板库. 它包含了诸多在计算机科学领域里所常用的基本数据结构和算法.这些数据结构可以与标准算法一起 ...

  4. My deep learning reading list

    My deep learning reading list 主要是顺着Bengio的PAMI review的文章找出来的.包括几本综述文章,将近100篇论文,各位山头们的Presentation.全部 ...

  5. MappedByteBuffer以及ByteBufer的底层原理

    最近在用java中的ByteBuffer,一直不明所以,尤其是对MappedByteBuffer使用的内存映射这个概念云里雾里. 于是首先补了物理内存.虚拟内存.页面文件.交换区的只是:小科普——物理 ...

  6. Try finally的一个实验和为什么避免重载 finalize()方法--例子

    public class TryFinallTest { public TryFinallTest(){ } public void runSomething(String str){ System. ...

  7. ajax做显示信息以后用ajax、Bootstrp做弹窗显示信息详情

    1.用ajax做弹窗显示信息详情 nation.php <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN&qu ...

  8. ueditor和thinkphp框架整合修改版

    基于tp官网上的一篇文章修改的  因为tp中所有目录其实都是性对于入口文件的 在原来的基础上略做修改后 已经做到 无论项目放在www下的任何位置 图片在编辑器中回填后都能正常显示! http://fi ...

  9. keypress 、keydown、keyup后触发回车

    1.keypress .keydown.keyup的区别 keypress表示键盘按下的全过程,只有按下任意字母数字键(后退.删除等系统功能键无效)时才触发,捕获到的keyCode区分大小写 keyd ...

  10. PEB及LDR链

    PEB地址的取得在NT内核系统中fs寄存器指向TEB结构,TEB+0x30处指向PEB结构,PEB+0x0c处指向PEB_LDR_DATA结构,PEB_LDR_DATA+0x1c处存放一些指向动态链接 ...