Struts
標籤(空格分隔): SSH Struts
一、Struts基本介紹
(1)Struts基本概念
Struts是一個web框架
(2)爲什麼有struts?
Struts是基於MVC的web框架,解決了MVC設計的規範問題。
(3)Struts的優缺點
優點:
1. 程序更加規範
2. 開發效率提高
3. 程序可讀性提高
4. 程序可維護性提高
缺點:
1. form表單優點雞肋
2. action是單態的(對網站的併發處理有影響)
二、Struts原理
(1)Struts運行原理圖
下面以登錄驗證時序圖來舉例說明:
三、快速入門案例
(1)手動配置Struts
以上圖登錄爲例,步驟如下:
1. 新建web工程,導入struts jar包
2. 創建login.jsp頁面
3. 編寫ActionForm和Action
4. 編寫structs-config.xml文件,用於配置actionform和action的對應關係及跳轉,一般放在WEB-INF目錄下。
5. 編寫welcome.jsp和error.jsp頁面
6. 在web.xml中配置ActionServlet
7. 開始使用我們的structs
8. struts中文亂碼問題->過濾器
struts-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts-config PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 1.3//EN"
"http://struts.apache.org/dtds/struts-config_1_3.dtd">
<struts-config>
<!-- 配置單 -->
<form-beans>
<!-- type 指明actionform的完整類名 -->
<form-bean name="userForm" type="com.demo.form.UserForm"/>
</form-beans>
<!-- 配置action -->
<action-mappings>
<!--name用來關聯action和actionform, path指定訪問action的路徑 (注意斜槓), type指定action類的完整類名 -->
<!--scope="request" 表示該action對應的表單對象的生命週期request=request.setAttribute("userForm",userForm)
scope="session" 表示該action對應的表單對象的生命週期session=request.getSession() .setAttribute("userForm",userForm)-->
<action path="/login" name="userForm" scope="request" type="com.demo.action.LoginAction">
<!-- 配置頁面跳轉 -->
<forward name="success" path="/WEB-INF/welcome.jsp"/>
<forward name="error" path="/WEB-INF/error.jsp"/>
</action>
</action-mappings>
</struts-config>
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">
<servlet>
<servlet-name>action</servlet-name>
<servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
<init-param>
<param-name>config</param-name>
<param-value>/WEB-INF/struts-config.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>action</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
UserForm.java
package com.demo.form;
import org.apache.struts.action.ActionForm;
public class UserForm extends ActionForm {
private static final long serialVersionUID = -5728373396473448952L;
private String username;
private String password;
//保證set和get方法名和前端form中input的name一致
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;
}
}
LoginActin.java
package com.demo.action;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import com.demo.form.UserForm;
public class LoginAction extends Action {
@Override
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws Exception {
// TODO Auto-generated method stub
UserForm userForm = (UserForm) form;
//System.out.println("username : "+userForm.getUsername());
if(userForm!=null &&
"lawen".equals(userForm.getUsername()) &&
"123456".equals(userForm.getPassword())){
return mapping.findForward("success");
}
return mapping.findForward("error");
}
}
(2) Structs需要注意的細節
struts底層使用到反射機制,因此在配置action和form-bean時type屬性必須指明相應類的完整路徑,在action類中,setter和getter方法名應該和form表單的屬性name一致。actionform scope可選request和session
(3)使用過濾器解決structs 表單中文亂碼問題
步驟如下:開發一個過濾器,並設置request,setCharacterEncoding("utf-8");
Filter.java
package com.demo.filter;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class MyFilter1 extends HttpServlet implements Filter {
@Override
public void doFilter(ServletRequest arg0, ServletResponse arg1,
FilterChain arg2) throws IOException, ServletException {
// TODO Auto-generated method stub
arg0.setCharacterEncoding("utf-8"); //設置接收編碼
arg2.doFilter(arg0, arg1); //必須
}
@Override
public void init(FilterConfig arg0) throws ServletException {
// TODO Auto-generated method stub
}
}
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">
<servlet>
<servlet-name>action</servlet-name>
<servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
<init-param>
<param-name>config</param-name>
<param-value>/WEB-INF/struts-config.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>action</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
<filter>
<filter-name>MyFilter1</filter-name>
<filter-class>com.demo.filter.MyFilter1</filter-class>
</filter>
<filter-mapping>
<filter-name>MyFilter1</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
三、struts-config配置詳解
struts-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts-config PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 1.1//EN"
"http://jakarta.apache.org/struts/dtds/struts-config.dtd">
<!-- struts-config.xml中的元素必須按照上述doc指令中的dtd文檔定義順序書寫,本例即遵從了dtd定義順序 -->
<!-- struts-config是整個xml的根元素,其他元素必須被包含其內 -->
<struts-config>
<!--
名稱:data-sources
描述:data-sources元素定義了web App所需要使用的數據源
數量:最多一個
子元素:data-source
-->
<data-sources>
<!--
名稱:data-source
描述:data-source元素定義了具體的數據源
數量:任意多個
屬性:
@key:當需要配置多個數據源時,相當於數據源的名稱,用來數據源彼此間進行區別
@type:可以使用的數據源實現的類,一般來自如下四個庫
Poolman,開放源代碼軟件
Expresso,Jcorporate
JDBC Pool,開放源代碼軟件
DBCP,Jakarta
-->
<data-source key="firstOne" type="org.apache.commons.dbcp.BasicDataSource">
<!--
名稱:set-property
描述:用來設定數據源的屬性
屬性:
@autoCommit:是否自動提交 可選值:true/false
@description:數據源描述
@driverClass:數據源使用的類
@maxCount:最大數據源連接數
@minCount:最小數據源連接數
@user:數據庫用戶
@password:數據庫密碼
@url:數據庫url
-->
<set-property property="autoCommit" value="true"/>
<set-property property="description" value="Hello!"/>
<set-property property="driverClass" value="com.mysql.jdbc.Driver"/>
<set-property property="maxCount" value="10"/>
<set-property property="minCount" value="2"/>
<set-property property="user" value="root"/>
<set-property property="password" value=""/>
<set-property property="url" value="jdbc:mysql://localhost:3306/helloAdmin"/>
</data-source>
</data-sources>
<!--
名稱:form-beans
描述:用來配置多個ActionForm Bean
數量:最多一個
子元素:form-bean
-->
<form-beans>
<!--
名稱:form-bean
描述:用來配置ActionForm Bean
數量:任意多個
子元素:form-property
屬性:
@className:指定與form-bean元素相對應的配置類,一般默認使用org.apaceh.struts.config.FormBeanConfig,如果自定義,則必須繼承 FormBeanConfig
@name:必備屬性!爲當前form-bean制定一個全局唯一的標識符,使得在整個Struts框架內,可以通過該標識符來引用這個ActionForm Bean。
@type:必備屬性!指明實現當前ActionForm Bean的完整類名。
-->
<form-bean name="Hello" type="myPack.Hello">
<!--
名稱:form-property
描述:用來設定ActionForm Bean的屬性
數量:根據實際需求而定,例如,ActionForm Bean對應的一個登陸Form中有兩個文本框,name和password,ActionForm Bean中也有這兩個字段,則此處編寫兩個form-property來設定屬性
屬性:
@className:指定與form-property相對應的配置類,默認是org.apache.struts.config.FormPropertyConfig,如果自定義,則必須繼承FormPropertyConfig類
@name:所要設定的ActionForm Bean的屬性名稱
@type:所要設定的ActionForm Bean的屬性值的類
@initial:當前屬性的初值
-->
<form-property name="name" type="java.lang.String"/>
<form-property name="number" type="java.lang.Iteger" initial="18"/>
</form-bean>
</form-beans>
<!--
名稱:global-exceptions
描述:處理異常
數量:最多一個
子元素:exception
-->
<global-exceptions>
<!--
名稱:exception
描述:具體定義一個異常及其處理
數量:任意多個
屬性:
@className:指定對應exception的配置類,默認爲org.apache.struts.config.ExceptionConfig
@handler:指定異常處理類,默認爲org.apache.struts.action.ExceptionHandler
@key:指定在Resource Bundle種描述該異常的消息key
@path:指定當發生異常時,進行轉發的路徑
@scope:指定ActionMessage實例存放的範圍,默認爲request,另外一個可選值是session
@type:必須要有!指定所需要處理異常類的名字。
@bundle:指定資源綁定
-->
<exception
key="hello.error"
path="/error.jsp"
scope="session"
type="hello.HandleError"/>
</global-exceptions>
<!--
名稱:global-forwards
描述:定義全局轉發
數量:最多一個
子元素:forward
-->
<global-forwards>
<!--
名稱:forward
描述:定義一個具體的轉發
數量:任意多個
屬性:
@className:指定和forward元素對應的配置類,默認爲org.apache.struts.action.ActionForward
@contextRelative:如果爲true,則指明使用當前上下文,路徑以“/”開頭,默認爲false
@name:必須配有!指明轉發路徑的唯一標識符
@path:必須配有!指明轉發或者重定向的URI。必須以"/"開頭。具體配置要與contextRelative相應。
@redirect:爲true時,執行重定向操作,否則執行請求轉發。默認爲false
-->
<forward name="A" path="/a.jsp"/>
<forward name="B" path="/hello/b.do"/>
</global-forwards>
<!--
名稱:action-mappings
描述:定義action集合
數量:最多一個
子元素:action
-->
<action-mappings>
<!--
名稱:action
描述:定義了從特定的請求路徑到相應的Action類的映射
數量:任意多個
子元素:exception,forward(二者均爲局部量)
屬性:
@attribute:制定與當前Action相關聯的ActionForm Bean在request和session範圍內的名稱(key)
@className:與Action元素對應的配置類。默認爲org.apache.struts.action.ActionMapping
@forward:指名轉發的URL路徑
@include:指名包含的URL路徑
@input:指名包含輸入表單的URL路徑,表單驗證失敗時,請求會被轉發到該URL中
@name:指定和當前Acion關聯的ActionForm Bean的名字。該名稱必須在form-bean元素中定義過。
@path:指定訪問Action的路徑,以"/"開頭,沒有擴展名
@parameter:爲當前的Action配置參數,可以在Action的execute()方法中,通過調用ActionMapping的getParameter()方法來獲取參數
@roles:指定允許調用該Aciton的安全角色。多個角色之間用逗號分割。處理請求時,RequestProcessor會根據該配置項來決定用戶是否有調用該Action的權限
@scope:指定ActionForm Bean的存在範圍,可選值爲request和session。默認爲session
@type:指定Action類的完整類名
@unknown:值爲true時,表示可以處理用戶發出的所有無效的Action URL。默認爲false
@validate:指定是否要先調用ActionForm Bean的validate()方法。默認爲true
注意:如上屬性中,forward/include/type三者相斥,即三者在同一Action配置中只能存在一個。
-->
<action path="/search"
type="addressbook.actions.SearchAction"
name="searchForm"
scope="request"
validate="true"
input="/search.jsp">
<forward name="success" path="/display.jsp"/>
</action>
</action-mappings>
<!--
名稱:controller
描述:用於配置ActionServlet
數量:最多一個
屬性:
@bufferSize:指定上傳文件的輸入緩衝的大小.默認爲4096
@className:指定當前控制器的配置類.默認爲org.apache.struts.config.ControllerConfig
@contentType:指定相應結果的內容類型和字符編碼
@locale:指定是否把Locale對象保存到當前用戶的session中,默認爲false
@processorClass:指定負責處理請求的Java類的完整類名.默認org.apache.struts.action.RequestProcessor
@tempDir:指定文件上傳時的臨時工作目錄.如果沒有設置,將才用Servlet容器爲web應用分配的臨時工作目錄.
@nochache:true時,在相應結果中加入特定的頭參數:Pragma ,Cache-Control,Expires防止頁面被存儲在可數瀏覽器的緩存中,默認爲false
-->
<controller
contentType="text/html;charset=UTF-8"
locale="true"
processorClass="CustomRequestProcessor">
</controller>
<!--
名稱:message-resources
描述:配置Resource Bundle.
數量:任意多個
屬性:
@className:指定和message-resources對應的配置類.默認爲org.apache.struts.config.MessageResourcesConfig
@factory:指定資源的工廠類,默認爲org.apache.struts.util.PropertyMessageResourcesFactory
@key:
@null:
@parameter:
-->
<message-resources
null="false"
parameter="defaultResource"/>
<message-resources
key="images"
null="false"
parameter="ImageResources"/>
<!--
名稱:plug-in
描述:用於配置Struts的插件
數量:任意多個
子元素:set-property
屬性:
@className:指定Struts插件類.此類必須實現org.apache.struts.action.PlugIn接口
-->
<plug-in
className="org.apache.struts.validator.ValidatorPlugIn">
<!--
名稱:set-property
描述:配置插件的屬性
數量:任意多個
屬性:
@property:插件的屬性名稱
@value:該名稱所配置的值
-->
<set-property
property="pathnames"
value="/WEB-INF/validator-rules.xml,/WEB-INF/vlaidation.xml"/>
</plug-in>
</struts-config>
一、爲struts配置web.xml
1,配置ActionServlet(only one),使其接收應用程序收到的所有請求
分爲兩步,a:使用servlet元素配置servlet實例,做servlet-mapping
<web-app>
<servlet>
<servlet-name>storefront</servlet-name>
<servlet-class>完全限定的類名</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>storefront</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
</web-map>
2,配置初始化參數:init-param,以name/value表示<param-name><param-value>
config :默認爲/WEB-INF/struts-config.xml
config/sub1:config/... 從附加的struts配置文件中加在資程序sub1
debug:servlet的調試detail
detail:Digester的調試detail
convertHack
3,<taglib>使用struts提供的標記庫時必須配置包括
<taglib-uri>識別web應用程序所使用的標記庫,必須是有效的
<taglib-location>指定了標記庫描述文件的位置
4,<welcome-file-list>配置在web app中輸入有效的,但不完整的url所使用的default resource;不使用servlet映射
<welcome-file>起始和結束都沒有/符號
5,<error-page>
(<error-code> <location>)
<<exception-type><location>
</error-page>
二、Struts配置文件
ApplicationConfig: 包含了struts配置文件中的所有信息
1, <data-source>
<set-property property=““ value=““/>
<data-source>
2,<form-beans>
<form-bean name=“loginForm“ type=“完全限定的類名,是ActionForm的子類“>
<form-property name=““ type=““/>
</form-bean>
<form-bean
</form-beans>
3,<global-exceptions>
4,<global-forwards>
在Struts1.3中已經取消了<data-sources>標籤,也就是說只能在1.2版中配置,因爲Apache不推薦在struts-config.xml中配置數據源。所以建議不要在struts中配置數據源,如果你用了hibernate或spring得話就可以在hibernate配置文件或spring文件配數據源如果都沒用就到tomcat中配置
四、JSTL標籤庫(JSP Standard Tag Libaray)
域對象優先級:pageContext > request > session > application
五、Struts標籤
(1)HTML標籤
(2)bean標籤
(3)logic標籤
六、Struts文件上傳及下載
(1)上傳
upload.jsp
<form action="/structs1/login.do" method="post" enctype="multipart/form-data">
photo: <input type="file" name="photo"><br>
<input type="submit" value="上傳">
</form>
UserForm
package com.demo.form;
import org.apache.struts.action.ActionForm;
import org.apache.struts.upload.FormFile;
public class UserForm extends ActionForm {
private static final long serialVersionUID = -5728373396473448952L;
private FormFile photo;
//保證set和get方法名和前端form中input的name一致
public FormFile getPhoto() {
return photo;
}
public void setPhoto(FormFile photo) {
this.photo = photo;
}
}
uploadAction
package com.demo.action;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.upload.FormFile;
import com.demo.form.UserForm;
/*action是單態的*/
public class LoginAction extends Action {
@Override
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws Exception {
// TODO Auto-generated method stub
UserForm userForm = (UserForm) form;
FormFile photoFile = userForm.getPhoto();
System.out.println("filename : "+photoFile.getFileName()+" filesize:"+
photoFile.getFileSize());
String path=this.getServlet().getServletContext().getRealPath("file");
System.out.println(path+"\\"+photoFile.getFileName());
OutputStream out=null;
InputStream in = null;
try {
in = photoFile.getInputStream();
out = new FileOutputStream(path+"\\"+photoFile.getFileName());
byte buff[] = new byte[1024];
int len = 0;
while((len=in.read(buff))>0){
out.write(buff, 0, len);
}
System.out.println("文件保存成功");
} catch (Exception e) {
// TODO: handle exception
return mapping.findForward("error");
}finally{
if(out!=null)
out.close();
if(in!=null)
in.close();
}
return mapping.findForward("success");
}
}
(4)下載
downloadAction
response.setHeader("Content-Disposition", "attachment;filename=test.pdf");
//獲取要下載文件的全路徑
String path = this.getServletContext().getRealPath("/images/test.pdf");
//創建文件流
FileInputStream in = new FileInputStream(path);
byte buff[] = new byte[1024];
int len = 0;
OutputStream out = response.getOutputStream();
while((len=in.read(buff))>0){
out.write(buff, 0, len);
}
in.close();
out.close();