1.javaEE使用三层架构: web层(表现层),业务逻辑层,数据持久层
采用mvc模式。
传统:(servlet时代)一个请求,对应一个servlet
现在:(struts时代)多个请求,对应一个前端控制器,再由前端控制器完成请求分发,交给多个action去执行
2.struts运行流程分析:
用户发起请求:--》web.xml中配置的StrutsPrepareAndExecuteFilter过滤器会加载拦截器(Interceptor--》在struts-default.xml中定义,执行是defaultStack中引用一系列拦截链),拦截所有请求————》分发请求给相应的action,---》action执行execute()方法执行请求。
2.2:用户编写的acton,类似struts中的forward。。。。。。返回的return '' '' 类似struts中的forward
2.3配置文件的加载顺序:
struts2-core.jar中保存default.properties----》还是struts2-core.jar中的struts-default.xml--->(struts-xxx.jar)struts-plugin.xml,---->struts.xml是web应用默认的struts配置文件--》struts.properties是struts的默认配置文件-----》
web.xml是web应用的配置文件【多文件的常量值相同的话,后一个文件配置的常量值会覆盖前面文件的常量值】
2.4struts的默认常量可以在default.properties中配置,开发者自定义在struts.xml中为<constant name="struts.devMode" value="true">
name="struts.i18n.encoding" value="utf8" 解决post乱码问题,相当于request.setEncodingChartSet=utf8
struts.action.extension ---------->action 默认以.action结尾扩展名和不写.action扩展名都会分发给action,该常量是指定访问时的扩展名
struts.serve.static.browserCashe ------->true 浏览器会缓存静态页面
struts.devMode ----------------->true 提供详细报错页面,修改struts.xml后不需要重启服务器
2.5使用<struts><include file="xxx.xml"/><include file="xxx.xml"/></struts>,配置文件分离,使用它可按模块添加配置文件
2.6struts的action的三种写法:
2.6.1 POJO写法:
public class UserAction{
public String execute(){
return ""
}
}
运行原理:通过反射调用 :
1. 读取struts.xml获得完整的action类名
2. obj=Class.forName("完整类名").newInstance();
3. Method m=Class.forName("完整类名").getMethod("execute")
4. m.invoke(obj);
这种调用是标准的命令模式:命令模式是为了解决命令的请求者和命令的实现者之间的耦合关系 (每个请求都访问execute方法)
2.6.1 实现Action接口:
public class UserAction implements Action{
@Override public String execute(){
return ""}
}
Action接口提供了5种逻辑视图:
success------------》数据处理成功
none-----------------》页面不跳转(==return ‘’ ‘’)
input--------------》用户输入页面错误,用于表单校验
error------------》数据处理错误
login----------------》主要权限认证(登录页面)
2.6.2 继承ActionSupport(间接实现了接口,它还自带表单域的校验,错误信息设置,获得国际化信息)
3.Action的方法调用
通过action的method配置属性,实现多请求,一个action,多个方法处理的功能/bb--->回调register(), /cc---》会调login()
<action name="index" class="com.ssh.action.UserAction">
<result>/success.jsp</result>
</action>
<action name="bb" class="com.ssh.action.UserAction" method="register">
<result>/success.jsp</result>
</action>
<action name="cc" class="com.ssh.action.UserAction" method="login">
<result>/success.jsp</result>
</action>
简化配置:(通过通配符和占位符)
public String user_add(){}
<action name="user_*" class="com.ssh.action.UserAction" method="{1}">
<result>/success.jsp</result>
</action>
高级写法:
访问形式为类名+方法名{1}表示第一个通配符的内容,{2}表示第二个通配符的内容
<action name="*_*" class="com.ssh.action.{1}" method="{2}">
<result>/success.jsp</result>
</action>
动态方法调用:
首先保证常量 struts.enable.DynamicMethodInvocation--------------->true
写法: “ !方法名 ”
<struts>
<constant name="struts.devMode" value="true" />
<constant name="struts.enable.DynamicMethodInvocation" value="true"/>
<action name="index" class="com.ssh.action.UserAction">
<result>/success.jsp</result>
</action>
</struts>
5. action中使用ServletApi:
1.action api与servlet api已经解耦,action间接通过ActionContext对象(上下文对象,它什么都知道)访问ServletApi
public String actionServletApi(){
//获取参数
ActionContext actionContext=ActionContext.getContext();
Map<String,Object>parameters=actionContext.getParameters();
String [] value=(String[])parameters.get("username"); //request.getParameter("username")
System.out.println("username:"+value[0]);
//读取request的attribute
actionContext.put("company","好世界");
System.out.println(actionContext.get("company"));
//存取session
Map<String,Object>sessionMap=actionContext.getSession();
sessionMap.put("age",20);
System.out.println(sessionMap.get("age"));
//存取Application的Attribute
Map<String,Object>applicationMap=actionContext.getApplication();
applicationMap.put("info","下雨了");
System.out.println(sessionMap.get("info"));
return SUCCESS;
}
2.使用接口注入方式(耦合方式)
//implements ServletContext
public class UserAction extends ActionSupport implements ServletRequestAware, ServletResponseAware {
private HttpServletRequest request;
public String execute() throws Exception {
System.out.println(request.getParameter("name"));
}
public String actionServletApi(HttpServletRequest request){
System.out.println(request.getParameter("name"));
}
@Override
//struts会自动将request对象设置进来
public void setServletRequest(HttpServletRequest httpServletRequest) {
this.request=request;
}
@Override
public void setServletResponse(HttpServletResponse httpServletResponse) {
}
}
3.静态方法直接访问:
直接通过ServletActionContext访问servlet Api
ServletActionContext.getRequest(),获得request对象(session) .getServletContext获得ServletContext对象
虽然是静态方法,但他没有线程问题,因为有ThreadLocal模式,保存线程的私有变量。(推荐使用1和3)
6. 基于注解的struts开发:
约定:开发者与大家默认的一个暗号,约定是实现真正的零配置(解决了接收与跳转问题,约定不够灵活)
struts2中有个convention-plugin插件,实现了约定
注解:是基于约定的。(解决了更细节的东西,如拦截器。注解功能等价于xml配置,注解可以覆盖约定的结果)
页面访问路经的配置说明:
注解的struts的页面处理:(结果页面的配置处理)
4.struts实现hello world。目录结构如下:(说明都在代码里)
pom.xml中引入相关依赖:
<properties>
<hibernate.version>5.0.7.Final</hibernate.version>
<spring.version>4.2.4.RELEASE</spring.version>
<struts.version>2.3.24</struts.version>
<slf4j.version>1.6.6</slf4j.version>
<log4j.version>1.2.12</log4j.version>
</properties>
<dependencies>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.7</version>
</dependency>
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-core</artifactId>
<version>${struts.version}</version>
<exclusions>
<exclusion>
<groupId>javassist</groupId>
<artifactId>javassist</artifactId>
</exclusion>
</exclusions>
</dependency>
<!--javassist二方包,手工编写字节码,再由JVM执行,动态编程,开销低于反射, 手工编写字节码,再由JVM执行 -->
<dependency>
<groupId>org.javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.24.1-GA</version>
</dependency>
<!-- log start -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${slf4j.version}</version>
</dependency>
<!-- log end -->
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!-- 数据库驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.1.37</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.9</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
</dependencies>
web.xml文件代码:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
<display-name>mySSH</display-name>
<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>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
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.devMode" value="true" />
<package name="mySSH" extends="struts-default">
<action name="index" class="com.ssh.action.UserAction">
<result>/success.jsp</result>
</action>
</package>
</struts>
UserEntity类:
public class UserEntity {
private int id;
private String account;
private String password;
private String name;
private String facepic;
private Integer companyId;
}
//get,set方法
UserAction类:
package com.ssh.action;
import com.opensymphony.xwork2.ActionSupport;
import com.ssh.entity.UserEntity;
/* 而Actionsupport这个工具类在实现了Action接口的基础上还定义了一个validate()方法,重写该方法,它会在execute()方法之前执行,如校验失败,会转入input处,必须在配置该Action时配置input属性。
另外,Actionsupport还提供了一个getText(String key)方法还实现国际化,该方法从资源文件上获取国际化信息. 这样在自定义标签时可以定义一个变量为new actionsupport对象实现国际化。
ActionSupport类的作用 struts2不要求我们自己设计的action类继承任何的struts基类或struts接口,但是我们为了方便实现我们自己的action,大多数情况下都会继承com.opensymphony.xwork2.ActionSupport类,并重写此类里的public String execute() throws Exception方法。
因为此类中实现了很多的实用借口,提供了很多默认方法,这些默认方法包括国际化信息的方法、默认的处理用户请求的方法等,这样可以大大的简化Acion的开发。
Struts2中通常直接使用Action来封装HTTP请求参数,因此,Action类里还应该包含与请求参数对应的属性,并且为属性提供对应的getter和setter方法。*/
public class UserAction extends ActionSupport {
private UserEntity userEntity;
@Override
public String execute() throws Exception {
userEntity = new UserEntity();
userEntity.setName("hello world");
System.out.println(userEntity.getName());
//返回字符串来控制页面的跳转
return SUCCESS;
}
}
index.jsp:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h2>Hello World!</h2>
<a href="/index.action">跳转</a>
</body>
</html>
运行结果: