摘要:文件上傳通過這個(gè)攔截器攔截器的設(shè)計(jì)就是基于組件設(shè)計(jì)的應(yīng)用再次回顧攔截器基礎(chǔ)在開始講解的時(shí)候已經(jīng)說明過了這個(gè)文件,它定義了的所有攔截器。由于我們配置了自定義攔截器,那么默認(rèn)的攔截器棧是不會(huì)執(zhí)行的。
什么是攔截器
攔截器Interceptor.....攔截器是Struts的概念,它與過濾器是類似的...可以近似于看作是過濾器
為什么我們要使用攔截器前面在介紹Struts的時(shí)候已經(jīng)講解過了,Struts為我們實(shí)現(xiàn)了很多的功能,比如數(shù)據(jù)自動(dòng)封裝阿..文件上傳功能阿....Struts為我們提供的這些功能都是通過攔截器完成的......
數(shù)據(jù)自動(dòng)封裝通過
文件上傳通過
攔截器的設(shè)計(jì)就是基于組件設(shè)計(jì)的應(yīng)用!
再次回顧攔截器基礎(chǔ)在開始講解Struts的時(shí)候已經(jīng)說明過了struts-default.xml這個(gè)文件,它定義了Struts的所有攔截器。因?yàn)槲覀冊(cè)趩?dòng)服務(wù)器的時(shí)候會(huì)自動(dòng)裝載這個(gè)文件,因此我們才可以在Action中使用到Struts為我們提供的功能【數(shù)據(jù)自動(dòng)封裝...文件上傳】
在struts-default.xml中定義的攔截器就有32個(gè)之多,Struts2為了方便我們對(duì)攔截器的引用,提供了攔截器棧的定義。
dojo..*,^struts..*,^session..*,^request..*,^application..*,^servlet(Request|Response)..*,parameters...* input,back,cancel,browse input,back,cancel,browse
也就是說:當(dāng)我們要引用多個(gè)攔截器的時(shí)候,只要把攔截器都放在棧里頭,在外邊引用攔截器即可!
值得注意的是:Struts2默認(rèn)執(zhí)行的是默認(rèn)攔截器棧,一旦用戶有指定執(zhí)行哪些攔截器,那么默認(rèn)的攔截器棧就不會(huì)被執(zhí)行!
自定義攔截器Struts2允許我們自定義攔截器,這就使我們能夠更加靈活地操作Struts2這個(gè)框架了!
Struts2提供了Interceptor這個(gè)攔截器接口,只要我們實(shí)現(xiàn)這個(gè)接口,那么這就算是自定義開發(fā)攔截器了。
當(dāng)然啦,大部分時(shí)候,我們定義攔截器都是繼承AbstractInterceptor這個(gè)類....為了學(xué)習(xí)攔截器的內(nèi)容,下面就實(shí)現(xiàn)Interceptor這個(gè)接口了。
編寫攔截器類當(dāng)實(shí)現(xiàn)該接口時(shí),有3個(gè)需要我們實(shí)現(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í)行順序有關(guān)的方法,我們現(xiàn)在先不理會(huì)....首先來講解intercept這個(gè)方法
/** * @param actionInvocation 攔截器的執(zhí)行狀態(tài) */ @Override public String intercept(ActionInvocation actionInvocation) throws Exception { //調(diào)用invoke()方法,代表著放行執(zhí)行下一個(gè)攔截器,如果沒有攔截器了,那么就執(zhí)行Action的業(yè)務(wù)代碼 actionInvocation.invoke(); return null; }
這很容易就能讓我們想起在學(xué)習(xí)過濾器中的doFilter()方法,其實(shí)是差不多的!
在struts.xml中配置像Struts默認(rèn)的攔截器一樣,我們自定義的攔截器是需要我們?cè)趕truts中配置的。
由于我們配置了自定義攔截器,那么struts默認(rèn)的攔截器棧是不會(huì)執(zhí)行的。如果我們想要使用默認(rèn)攔截器棧的功能,就必須把它配置在我們自定義的棧中!
攔截器的執(zhí)行順序/index.jsp
我們來觀察攔截器和Action類的執(zhí)行順序...只要在對(duì)應(yīng)的方法上向控制臺(tái)輸出就行了!
攔截器
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("我是攔截器的攔截方法"); //調(diào)用invoke()方法,代表著放行執(zhí)行下一個(gè)攔截器,如果沒有攔截器了,那么就執(zhí)行Action的業(yè)務(wù)代碼 //可看成是過濾器的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í)行順序是這樣的:
當(dāng)服務(wù)器開啟的時(shí)候,會(huì)執(zhí)行攔截器的init()方法
當(dāng)訪問Action時(shí),Action實(shí)例被創(chuàng)建
創(chuàng)建完Action實(shí)例,會(huì)調(diào)用攔截器的interceptor()方法
最后,執(zhí)行Action的execute()方法
其實(shí)很好理解,之前我們使用Struts為我們提供數(shù)據(jù)自動(dòng)封裝功能的時(shí)候,是這樣子的:
服務(wù)器啟動(dòng),加載配置文件的信息
初始化默認(rèn)的攔截器棧
當(dāng)用戶訪問Action時(shí),創(chuàng)建Action的實(shí)例。拿到Action具體的信息【成員變量、setter和getter】
執(zhí)行攔截器具體的內(nèi)容,根據(jù)Action具體的信息,把web端的數(shù)據(jù)封裝到Action上
最后在execute()就可以得到封裝后的數(shù)據(jù)了!
攔截器應(yīng)用案例需求:當(dāng)用戶登陸成功,跳轉(zhuǎn)到顯示用戶的JSP頁面中。當(dāng)用戶登陸失敗,重新返回登陸界面。如果用戶直接訪問顯示用戶的JSP頁面,那么返回到登陸界面
分析實(shí)現(xiàn)這個(gè)需求,我們可以使用過濾器的。只要獲取用戶的請(qǐng)求URL,再判斷URL是不是為list.jsp,如果是,我們返回到登陸的界面就好了。
現(xiàn)在,為了對(duì)攔截器的理解,我們使用攔截器去完成這個(gè)功能!
搭建配置環(huán)境導(dǎo)入我們c3p0.xml文件
導(dǎo)入c3p0開發(fā)包
導(dǎo)入mysql開發(fā)包
寫數(shù)據(jù)庫連接池工具類
dbUtils開發(fā)包
8個(gè)struts2需要用到的開發(fā)包
創(chuàng)建數(shù)據(jù)庫表,導(dǎo)入數(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" %>編寫處理請(qǐng)求的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.調(diào)用Service*******************/ Service service = new Service(); //登陸 public String login() { User user = service.login(this.user); if (user == null) { return "input"; } else { //將user的信息存到Session域?qū)ο笾? Mapstruts.xml配置文件session = ActionContext.getContext().getSession(); session.put("user", user); //登陸成功 return "login"; } } //查看user信息 public String list() { //拿到所有用戶的信息 List users = service.getAll(); //存到request域?qū)ο笾? Map request = ActionContext.getContext().getContextMap(); request.put("users", users); return "list"; } }
user_list /WEB-INF/list.jsp
到目前為止,我們登陸或者不登陸都可以得到用戶的具體信息....這是不合理的
我們想要的效果是:只有用戶正在調(diào)用login方法,或者該用戶已經(jīng)登陸了,才可以查看具體的用戶信息。
因此,我們們要攔截它們,只有用戶調(diào)用的是login方法時(shí)或者已經(jīng)登陸的情況下,才能跳轉(zhuǎn)到對(duì)應(yī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í)行的代理對(duì)象 ActionProxy proxy = actionInvocation.getProxy(); //通過代理對(duì)象得到正在執(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
只有當(dāng)用戶登陸了才能查看用戶具體信息,直接訪問Action會(huì)跳轉(zhuǎn)回
Struts2其他攔截器 計(jì)時(shí)攔截器Struts2自帶了計(jì)時(shí)攔截器,也就是用來統(tǒng)計(jì)每個(gè)Action執(zhí)行的時(shí)間
執(zhí)行等待攔截器如果頁面執(zhí)行得太慢了,Struts2還提供了執(zhí)行等待攔截器,也就是說,當(dāng)頁面加載得太久了,就跳轉(zhuǎn)到對(duì)應(yīng)的提示頁面...當(dāng)服務(wù)器執(zhí)行完畢了,也跳轉(zhuǎn)到相對(duì)應(yīng)的頁面
Struts2防止表單重復(fù)提交攔截器 回顧防止表單重復(fù)提交當(dāng)我們學(xué)習(xí)Session的時(shí)候已經(jīng)通過Session來編寫了一個(gè)防止表單重復(fù)提交的小程序了,我們來回顧一下我們當(dāng)時(shí)是怎么做的:
在Servlet上生成獨(dú)一無二的token,保存在Session域中,并交給JSP頁面
JSP頁面在提交表單數(shù)據(jù)的時(shí)候,把token放在隱藏域中...一起帶過去給Servlet
Servlet判斷用戶有沒有帶token值過來,判斷token的值是否和Session的相匹配
如果用戶是第一次提交的話,那么就允許用戶的請(qǐng)求,接著就把保存在Session中的token值去除
等用戶想要再次提交的時(shí)候,Servlet發(fā)現(xiàn)Session中并沒有token了,所以不搭理用戶的請(qǐng)求
我們以前寫表達(dá)重復(fù)提交就花了這么幾個(gè)步驟...如果有興趣的同學(xué)可以看一下以前的實(shí)現(xiàn)思路:http://blog.csdn.net/hon_3y/article/details/54799494#t11
Struts2防止表單重復(fù)提交Struts2是簡(jiǎn)化我們的開發(fā)的,表單重復(fù)提交也是一件非常常用的功能...Struts2也為我們實(shí)現(xiàn)了...當(dāng)然啦,也是通過攔截器來實(shí)現(xiàn)
它的實(shí)現(xiàn)原理和我們以前寫的思路幾乎一致...它不需要另外寫一個(gè)組件來生成token值,struts2標(biāo)簽就有這么一個(gè)功能...因此是十分方便的
為了熟悉一下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) { //手動(dòng)設(shè)置id,因?yàn)樵跀?shù)據(jù)庫表我沒使用自動(dòng)增長id user.setId(WebUtils.makeId()); //這是以前的表,規(guī)定要address,只能手動(dòng)設(shè)置了 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" %>
使用了模型驅(qū)動(dòng)封裝數(shù)據(jù),添加用戶
//這里一定要實(shí)例化 User user = new User(); public User getUser() { return user; } public void setUser(User user) { this.user = user; } @Override public User getModel() { return user; } /*******調(diào)用service********/ Service service = new Service(); public String register() throws Exception { service.add(user); //注冊(cè)成功,就跳轉(zhuǎn)到list()方法,list方法就跳轉(zhuǎn)到查看所有用戶頁面了! return list(); }
列出全部的用戶數(shù)據(jù),提供修改功能,需要把id傳遞過去,明確修改的是哪一個(gè)用戶
<%-- 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,找到對(duì)象,添加到值棧中(數(shù)據(jù)回顯)
public String updatePage() throws Exception { //得到用戶帶過來的id,根據(jù)id查找對(duì)象 User user222 = service.findUser(user.getId()); ActionContext.getContext().getValueStack().push(user222); return "updatePage"; }
修改用戶的JSP頁面,使用Struts2提供的回顯技術(shù),并把id通過隱藏域帶過去給Action..最終是通過id來修改用戶的數(shù)據(jù)
效果 防止表單重復(fù)提交
上面我們已經(jīng)完成了大部分的功能了,但當(dāng)我們如果提交之后,再刷新頁面,那么表單的數(shù)據(jù)就會(huì)重復(fù)提交...我們使用Struts2我們提供的防止表單重復(fù)提交的功能把!
在需要提交的表單上使用token標(biāo)簽用戶名: |
密碼: |
電話: |
token攔截器默認(rèn)是不會(huì)啟動(dòng)的,也就是說:需要我們手動(dòng)配置...
當(dāng)我們配置攔截器的時(shí)候,Struts2默認(rèn)的攔截器是不會(huì)執(zhí)行的,所以要把Struts2默認(rèn)的攔截器也寫上
register /list.jsp /update.jsp /login.jsp /user_list
當(dāng)我們重復(fù)提交的時(shí)候,它會(huì)報(bào)錯(cuò),因此,如果它報(bào)錯(cuò)了,我們就跳轉(zhuǎn)到register頁面把
測(cè)試如果文章有錯(cuò)的地方歡迎指正,大家互相交流。習(xí)慣在微信看技術(shù)文章,想要獲取更多的Java資源的同學(xué),可以關(guān)注微信公眾號(hào):Java3y
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/68742.html
摘要:前言由于寫的文章已經(jīng)是有點(diǎn)多了,為了自己和大家的檢索方便,于是我就做了這么一個(gè)博客導(dǎo)航。 前言 由于寫的文章已經(jīng)是有點(diǎn)多了,為了自己和大家的檢索方便,于是我就做了這么一個(gè)博客導(dǎo)航。 由于更新比較頻繁,因此隔一段時(shí)間才會(huì)更新目錄導(dǎo)航哦~想要獲取最新原創(chuàng)的技術(shù)文章歡迎關(guān)注我的公眾號(hào):Java3y Java3y文章目錄導(dǎo)航 Java基礎(chǔ) 泛型就這么簡(jiǎn)單 注解就這么簡(jiǎn)單 Druid數(shù)據(jù)庫連接池...
摘要:也就是說映射器就是用于處理什么樣的請(qǐng)求提交給處理。這和是一樣的提交參數(shù)的用戶名編號(hào)提交配置處理請(qǐng)求注冊(cè)映射器包框架接收參數(shù)設(shè)置無參構(gòu)造器,里邊調(diào)用方法,傳入要封裝的對(duì)象這里的對(duì)象就表示已經(jīng)封裝好的了對(duì)象了。 什么是SpringMVC? SpringMVC是Spring家族的一員,Spring是將現(xiàn)在開發(fā)中流行的組件進(jìn)行組合而成的一個(gè)框架!它用在基于MVC的表現(xiàn)層開發(fā),類似于struts...
摘要:要是使用到日歷的話,我們想到使用這個(gè)日歷類上面僅僅是我個(gè)人總結(jié)的要點(diǎn),如果有錯(cuò)誤的地方還請(qǐng)大家給我指正。 納稅服務(wù)系統(tǒng)總結(jié) 納稅服務(wù)系統(tǒng)是我第一個(gè)做得比較大的項(xiàng)目(不同于javaWeb小項(xiàng)目),該項(xiàng)目系統(tǒng)來源于傳智Java32期,十天的視頻課程(想要視頻的同學(xué)關(guān)注我的公眾號(hào)就可以直接獲取了) 我跟著練習(xí)一步一步完成需求,才發(fā)覺原來Java是這樣用來做網(wǎng)站的,Java有那么多的類庫,頁面...
摘要:是使用攔截器來自動(dòng)幫我們完成中文亂碼的問題的。這是我的首頁當(dāng)然了,基于注解和基于來開發(fā),都是通過映射器適配器和視圖解析器的。能夠控制請(qǐng)求路徑和請(qǐng)求方式一個(gè)控制器寫多個(gè)業(yè)務(wù)方法到目前為止,我們都是一個(gè)控制器寫一個(gè)業(yè)務(wù)方法,這肯定是不合理的。 前言 本文主要是講解在Controller中的開發(fā),主要的知識(shí)點(diǎn)有如下: 編碼過濾器 使用注解開發(fā) 注解@RequestMapping詳解 業(yè)務(wù)方...
摘要:自定義的攔截器可以和框架內(nèi)置的攔截器進(jìn)行混合使用,一般情況攔截器都被默認(rèn)配置成為執(zhí)行的基礎(chǔ)。若類型轉(zhuǎn)換失敗,或者數(shù)據(jù)驗(yàn)證失敗,攔截器就會(huì)阻止的執(zhí)行。 1.攔截器簡(jiǎn)介 默認(rèn)的攔截器在設(shè)計(jì)的時(shí)候就能滿足大部分的應(yīng)用,所以很多時(shí)候就不需要添加自定義的攔截器或者修改攔截器棧。很多action有各種各樣的需求,比如輸入驗(yàn)證、文件上傳、防止多次提交等等。于是struts框架就提供了一個(gè)解決方案,I...
閱讀 1743·2021-09-22 15:25
閱讀 1307·2019-08-29 12:34
閱讀 1908·2019-08-26 13:57
閱讀 3188·2019-08-26 10:48
閱讀 1443·2019-08-26 10:45
閱讀 793·2019-08-23 18:23
閱讀 733·2019-08-23 18:01
閱讀 1945·2019-08-23 16:07