欢迎浏览Java工程师SSH教程从零打造在线网盘系统系列教程,本系列教程将会使用SSH(Struts2+Spring+Hibernate)打造一个在线网盘系统,本系列教程是从零开始,所以会详细以及着重地阐述SSH三个框架的基础知识,第四部分将会进入项目实战,如果您已经对SSH框架有所掌握,那么可以直接浏览第四章,源码均提供在GitHub/ssh-network-hard-disk上供大家参阅

我相信你在使用任何一个MVC框架的时候都会接触到以下功能,你必须要会使用这些功能才能够在Struts2中熟练的解决大多数问题

本篇目标

  • 接收参数
  • 参数校验
  • 数据转换
  • 响应数据
  • 上传下载
  • 异常处理
  • 国际化支持

接收参数 示例源码下载

Struts2接收参数有三种方式,

  1. Servlet API
  2. getter和Setter方法
  3. 模型驱动

Servlet API

    @Action(value = "register")
public void register() {
ActionContext context = ActionContext.getContext();
HttpServletRequest httpServletRequest = (HttpServletRequest) context.get(StrutsStatics.HTTP_REQUEST);
String username = httpServletRequest.getParameter("username");
String password = httpServletRequest.getParameter("password");
System.out.println("username:" + username + " password:" + password);
}

getter和Setter方法

    private String username;

    private String password;

    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;
} @Action(value = "register")
public void register() {
System.out.println("username:" + username + " password:" + password);
}

当然你也可以使用JavaBean进行接收参数,类似下面这样,前端传递的name属性需要有些变动,name属性需要改成xxxx.xxx与属性名一致

<form action="register.action" method="get">
<input name="user.username" type="text">
<input name="user.password" type="text">
<input type="submit">
</form>
    private User user;

    public User getUser() {
return user;
} public void setUser(User user) {
this.user = user;
} @Action(value = "register")
public void register() {
System.out.println("username:" + user.getUsername() + " password:" + user.getPassword());
}

模型驱动

@ParentPackage("default")
public class RegisterAction implements ModelDriven<User> { private User user = new User(); @Override
public User getModel() {
return user;
} @Action(value = "register")
public void register() {
System.out.println("username:" + user.getUsername() + " password:" + user.getPassword());
} }
![1](7623C3566DA045869126C1B9D546A934)

参数校验 示例源码下载

对于前端传递的参数来讲,存在太多不稳定性,所以对于参数的校验是必不可少的,对于校验来说大体上分为两种,一种是前端校验,一种是后端校验,前端校验的方法在这里就不再累述,这里仅仅讲述Struts2如何使用Validation校验框架

获取参数

  private String username;
private String password;
getter and setter......

在Action同级目录增加-validation.xml

<!DOCTYPE validators PUBLIC
"-//Apache Struts//XWork Validator 1.0.2//EN"
"http://struts.apache.org/dtds/xwork-validator-1.0.2.dtd"> <validators>
<!-- 要对哪个属性进行验证 -->
<field name="username">
<!-- 验证规则 -->
<field-validator type="requiredstring">
<!-- 违反规则的提示 -->
<message>用户名不能为null!</message>
</field-validator>
</field>
<field name="password">
<field-validator type="requiredstring">
<message>密码不能为null</message>
</field-validator>
</field> </validators>

核心Action(这里可以看到如果校验正确跳转 "/success.jsp",如果校验失败错误信息输出在"/form.jsp")

    @Override
@Action(value = "register", results = {
@Result(name = SUCCESS, location = "/success.jsp"),
@Result(name = INPUT,location = "/form.jsp")
})
public String execute() throws Exception {
System.out.println("username"+username+"password:"+password);
return SUCCESS;
}

下载本小节源码访问http://localhost:8080/form.jsp

数据转换 示例源码下载

WEB系统都是基于网页形式的,接收到的信息都是字符串,Java又是强类型的语言,所以必须需要一个转换的过程.而Struts2的类型转换是基于OGNL表达式的,只需要将表单中的name属性根据OGNL规则命名就能转换成相应的Java类型,通常情况下哦我们无需建立自己的类型转换器,Struts2的内建转换器完全能帮助我们完成任务

例如我们有下面一个需求(包含Integer,Date,数组的转换)

我们该怎么办呢?不不不~~~~我们什么都不用做正常编写Action就行了,Struts2会自动帮我们进行转换

public class RegisterAction extends ActionSupport implements ModelDriven<User> {

    private User user = new User();

    @Override
public User getModel() {
return user;
}
@Override
@Action(value = "register", results = {
@Result(name = SUCCESS, location = "/success.jsp")
})
public String execute() throws Exception {
System.out.println(user.toString());
return SUCCESS;
}
}

好吧,真的没什么挑战力,下面我们要自己实现转换器了

例如:我们需要将字符串"自行车,1033,100"转换为Java的Product对象

自定义转换器

public class StringToProductTypeConverter extends DefaultTypeConverter {

    @Override
public Object convertValue(Map context, Object value, Class toType) {
if (toType == Product.class) {
String[] params = (String[]) value;
Product product = new Product();
String[] productValues = params[0].split(",");
product.setProductName(productValues[0].trim());
product.setPrice(Float.parseFloat(productValues[1].trim()));
product.setCount(Integer.parseInt(productValues[2].trim()));
return product;
} else if (toType == String.class) {
Product product = (Product) value;
return product.toString();
}
return null;
} }

配置全局转换器(在WEB-INF\classes目录新建xwork-conversion.properties)

com.jimisun.action.Product=com.jimisun.action.StringToProductTypeConverter

在Action中接收(不要使用模型驱动方式接收参数,接收不到)

public class ProductAction extends ActionSupport {

    private Product product;

    public Product getProduct() {
return product;
} public void setProduct(Product product) {
this.product = product;
} @Override
@Action(value = "register", results = {
@Result(name = SUCCESS, location = "/success.jsp")
})
public String execute() throws Exception {
System.out.println(product.toString());
return SUCCESS;
}
}

响应数据 示例源码下载

我们一直都没有探讨一个问题,那就是Struts2的结果的响应.对于任何一个程序而言,最重要的莫过于输入和输出,当我们了解了Struts2接收参数后,现在我们一起来看一看Struts2如何响应参数吧

  • Servlet API存取值
  • 属性值存取值
  • 值栈Set方法存取值
  • 值栈Push方法存取值

Servlet API存取值

    ActionContext context = ActionContext.getContext();
HttpServletRequest request = (HttpServletRequest) context.get(StrutsStatics.HTTP_REQUEST);
request.setAttribute("requestValue","requestValue");
<%--从Servlet API的Request域对象中取值--%>
Request取值:<s:property value="#request.requestValue"/>

属性值存取值

private User user = new User("jimisun", "jimisun");
<%--获取属性值--%>
简单属性取值:<s:property value="user.username"/>

那么对于复杂的属性存取值我们可以这样,例如List

private List<User> list = new ArrayList<>();
User user1 = new User("list1","list1");
User user2 = new User("list2","list2");
list.add(user1);
list.add(user2);
<%--获取属性List值--%>
list属性取值:
<br>
<s:iterator value="list" var="user"> <s:property value="#user.username"/>
<s:property value="#user.password"/>
<br/>
</s:iterator>

值栈Set方法存取值

 ActionContext context = ActionContext.getContext();
ValueStack valueStack = context.getValueStack();
valueStack.set("valueStackDemo", "valueStackDemoSet");
<%--值栈Set方法取值--%>
值栈set取值:<s:property value="valueStackDemo"/>

值栈Push方法存取值

 ActionContext context = ActionContext.getContext();
ValueStack valueStack = context.getValueStack();
valueStack.push("valueStackPush");
<%--值栈Push方法取值--%>
值栈push取值:<s:property value="[0].top"/>

OK,现在对于Struts2的几种数据的响应方式我们大概已经知道了,现在我们来看一看这几种存储数据方式在值栈中的结构,在本小节源码中运行项目直接访问http://localhost:8080/outputdate.action即可

注意点:使用OGNL表达式访问"根"对象中的对象及属性时,不需要前面加"#"号

文件上传 示例源码下载

对于文件上传功能Struts2并没有提出自己的解决方案,但是Struts2为文件上传提供了统一的接口,开发人员在使用上传文件的组件时,并不需要知道太多的细节就可以轻松使用他们,Struts2目前支持三种上传文件组件Commons-FileUpload,cos,pell,例如我们使用Commons-FileUpload为例来快速学习文件上传功能

commons-fileupload依赖(已经内置,无须再次添加)

struts.properties相关配置

struts.multipart.parser=jakarta
struts.multipart.maxSize=2097152

核心上传代码

    @Action(value = "UploadAction", params = {"uploadPath", "D:/"}, results = {
@Result(name = "success", location = "/result.jsp")
})
public String execute() throws Exception {
String fn = "";
if (filename.equals("")) {
fn = uploadPath + uploadFileName;
} else {
fn = uploadPath + filename;
} if (new File(fn).exists()) {
result = "该文件已经存在!";
} else {
FileOutputStream fileOutputStream = new FileOutputStream(fn);
InputStream inputStream = new FileInputStream(upload);
byte[] buffer = new byte[8192];
int count = 0;
while ((count = inputStream.read(buffer)) > 0) {
fileOutputStream.write(buffer, 0, count);
}
fileOutputStream.close();
inputStream.close();
result = "文件上传成功!";
}
return "success";
}

下面我们再进行展示同时上传多个文件的示例,对于同时上传多个文件,我们仅仅需要做一点改变即可,即接收值的属性改成数组或者List集合

    private File[] upload;
private String[] uploadFileName;
    @Action(value = "UploadAction", params = {"uploadPath", "D:/"}, results = {
@Result(name = "success", location = "/result.jsp")
})
public String execute() throws Exception {
for (int i = 0; i < uploadFileName.length; i++) {
String fn = uploadPath + uploadFileName[i];
FileOutputStream fileOutputStream = new FileOutputStream(fn);
InputStream inputStream = new FileInputStream(upload[i]);
byte[] buffer = new byte[8192];
int count = 0;
while ((count = inputStream.read(buffer)) > 0) {
fileOutputStream.write(buffer, 0, count);
}
fileOutputStream.close();
inputStream.close();
}
result = "文件上传成功!";
return "success";
}

我们了解了文件上传那么现在我们再来一起看一下文件的下载,再Struts2中提供了一种使用Stream下载文件的方式,类似于文件和浏览器的一个"代理",通过这个"代理"我们就能控制某某下载文件,如下是一个Download的Action

public InputStream getFileInputStream() {
// 以及文件的mime类型以及创建流
ServletContext context = ServletActionContext.getServletContext();
contentType = context.getMimeType(context.getRealPath(filePath + "/" + fileName));
setContentType(contentType);
return context.getResourceAsStream(filePath + "/" + fileName);
} @Override
@Action(value = "download", params = {"filePath", "/file"}, results = {
@Result(name = SUCCESS, type = "stream",
params = {"contentType", "${contentType}", "inputName", "fileInputStream", "contentDisposition", "attachment;filename=\"${fileName}\""})
})
public String execute() throws Exception {
return SUCCESS;
}

异常处理 示例源码下载

异常处理是任何成熟的MVC框架必备的功能,在Struts2中提供了异常的拦截器,我们可以在struts.xml文件中进行配置异常,以灵活的方式处理异常

配置全局异常

    <package name="default" extends="struts-default" namespace="/">
<global-results>
<result name="exception">/error.jsp</result>
</global-results> <global-exception-mappings>
<exception-mapping exception="java.sql.SQLException" result="exception"></exception-mapping>
</global-exception-mappings> ...
</package>

模拟异常

@ParentPackage("default")
public class ExceptionAction extends ActionSupport { @Override
@Action(value = "testerror", results = {
@Result(name = SUCCESS, location = "/success.jsp")
})
public String execute() throws Exception {
if ("a".equals("a")) {
throw new SQLException("SQL错误!!!");
}
return SUCCESS;
}
}

当发生异常后就会跳转到所配置的error.jsp页面

国际化支持 示例源码下载

Struts2的国际化支持是建立在Java对国际化的支持之上的,对Java的国际化支持进行了封装,下面我们来针对一段优美的诗,我们我们将会展示中文和英文两种页面给访问者

我那美丽的女孩

我的挚爱

无论梦里梦外

去去来来

抬头眺望云端

高不可攀

低头忆你容颜

温柔绚烂

配置Struts2全局资源文件(使用下面两种方式都可以)

在struts.properties中配置
struts.custom.i18n.resources=Resource
在struts.xml中配置
<constant name="struts.custom.i18n.resources" value="Resource"/>

创建两个资源文件(中文和英文)

Resource_en_US.properties

welcome = hello,{0}
content = My beautiful girl, my love, my dream, my dream, my dream, my dream, my dream

Resource_zh_CN.properties

welcome = 你好,{0}
content = 我那美丽的女孩 我的挚爱 无论梦里梦外 去去来来 抬头眺望云端 高不可攀 低头忆你容颜 温柔绚烂

在Action中使用

public class BeautifulGirlAction extends ActionSupport {

    private String username;
private String content;
private String welcome; @Override
@Action(value = "girl", results = {
@Result(name = SUCCESS, location = "/success.jsp")
})
public String execute() throws Exception {
welcome = getText("welcome", new String[]{username});
content = getText("content");
return SUCCESS;
}
...
}

通过下载本小节示例源码访问http://localhost:8080/form.jsp

本章总结

在WEB应用中常见的功能是很多的,很多场景下Struts2都为我们提供了响应的解决方案,本章叙述中在下主要讲述了Struts2的常见的功能的基本使用,即只有广度而没有深度,更为深度的学习还希望小伙伴们查阅相关资料,例如OGNL表达式等...

从零打造在线网盘系统之Struts2框架核心功能全解析的更多相关文章

  1. 从零打造在线网盘系统之Struts2框架起步

    欢迎浏览Java工程师SSH教程从零打造在线网盘系统系列教程,本系列教程将会使用SSH(Struts2+Spring+Hibernate)打造一个在线网盘系统,本系列教程是从零开始,所以会详细以及着重 ...

  2. 从零打造在线网盘系统之Struts2框架配置全解析

    欢迎浏览Java工程师SSH教程从零打造在线网盘系统系列教程,本系列教程将会使用SSH(Struts2+Spring+Hibernate)打造一个在线网盘系统,本系列教程是从零开始,所以会详细以及着重 ...

  3. 从零打造在线网盘系统之Hibernate框架起步

    欢迎浏览Java工程师SSH教程从零打造在线网盘系统系列教程,本系列教程将会使用SSH(Struts2+Spring+Hibernate)打造一个在线网盘系统,本系列教程是从零开始,所以会详细以及着重 ...

  4. 从零打造在线网盘系统之SSH框架整合

    欢迎浏览Java工程师SSH教程从零打造在线网盘系统系列教程,本系列教程将会使用SSH(Struts2+Spring+Hibernate)打造一个在线网盘系统,本系列教程是从零开始,所以会详细以及着重 ...

  5. 从零打造在线网盘系统之Hibernate配置O/R映射

    欢迎浏览Java工程师SSH教程从零打造在线网盘系统系列教程,本系列教程将会使用SSH(Struts2+Spring+Hibernate)打造一个在线网盘系统,本系列教程是从零开始,所以会详细以及着重 ...

  6. 从零打造在线网盘系统之Hibernate查询与更新技术

    欢迎浏览Java工程师SSH教程从零打造在线网盘系统系列教程,本系列教程将会使用SSH(Struts2+Spring+Hibernate)打造一个在线网盘系统,本系列教程是从零开始,所以会详细以及着重 ...

  7. SSH教程从零打造在线网盘系统前言&目录

    本系列教程内容提要 本系列教程是一个学习教程,是关于Java工程师的SSH(Struts2+Spring+Hibernate)系列教程,本教程将会分为四个部分和大家一同打造一个在线网盘系统,由于教程是 ...

  8. vue+nodejs+express+mysql 建立一个在线网盘程序

    vue+nodejs+express+mysql 建立一个在线网盘程序 目录 vue+nodejs+express+mysql 建立一个在线网盘程序 第一章 开发环境准备 1.1 开发所用工具简介 1 ...

  9. Layui框架+PHP打造个人简易版网盘系统

    网盘系统   大家应该都会注册过致命的一些网盘~如百度云.百科介绍:网盘,又称网络U盘.网络硬盘,是由互联网公司推出的在线存储服务,服务器机房为用户划分一定的磁盘空间,为用户免费或收费提供文件的存储. ...

随机推荐

  1. C++对析构函数的误解

    C++析构前言 析构函数在什么时候会自动被调用,在什么时候需要手动来调用,真不好意思说偶学过C++…今日特此拨乱反正. C++析构误解正文 对象在构造的时候系统会分配内存资源,对一些数据成员进行初始化 ...

  2. 【JavaScript】使用setInterval()函数作简单的轮询操作

    轮询(Polling)是一种CPU决策怎样提供周边设备服务的方式,又称"程控输出入"(Programmed I/O). 轮询法的概念是.由CPU定时发出询问.依序询问每个周边设备是 ...

  3. spark 安装配置

    最佳参考链接 https://opensourceteam.gitbooks.io/bigdata/content/spark/install/spark-160-bin-hadoop26an_zhu ...

  4. 如何解决ChemDraw引起的系统崩溃

    运行ChemDraw应用程序时,一般不会引起系统崩溃,但在使用CS software产品可能会引发计算机崩溃.为了方便广大用户的使用,本教程将教授大家如何解决ChemDraw运行中引起的系统崩溃. 当 ...

  5. tiny6410nfs挂载问题

    一.制作根文件系统 1.下载最新版的 busybox 地址:http://www.busybox.net/downloads/ 2.编译busybox.先make menuconfig ,修改以下:B ...

  6. web.xml 中的listener、filter、servlet 加载顺序及其【配置详解】

    在项目中总会遇到一些关于加载的优先级问题,近期也同样遇到过类似的,所以自己查找资料总结了下,下面有些是转载其他人的,毕竟人家写的不错,自己也就不重复造轮子了,只是略加点了自己的修饰. 首先可以肯定的是 ...

  7. vertica时间计算SQL语句实例:统计一天内登录的用户

    SQL语句实例: select count(id) as num from public.user where cast((CURRENT_TIMESTAMP-login_timed) day as ...

  8. UVA 11542 - Square(高斯消元)

    UVA 11542 - Square 题目链接 题意:给定一些数字.保证这些数字质因子不会超过500,求这些数字中选出几个,乘积为全然平方数,问有几种选法 思路:对每一个数字分解成质因子后.发现假设要 ...

  9. Java类的设计----访问控制

    访问控制 可以对Java类中定义的属性和方法进行访问控制----规定不同的保护等级: public.protected.default.private //仅在类的内部可以访问. private St ...

  10. swift学习笔记之--方法

    一.说明 跟oc一样,面向对象,swift重点额方法可以分为2大类: (1)实例方法 oc中为减号方法(对象方法) (2)类型方法 oc中的加号方法(类方法) 二.实例方法 只能是对象调用的方法 代码 ...