欢迎浏览Java工程师SSH教程从零打造在线网盘系统系列教程,本系列教程将会使用SSH(Struts2+Spring+Hibernate)打造一个在线网盘系统,本系列教程是从零开始,因此会详细以及着重地阐述SSH三个框架的基础知识,第四部分将会进入项目实战,若是您已经对SSH框架有所掌握,那么能够直接浏览第四章,源码均提供在GitHub/ssh-network-hard-disk上供你们参阅html
我相信你在使用任何一个MVC框架的时候都会接触到如下功能,你必需要会使用这些功能才可以在Struts2中熟练的解决大多数问题前端
Struts2接收参数有三种方式,java
Servlet APIgit
@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方法github
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与属性名一致sql
<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()); }
模型驱动apache
@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()); } } 
对于前端传递的参数来说,存在太多不稳定性,因此对于参数的校验是必不可少的,对于校验来讲大致上分为两种,一种是前端校验,一种是后端校验,前端校验的方法在这里就再也不累述,这里仅仅讲述Struts2如何使用Validation校验框架后端
获取参数数组
private String username; private String password; getter and setter......
在Action同级目录增长
<!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存取值
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表达式等...