软件开发过程中的半成品,解决软件开发中的通用问题,从而提高开发效率。
eg:
典型的MVC框架,人为的把一个软件分为3个层次从而提高开发效率。
M(Model | 模型层)Service + DAO + Entity
V(View | 视图层) JSP(freemarker velocity)
C(Controller | 控制层) (Servlet)
Servlet {
//收集数据
//出现问题1:设置字符集编码的代码问题
String age = request.getParamter("age");
request.getParamter("password");
//问题2:手工进行类型转换
Interger.parseInt();
//调用业务
Service
//跳转页面
request.getRequestDispatcher("/a.jsp").forward(request, response);
redirect;
//问题3:把跳转路径写死在程序中,不利于代码的维护
response.sendredirect("/b.jsp");
Struts2代码:
Struts2 {
MyStruts2 implements Action {
public String execute() throws Exception {
//调用业务
//调用业务
//跳转页面
return "hibiscidai"
}
}
}
对于WEBAPPLICATION的配置文件web.xml要声明映射
<servlet>
<servlet-name>Aservlet-name>
<servlet-class>xxx.servletservlet-class>
servlet>
<servlet-mapping>
<servlet-name>Aservlet-name>
<url-pattern>/Aurl-pattern>
servlet-mapping>
对于Struts.xml的配置
name="A" class="xxx.action">
<result name="hibiscidai">
result>
struts2-core-2.3.15.1.jar
在web.xml中声明
<filter>
<filter-name>struts2filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilterfilter-class>
filter>
<filter-mapping>
<filter-name>struts2filter-name>
/*
filter-mapping>
对于不同版本会有兼容问题,注意 filter-class 标签映射类
在 servlet-api.jar 包中
HttpServletRequest request = ServletActionContext.getRequest();
HttpServletResponse response =ServletActionContext.getResponse();
HttpSession session = request.getSession();
直接在项目路径下输入action名字或者 xxx.action
eg:
http://localhost:8080/ProjectName/MyAction
http://localhost:8080/ProjectName/MyAction.action
name="FirstStruts" class="fancylab.hibiscidai.action.MyAction">
<result name="success" type="dispatcher">
/ok.jsp
result>
name="FirstStruts" class="fancylab.hibiscidai.action.MyAction">
<result name="success" type="redirect">
/ok.jsp
result>
name="A" class="fancylab.hibiscidai.action.AAction">
<result name="B" type="chain">
B
result>
name="B" class="fancylab.hibiscidai.action.BAction">
<result name="success">
/ok.jsp
result>
name="A" class="fancylab.hibiscidai.action.AAction">
<result name="B" type="redirectAction">
B
result>
name="B" class="fancylab.hibiscidai.action.BAction">
<result name="success">
/ok.jsp
result>
使配置文件当中的配置信息模块化,便于配置信息的管理。
<package name="xxx" extends="struts-default">
使用户的请求模块化,便于随后过滤器的使用。
原 web.xml配置
<servlet>
<servlet-name>Aservlet-name>
<servlet-class>fancylab.hibiscidai.action.AActionservlet-class>
servlet>
<servlet-mapping>
<servlet-name>Aservlet-name>
<url-pattern>/User/Aurl-pattern>
servlet-mapping>
<servlet>
<servlet-name>Aservlet-name>
<servlet-class>fancylab.hibiscidai.action.AActionservlet-class>
servlet>
<servlet-mapping>
<servlet-name>Aservlet-name>
<url-pattern>/User/Burl-pattern>
servlet-mapping>
<filter>
/User/*
filter>
访问方式:localhost:[port]/ProjectName/A
Struts2 包空间加入后
struts.xml配置
<package name="user" extends="strust-default" namespace="/First">
"A" class="fancylab.hibiscidai.action.AAction">
package>
<package name="Admin" extends="strust-default">
"A" class="fancylab.hibiscidai.action.AAction">
package>
访问方式:localhost:[port]/ProjectName/namespace/A
<result name="D" type="chain">
<param name="namespace">/secondparam>
<param name="actionName">Dparam>
result>
当许多Action跳转到相同路径时,可以定义全局跳转,减少配置文件当中的配置信息冗余。
<global-results>
<result name="success">
/ok.jsp
result>
global-results>
login.jsp
type="text" name="username">
type="password" name="password">
type="submit" value="login">
xxxAction implements Action {
private String username;
private String password;
//setget方法
public String execute() {
UserService.login(username, password);
}
}
好处
- 简化了收集client数据的方式。
HttpServletRequest request = ServletActionContext.getRequest();
String username = request.getParameter("username
");
register.jsp
用户名type="text" name="user.username">
密码type="password" name="user.password">
年龄type="text" name="user.age">
日期type="date" name="user.birthdate">
type="submit">
User.java
class User {
private String username;
private String password;
private int age;
private Date birthdate;
//setter和getter方法
}
RegisterAction.java
RegisterAction implements Action {
private User user;
//setter和getter方法
public String execute() {
UserService.register(user);
}
}
type="checkbox" value="1" name="a">
type="checkbox" value="2" name="a">
type="checkbox" value="3" name="a">
private List a;//以数组的形式接收数据
MyAction extends ActionSupport
在一个Action中提供多个方法应对用户不同需求
extends ActionSupport(建议)
语法要求:DMI中Action中的方法,方法名随便写
修饰符 返回值 参数列表 与execute中方法保持一致
method
标签中设置方法
优点:可读性好
缺点:配置信息冗余
<action name="addUser" class="fancylab.hibiscidai.action.UserAction" method="add">action>
采用通配符进行
优点:配置信息不再冗余
缺点:可读性极差
<action name="user_" class="fancylab.hibiscidai.action.UserAction" method="{1}">action>
OGNL表达式:是一种独立的表达式语言,不依赖于任何的框架
OGNL表达式特点: 从root区,ContextMap区取数据
从Root区中取所存对象的属性值
@Test
public void test1() throws Exception{
Person person = new Person();
person.setUsername("laowang");
person.setPassword("12345");
person.setAge(30);
System.out.println(Ognl.getValue("username",person));
System.out.println(Ognl.getValue("password",person));
System.out.println(Ognl.getValue("age",person));
}
@Test
public void test2() throws Exception{
Person person = new Person();
person.setUsername("laowang");
person.setPassword("12345");
person.setAge(30);
Address address = new Address();
address.setStreet("文化路");
person.setAddress(address);
System.out.println(Ognl.getValue("address.addressname",person));
System.out.println(Ognl.getValue("address.street",person));
}
@Test
public void test3() throws Exception{
Person person = new Person();
person.setUsername("laowang");
person.setPassword("12345");
person.setAge(30);
List tels = person.getTels();
tels.add("xjr");
tels.add("whp");
System.out.println(Ognl.getValue("tels[0]",person));
System.out.println(Ognl.getValue("tels[1]",person));
}
@Test
public void test4() throws Exception{
Person person = new Person();
person.setUsername("laowang");
person.setPassword("12345");
person.setAge(30);
Map qqs = person.getQqs();
qqs.put("kuaige","562471794");
qqs.put("zpf","7654321");
System.out.println(Ognl.getValue("qqs['kuaige']",person));
System.out.println(Ognl.getValue("qqs['zpf']",person));
}
+
-
*
/
%
>
<
>=
<=
!=
&&
||
!
@Test
public void test5() throws Exception{
Person person = new Person();
person.setUsername("laowang");
person.setPassword("12345");
person.setAge(30);
System.out.println(Ognl.getValue("age<10",person));
System.out.println(Ognl.getValue("username=='laowang'",person));
}
@Test
public void test6() throws Exception{
Person person = new Person();
person.setUsername("laowang");
person.setPassword("12345");
person.setAge(30);
System.out.println(Ognl.getValue("username.toUpperCase()",person));
System.out.println(Ognl.getValue("username.equals('laowang')",person));
}
contextmap本身是个map,在单独测试ognl时需要提供一个map集合
语法:#key的方式取值
//ContextMap区取值的方式
@Test
public void test1() throws Exception{
Map contextmap = new HashMap();
Person person = new Person();
person.setUsername("laowang");
person.setPassword("12345");
person.setAge(30);
contextmap.put("A", person);
System.out.println(Ognl.getValue("#A.age+10", contextmap,new Object()));
}
1.客户端传来的数据
2.作用域中的数据
- request
- session
- application
与视图层(view层)解耦合
ActionContext ac = ActionContext.getContext();
ValueStack vs = ac.getValueStack();
一次请求有效,请求变化则值栈变化
请求格式
request.setAttribute("name", "laowang");
request.getAttribute("name");
request.setAttribute("n", "feige");
user类
class User {
private String username;
//setter和getter方法
}
request作用域底层
class request {
private Map attribute;
public void setAttribute(String name, String object) {
attribute.put(name, object);
}
public Object getAttribute(String name) {
Object = attrbute.get("name");
return object;
}
}
对于作用域
request–map
session–map
application–map
问题:值栈是一次请求有效,为什么可以管理session application作用域?
作用:配合值栈在视图层显示数据
引用:
JSTL标签:
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
Strtus标签:
<%@taglib prefix="s" uri="/struts-tags"%>
value="OGNL表达式" />
if test="OGNL表达式" />
if>
else>
else>
if test="OGNL表达式">
if>
elseif test="OGNL表达式" />
elseif>
else>
else>
语法:
<s:iterator value="OGNL表达式">
s:iterator>
List或Set数组
<s:iterator value="#request.users">
<h1><s:property value="username"/>h1>
<h1><s:property value="password"/>h1>
<h1><s:property value="age"/>h1>
s:iterator>
Map
<s:iterator value="#request.users">
<h1><s:property value="key"/>h1>
<h1>==========h1>
<h1><s:property value="value"/>h1>
s:iterator>
<s:iterator value="#request.s">
<s:property/>
s:iterator>
value="OGNL" status="s">
#s.count 遍历次数
#s.index 遍历的下标
#s.odd 是否是奇数遍历
#s.even 是否是偶次遍历
value="OGNL" begin="" end="" Step="">
begin:从某一个下标开始遍历
end:以某一个下标结束
step:步幅
Action中成员变量的作用:
- 收集客户端的参数(零散变量,对象,数组或集合)
- 替换request作用域
Struts2ScopeUtil工具类的开发
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.util.ValueStack;
//简化值栈操作session作用域及application作用域的使用
public class Struts2ScopeUtil {
// 向session作用域中存值
public static void setSessionAttribute(String OGNL, Object value) {
ActionContext context = ActionContext.getContext();
ValueStack valueStack = context.getValueStack();
valueStack.setValue("#session." + OGNL, value);
}
// 从Session作用域中取值
public static Object getSessionAttribute(String OGNL) {
ActionContext context = ActionContext.getContext();
ValueStack valueStack = context.getValueStack();
return valueStack.findValue("#session." + OGNL);
}
// 向application作用域中存值
public static void setApplicationAttribute(String OGNL, Object value) {
ActionContext context = ActionContext.getContext();
ValueStack valueStack = context.getValueStack();
valueStack.setValue("#application." + OGNL, value);
}
// 从application作用域中取值
public static Object getApplicationAttribute(String OGNL) {
ActionContext context = ActionContext.getContext();
ValueStack valueStack = context.getValueStack();
return valueStack.findValue("#application." + OGNL);
}
}
栈:先进后出
语法:
作用:自定义日期的格式
date name="#request.date" format="yyyy-MM-dd hh:mm:ss" />
语法:
、
作用:防止用户禁用Cookie,自动进行url重写。加载第三方资源。
注意:传值
———->
———->
———->
———->
语法:
作用:把多个Action的处理结果作整合
ai.getAction();
//获取目标的Action ai.getStack();
//获取值栈 ai.invoke();
//控制请求的流程走向public class checkloginInterceptor extends AbstractInterceptor {
@Override
public String intercept(ActionInvocation ai) throws Exception {
// 获取登陆或注册的标志位
String flag = (String) Struts2ScopeUtil.getSessionAttribute("flag");
if (flag == null) {
return "login";
} else {
ai.invoke();
}
return null;
}
}
<interceptors>
<interceptor name="myInterceptor" class="fancylab.hibiscidai.interceptor.MyInterceptor">
interceptors>
<action name="A" class="fancylab.hibiscidai.action.AAction" method="A">
<interceptor-ref name=myinterceptor">interceptor-ref>
action>
作用:管理多个拦截器
使用:不编码,只需配置
<interceptor-stack name="my">
<interceptor-ref name="myInterceptor">interceptor-ref>
<interceptor-ref name="myInterceptor2">interceptor-ref>
interceptor-stack>
作用:可以指定一个拦截器栈为默认拦截器栈,可以拦截所有的目标Action
<default-interceptor-ref name="my">default-interceptor-ref>
注意:默认拦截器栈放置的位置必须在全局跳转的前边,每个包中只能配置一个默认拦截器,局部配置优先。
Struts2-core.jar —->Struts-default.xml
注意:如果自定义了默认拦截器栈,Struts2中的系统拦截器栈将失效
<interceptors>
<interceptor-stack name="my">
<interceptor-ref name="defalutStack">interceptor-ref>
<interceptor-ref name="myInterceptor">interceptor-ref>
<interceptor-ref name="myInterceptor2">interceptor-ref>
interceptor-stack>
interceptors>
注意:如果自定义拦截器,系统拦截器将失效
public class MethodInterceptor extends MethodFilterInterceptor {
@Override
public String doIntercept(ActionInvocation ai) throws Exception {
System.out.println("我是方法拦截器");
ai.invoke();
return null;
}
}
<param name="includeMethod">
拦截器拦截哪些方法
param>
<interceptors>
<interceptor name="methodinterceptor" class="fancylab.hibiscidai.interceptor.MethodInterceptor">
<param name="excludeMethods">
m4
param>
interceptor>
<interceptor-stack name="my">
<interceptor-ref name="defaultStack">interceptor-ref>
<interceptor-ref name="methodinterceptor">interceptor-ref>
interceptor-stack>
interceptors>
<defalut-interceptor-ref name="my">
defalut-interceptor-ref>
<s:token>s:token>
引入Struts2提供的token拦截器
name="my1">
ref name="token"> ref>
ref name="defaultStack"> ref>
<result name="invalid.token">
/error.jsp
result>
enctype="application/x-www-form-urlencoded"
把表单中的文本中的内容,提交到服务器中
enctype="multipart/form-data"
告知服务器端识别客户端传入的文件内容
public class uploadAction extends ActionSupport {
private File upload;
// 获取客户端传入的文件名和后缀
private String uploadFileName;
// 获取客户端传入的文件类型
private String uploadContentType;
// 文件存放的目录
private String directory;
public String getDirectory() {
return directory;
}
public void setDirectory(String directory) {
this.directory = directory;
}
public String getUploadContentType() {
return uploadContentType;
}
public void setUploadContentType(String uploadContentType) {
this.uploadContentType = uploadContentType;
}
public String getUploadFileName() {
return uploadFileName;
}
public void setUploadFileName(String uploadFileName) {
this.uploadFileName = uploadFileName;
}
public File getUpload() {
return upload;
}
public void setUpload(File upload) {
this.upload = upload;
}
public String upload() {
/*InputStream is = null;
OutputStream os = null;
// 把文件读入IO流
try {
is = new FileInputStream(upload);
// 把文件写出到文件系统中
os = new FileOutputStream("D:\\Class3\\apache-tomcat-7.0.67\\webapps\\Strutspratice\\upload\\zkf.txt");
byte[] buffer = new byte[1024];
int len = 0;
while (true) {
// 读操作
len = is.read(buffer, 0, buffer.length);
if (len == -1)
break;
// 写操作
os.write(buffer, 0, len);
}
return "uploadOK";
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
return "uploadError";
} finally {
try {
// 关闭流
is.close();
os.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}*/
try {
System.out.println(uploadContentType);
System.out.println(directory);
FileUtils.copyFile(upload, new File(getRealPath(directory) + "\\" + uploadFileName));
return "uploadOK";
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
return "uploadError";
}
}
public String getRealPath(String path) {
ServletContext servletContext = ServletActionContext.getServletContext();
// 获取绝对路径
String realPath = servletContext.getRealPath(path);
return realPath;
}
}
Commons-io.jar
提供文件操作的工具类
FileUtils.copyFile(upload, new File(getRealPath(directory) + "\\" + uploadFileName));
如何获得用户上传的文件名
private File upload;
// 获取客户端传入的文件名和后缀
private String uploadFileName;
// 获取客户端传入的文件类型
private String uploadContentType;
如何在web开发中通过相对路径获取绝对路径
ServletContext sc = ServletActionContext.getServletContext();
String RealPath = ac.getRealPath(“相对路径”);
String RealPath = ac.getRealPath(“/upload”);
文件目录转移到配置文件中进行配置
name="upload" class="fancylab.hibiscidai.Action.uploadAction" method="upload">
name="directory>/upload
Action中声明成员变量即可
private String directory;
<constant name="struts.multipart.maxSize" value="2097152000">constant>
/struts-2.3.15.1/docs/WW/docs/stream-result.html stream-result
//目的告知Struts2将要下载的文件
public InputStream getInputStream() throws Exception {
return new FileInputStream(getRealPath(directory) + "\\" + filename);
}
<result type="stream">
<param name="contentType">text/plainparam>
<param name="contentDisposition">attachment;filename=${filename}param>
result>
通过getRealPath()
方法与Action中为成员变量赋值的方式,完成路径的修改。
客户通过传递参数的形式,向Action中传递数据,Action中通过成员变量接收数据。
<ul>
<li>
<a href=" ?filename=z.txt">
z.txt
a>
li>
<li>
<a href=" ?filename=zkf.txt">
zkf.txt
a>
li>
ul>
//获取客户端所要下载的文件名
private String filename;
//获取客户端所要下载的文件名
private String filename;
<action name="download" class="com.baizhi.Action.downloadAction">
<param name="directory">/uploadparam>
<result type="stream">
<param name="contentType">text/plainparam>
<param name="contentDisposition"> attachment;filename=${filename}param>
result>
action>