歡迎瀏覽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表達式等...