摘要:文件上傳通過這個攔截器攔截器的設計就是基于組件設計的應用再次回顧攔截器基礎在開始講解的時候已經(jīng)說明過了這個文件,它定義了的所有攔截器。由于我們配置了自定義攔截器,那么默認的攔截器棧是不會執(zhí)行的。
什么是攔截器
攔截器Interceptor.....攔截器是Struts的概念,它與過濾器是類似的...可以近似于看作是過濾器
為什么我們要使用攔截器前面在介紹Struts的時候已經(jīng)講解過了,Struts為我們實現(xiàn)了很多的功能,比如數(shù)據(jù)自動封裝阿..文件上傳功能阿....Struts為我們提供的這些功能都是通過攔截器完成的......
數(shù)據(jù)自動封裝通過
文件上傳通過
攔截器的設計就是基于組件設計的應用!
再次回顧攔截器基礎在開始講解Struts的時候已經(jīng)說明過了struts-default.xml這個文件,它定義了Struts的所有攔截器。因為我們在啟動服務器的時候會自動裝載這個文件,因此我們才可以在Action中使用到Struts為我們提供的功能【數(shù)據(jù)自動封裝...文件上傳】
在struts-default.xml中定義的攔截器就有32個之多,Struts2為了方便我們對攔截器的引用,提供了攔截器棧的定義。
dojo..*,^struts..*,^session..*,^request..*,^application..*,^servlet(Request|Response)..*,parameters...* input,back,cancel,browse input,back,cancel,browse
也就是說:當我們要引用多個攔截器的時候,只要把攔截器都放在棧里頭,在外邊引用攔截器即可!
值得注意的是:Struts2默認執(zhí)行的是默認攔截器棧,一旦用戶有指定執(zhí)行哪些攔截器,那么默認的攔截器棧就不會被執(zhí)行!
自定義攔截器Struts2允許我們自定義攔截器,這就使我們能夠更加靈活地操作Struts2這個框架了!
Struts2提供了Interceptor這個攔截器接口,只要我們實現(xiàn)這個接口,那么這就算是自定義開發(fā)攔截器了。
當然啦,大部分時候,我們定義攔截器都是繼承AbstractInterceptor這個類....為了學習攔截器的內容,下面就實現(xiàn)Interceptor這個接口了。
編寫攔截器類當實現(xiàn)該接口時,有3個需要我們實現(xiàn)的方法:
public class MyInterceptor implements Interceptor { @Override public void destroy() { } @Override public void init() { } @Override public String intercept(ActionInvocation actionInvocation) throws Exception { return null; } }
init()和destory()都是和攔截器執(zhí)行順序有關的方法,我們現(xiàn)在先不理會....首先來講解intercept這個方法
/** * @param actionInvocation 攔截器的執(zhí)行狀態(tài) */ @Override public String intercept(ActionInvocation actionInvocation) throws Exception { //調用invoke()方法,代表著放行執(zhí)行下一個攔截器,如果沒有攔截器了,那么就執(zhí)行Action的業(yè)務代碼 actionInvocation.invoke(); return null; }
這很容易就能讓我們想起在學習過濾器中的doFilter()方法,其實是差不多的!
在struts.xml中配置像Struts默認的攔截器一樣,我們自定義的攔截器是需要我們在struts中配置的。
由于我們配置了自定義攔截器,那么struts默認的攔截器棧是不會執(zhí)行的。如果我們想要使用默認攔截器棧的功能,就必須把它配置在我們自定義的棧中!
攔截器的執(zhí)行順序/index.jsp
我們來觀察攔截器和Action類的執(zhí)行順序...只要在對應的方法上向控制臺輸出就行了!
攔截器
public class MyInterceptor implements Interceptor { @Override public void destroy() { System.out.println("我是攔截器的銷毀方法"); } @Override public void init() { System.out.println("我是攔截器的初始化方法"); } /** * @param actionInvocation 攔截器的執(zhí)行狀態(tài) */ @Override public String intercept(ActionInvocation actionInvocation) throws Exception { System.out.println("我是攔截器的攔截方法"); //調用invoke()方法,代表著放行執(zhí)行下一個攔截器,如果沒有攔截器了,那么就執(zhí)行Action的業(yè)務代碼 //可看成是過濾器的doFilter()方法 actionInvocation.invoke(); return null; } }
Action類
public class TestAction extends ActionSupport { public TestAction() { System.out.println("我是Action類,我被初始化了!"); } @Override public String execute() throws Exception { System.out.println("我是Action類的執(zhí)行方法"); return null; } }效果
從效果圖我們可以看出,他們的執(zhí)行順序是這樣的:
當服務器開啟的時候,會執(zhí)行攔截器的init()方法
當訪問Action時,Action實例被創(chuàng)建
創(chuàng)建完Action實例,會調用攔截器的interceptor()方法
最后,執(zhí)行Action的execute()方法
其實很好理解,之前我們使用Struts為我們提供數(shù)據(jù)自動封裝功能的時候,是這樣子的:
服務器啟動,加載配置文件的信息
初始化默認的攔截器棧
當用戶訪問Action時,創(chuàng)建Action的實例。拿到Action具體的信息【成員變量、setter和getter】
執(zhí)行攔截器具體的內容,根據(jù)Action具體的信息,把web端的數(shù)據(jù)封裝到Action上
最后在execute()就可以得到封裝后的數(shù)據(jù)了!
攔截器應用案例需求:當用戶登陸成功,跳轉到顯示用戶的JSP頁面中。當用戶登陸失敗,重新返回登陸界面。如果用戶直接訪問顯示用戶的JSP頁面,那么返回到登陸界面
分析實現(xiàn)這個需求,我們可以使用過濾器的。只要獲取用戶的請求URL,再判斷URL是不是為list.jsp,如果是,我們返回到登陸的界面就好了。
現(xiàn)在,為了對攔截器的理解,我們使用攔截器去完成這個功能!
搭建配置環(huán)境導入我們c3p0.xml文件
導入c3p0開發(fā)包
導入mysql開發(fā)包
寫數(shù)據(jù)庫連接池工具類
dbUtils開發(fā)包
8個struts2需要用到的開發(fā)包
創(chuàng)建數(shù)據(jù)庫表,導入數(shù)據(jù)
編寫entitypackage zhongfucheng.entity; /** * Created by ozc on 2017/5/3. */ public class User { private String id ; private String username; private String cellphone; private String email; private String password; public String getId() { return id; } public void setId(String id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getCellphone() { return cellphone; } public void setCellphone(String cellphone) { this.cellphone = cellphone; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } }編寫DAO
package zhongfucheng.dao; import org.apache.commons.dbutils.QueryRunner; import org.apache.commons.dbutils.handlers.BeanHandler; import org.apache.commons.dbutils.handlers.BeanListHandler; import zhongfucheng.entity.User; import zhongfucheng.utils.Utils2DB; import java.sql.SQLException; import java.util.List; /** * Created by ozc on 2017/5/3. */ public class UserDao { public User login(User user) { try { String sql = "SELECT * FROM user WHERE username = ? AND password = ?"; QueryRunner queryRunner = new QueryRunner(Utils2DB.getDataSource()); return (User) queryRunner.query(sql, new BeanHandler(User.class), new Object[]{user.getUsername(), user.getPassword()}); } catch (SQLException e) { new RuntimeException("登陸失敗了!"); } return null; } public List編寫ServicegetAll() { try { String sql = "SELECT * FROM user"; QueryRunner queryRunner = new QueryRunner(Utils2DB.getDataSource()); return (List ) queryRunner.query(sql, new BeanListHandler(User.class)); } catch (SQLException e) { new RuntimeException("登陸失敗了!"); } return null; } }
public class Service { UserDao userDao = new UserDao(); public User login(User user) { return userDao.login(user); } public List編寫登陸的JSP頁面getAll() { return userDao.getAll(); } }
<%@ page contentType="text/html;charset=UTF-8" language="java" %>編寫處理請求的Action登陸頁面
package zhongfucheng.action; import com.opensymphony.xwork2.ActionContext; import zhongfucheng.entity.User; import zhongfucheng.service.Service; import java.util.List; import java.util.Map; /** * Created by ozc on 2017/5/3. */ public class UserAction { /****************1.封裝數(shù)據(jù)********************/ private User user; public User getUser() { return user; } public void setUser(User user) { this.user = user; } /***************2.調用Service*******************/ Service service = new Service(); //登陸 public String login() { User user = service.login(this.user); if (user == null) { return "input"; } else { //將user的信息存到Session域對象中 Mapstruts.xml配置文件session = ActionContext.getContext().getSession(); session.put("user", user); //登陸成功 return "login"; } } //查看user信息 public String list() { //拿到所有用戶的信息 List users = service.getAll(); //存到request域對象中 Map request = ActionContext.getContext().getContextMap(); request.put("users", users); return "list"; } }
user_list /WEB-INF/list.jsp
到目前為止,我們登陸或者不登陸都可以得到用戶的具體信息....這是不合理的
我們想要的效果是:只有用戶正在調用login方法,或者該用戶已經(jīng)登陸了,才可以查看具體的用戶信息。
因此,我們們要攔截它們,只有用戶調用的是login方法時或者已經(jīng)登陸的情況下,才能跳轉到對應的顯示頁面
攔截器package zhongfucheng; import com.opensymphony.xwork2.ActionContext; import com.opensymphony.xwork2.ActionInvocation; import com.opensymphony.xwork2.ActionProxy; import com.opensymphony.xwork2.interceptor.AbstractInterceptor; /** * Created by ozc on 2017/5/3. */ public class Interceptor extends AbstractInterceptor{ @Override public String intercept(ActionInvocation actionInvocation) throws Exception { //得到正在執(zhí)行的代理對象 ActionProxy proxy = actionInvocation.getProxy(); //通過代理對象得到正在執(zhí)行的方法 String method = proxy.getMethod(); //如果方法的名字不是login,那么就讓他們返回到login頁面上 if (!method.equals("login")) { //查看用戶是否登陸了 Object user = ActionContext.getContext().getSession().get("user"); //如果沒有登陸,回到login頁面 if (user == null) { return "input"; } else { //登陸了,那么就讓它訪問具體的用戶信息頁面 return actionInvocation.invoke(); } } else { //如果是訪問login方法,那么就讓它執(zhí)行 return actionInvocation.invoke(); } } }Struts.xml
效果:user_list /WEB-INF/list.jsp /login.jsp
只有當用戶登陸了才能查看用戶具體信息,直接訪問Action會跳轉回
Struts2其他攔截器 計時攔截器Struts2自帶了計時攔截器,也就是用來統(tǒng)計每個Action執(zhí)行的時間
執(zhí)行等待攔截器如果頁面執(zhí)行得太慢了,Struts2還提供了執(zhí)行等待攔截器,也就是說,當頁面加載得太久了,就跳轉到對應的提示頁面...當服務器執(zhí)行完畢了,也跳轉到相對應的頁面
Struts2防止表單重復提交攔截器 回顧防止表單重復提交當我們學習Session的時候已經(jīng)通過Session來編寫了一個防止表單重復提交的小程序了,我們來回顧一下我們當時是怎么做的:
在Servlet上生成獨一無二的token,保存在Session域中,并交給JSP頁面
JSP頁面在提交表單數(shù)據(jù)的時候,把token放在隱藏域中...一起帶過去給Servlet
Servlet判斷用戶有沒有帶token值過來,判斷token的值是否和Session的相匹配
如果用戶是第一次提交的話,那么就允許用戶的請求,接著就把保存在Session中的token值去除
等用戶想要再次提交的時候,Servlet發(fā)現(xiàn)Session中并沒有token了,所以不搭理用戶的請求
我們以前寫表達重復提交就花了這么幾個步驟...如果有興趣的同學可以看一下以前的實現(xiàn)思路:http://blog.csdn.net/hon_3y/article/details/54799494#t11
Struts2防止表單重復提交Struts2是簡化我們的開發(fā)的,表單重復提交也是一件非常常用的功能...Struts2也為我們實現(xiàn)了...當然啦,也是通過攔截器來實現(xiàn)
它的實現(xiàn)原理和我們以前寫的思路幾乎一致...它不需要另外寫一個組件來生成token值,struts2標簽就有這么一個功能...因此是十分方便的
為了熟悉一下Struts2,我們也使用Struts2來編寫一下上圖的程序...
編寫DAOpackage zhongfucheng.dao; import org.apache.commons.dbutils.QueryRunner; import org.apache.commons.dbutils.handlers.BeanHandler; import org.apache.commons.dbutils.handlers.BeanListHandler; import zhongfucheng.entity.User; import zhongfucheng.utils.Utils2DB; import java.sql.SQLException; import java.util.List; /** * Created by ozc on 2017/5/3. */ public class UserDao { public void add(User user) { try { String sql = "INSERT INTO user(id,username,cellphone,password,address) VALUES (?,?,?,?,?)"; QueryRunner queryRunner = new QueryRunner(Utils2DB.getDataSource()); queryRunner.update(sql, new Object[]{user.getId(), user.getUsername(), user.getCellphone(), user.getPassword(),user.getAddress()}); } catch (SQLException e) { new RuntimeException("登陸失敗了!"); } } public User findUser(String id) { try { String sql = "SELECT * FROM user WHERE id=?"; QueryRunner queryRunner = new QueryRunner(Utils2DB.getDataSource()); return (User) queryRunner.query(sql, new BeanHandler(User.class), new Object[]{id}); } catch (SQLException e) { new RuntimeException("登陸失敗了!"); } return null; } public List編寫servicegetAll() { try { String sql = "SELECT * FROM user"; QueryRunner queryRunner = new QueryRunner(Utils2DB.getDataSource()); return (List ) queryRunner.query(sql, new BeanListHandler(User.class)); } catch (SQLException e) { new RuntimeException("登陸失敗了!"); } return null; } public void updateUser(User user) { try { String sql = "UPDATE user SET username=?,password=?,cellphone=? WHERE id=?"; QueryRunner queryRunner = new QueryRunner(Utils2DB.getDataSource()); queryRunner.update(sql, new Object[]{user.getUsername(), user.getPassword(), user.getCellphone(), user.getId()}); } catch (SQLException e) { new RuntimeException("登陸失敗了!"); } } }
package zhongfucheng.service; import zhongfucheng.dao.UserDao; import zhongfucheng.entity.User; import zhongfucheng.utils.WebUtils; import java.util.List; /** * Created by ozc on 2017/5/3. */ public class Service { UserDao userDao = new UserDao(); public void add(User user) { //手動設置id,因為在數(shù)據(jù)庫表我沒使用自動增長id user.setId(WebUtils.makeId()); //這是以前的表,規(guī)定要address,只能手動設置了 user.setAddress("廣州"); userDao.add(user); } public User findUser(String id) { return userDao.findUser(id); } public List開發(fā)步驟getAll() { return userDao.getAll(); } public void updateUser(User user) { userDao.updateUser(user); } }
編寫添加用戶JSP
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@taglib prefix="s" uri="/struts-tags" %>
使用了模型驅動封裝數(shù)據(jù),添加用戶
//這里一定要實例化 User user = new User(); public User getUser() { return user; } public void setUser(User user) { this.user = user; } @Override public User getModel() { return user; } /*******調用service********/ Service service = new Service(); public String register() throws Exception { service.add(user); //注冊成功,就跳轉到list()方法,list方法就跳轉到查看所有用戶頁面了! return list(); }
列出全部的用戶數(shù)據(jù),提供修改功能,需要把id傳遞過去,明確修改的是哪一個用戶
<%-- Created by IntelliJ IDEA. User: ozc Date: 2017/5/2 Time: 18:24 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> <%@ taglib prefix="s" uri="/struts-tags" %>列出下載頁面
用戶id | 用戶姓名 | 用戶密碼 | 用戶電話 | 操作 |
${user.id} | ${user.username} | ${user.password} | ${user.cellphone} | 修改 |
Action得到web帶過來的id,找到對象,添加到值棧中(數(shù)據(jù)回顯)
public String updatePage() throws Exception { //得到用戶帶過來的id,根據(jù)id查找對象 User user222 = service.findUser(user.getId()); ActionContext.getContext().getValueStack().push(user222); return "updatePage"; }
修改用戶的JSP頁面,使用Struts2提供的回顯技術,并把id通過隱藏域帶過去給Action..最終是通過id來修改用戶的數(shù)據(jù)
效果 防止表單重復提交
上面我們已經(jīng)完成了大部分的功能了,但當我們如果提交之后,再刷新頁面,那么表單的數(shù)據(jù)就會重復提交...我們使用Struts2我們提供的防止表單重復提交的功能把!
在需要提交的表單上使用token標簽用戶名: |
密碼: |
電話: |
token攔截器默認是不會啟動的,也就是說:需要我們手動配置...
當我們配置攔截器的時候,Struts2默認的攔截器是不會執(zhí)行的,所以要把Struts2默認的攔截器也寫上
register /list.jsp /update.jsp /login.jsp /user_list
當我們重復提交的時候,它會報錯,因此,如果它報錯了,我們就跳轉到register頁面把
測試如果文章有錯的地方歡迎指正,大家互相交流。習慣在微信看技術文章,想要獲取更多的Java資源的同學,可以關注微信公眾號:Java3y
文章版權歸作者所有,未經(jīng)允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/68742.html
摘要:前言由于寫的文章已經(jīng)是有點多了,為了自己和大家的檢索方便,于是我就做了這么一個博客導航。 前言 由于寫的文章已經(jīng)是有點多了,為了自己和大家的檢索方便,于是我就做了這么一個博客導航。 由于更新比較頻繁,因此隔一段時間才會更新目錄導航哦~想要獲取最新原創(chuàng)的技術文章歡迎關注我的公眾號:Java3y Java3y文章目錄導航 Java基礎 泛型就這么簡單 注解就這么簡單 Druid數(shù)據(jù)庫連接池...
摘要:也就是說映射器就是用于處理什么樣的請求提交給處理。這和是一樣的提交參數(shù)的用戶名編號提交配置處理請求注冊映射器包框架接收參數(shù)設置無參構造器,里邊調用方法,傳入要封裝的對象這里的對象就表示已經(jīng)封裝好的了對象了。 什么是SpringMVC? SpringMVC是Spring家族的一員,Spring是將現(xiàn)在開發(fā)中流行的組件進行組合而成的一個框架!它用在基于MVC的表現(xiàn)層開發(fā),類似于struts...
摘要:要是使用到日歷的話,我們想到使用這個日歷類上面僅僅是我個人總結的要點,如果有錯誤的地方還請大家給我指正。 納稅服務系統(tǒng)總結 納稅服務系統(tǒng)是我第一個做得比較大的項目(不同于javaWeb小項目),該項目系統(tǒng)來源于傳智Java32期,十天的視頻課程(想要視頻的同學關注我的公眾號就可以直接獲取了) 我跟著練習一步一步完成需求,才發(fā)覺原來Java是這樣用來做網(wǎng)站的,Java有那么多的類庫,頁面...
摘要:是使用攔截器來自動幫我們完成中文亂碼的問題的。這是我的首頁當然了,基于注解和基于來開發(fā),都是通過映射器適配器和視圖解析器的。能夠控制請求路徑和請求方式一個控制器寫多個業(yè)務方法到目前為止,我們都是一個控制器寫一個業(yè)務方法,這肯定是不合理的。 前言 本文主要是講解在Controller中的開發(fā),主要的知識點有如下: 編碼過濾器 使用注解開發(fā) 注解@RequestMapping詳解 業(yè)務方...
摘要:自定義的攔截器可以和框架內置的攔截器進行混合使用,一般情況攔截器都被默認配置成為執(zhí)行的基礎。若類型轉換失敗,或者數(shù)據(jù)驗證失敗,攔截器就會阻止的執(zhí)行。 1.攔截器簡介 默認的攔截器在設計的時候就能滿足大部分的應用,所以很多時候就不需要添加自定義的攔截器或者修改攔截器棧。很多action有各種各樣的需求,比如輸入驗證、文件上傳、防止多次提交等等。于是struts框架就提供了一個解決方案,I...
閱讀 1755·2021-09-22 15:25
閱讀 1316·2019-08-29 12:34
閱讀 1922·2019-08-26 13:57
閱讀 3198·2019-08-26 10:48
閱讀 1454·2019-08-26 10:45
閱讀 800·2019-08-23 18:23
閱讀 743·2019-08-23 18:01
閱讀 1954·2019-08-23 16:07