SSH的亂七八糟【過濾器+攔截器+監聽器】
一些面試的知識點:
今天想著隨便寫點,為日後回憶做點準備:
=======================過濾器和攔截器===================================================
過濾器<filter>:
攔截器<inteceptor>
過濾器,【還沒有進入業務裡面】是在java web中,你傳入的request,response提前過濾掉一些資訊,或者提前設定一些引數,
所以過濾器是攔截在業務請求之前
然後再傳入servlet或者struts的 action進行業務邏輯,
比如:
1:過濾掉非法url(不是login.do的地址請求,如果使用者沒有登陸都過濾掉),
2:在傳入servlet或者 struts的action前統一設定字符集,或者去除掉一些非法字元
攔截器,【已結進入到了業務裡面】是在面向切面程式設計的,
1:在你的service或者一個方法前呼叫一個方法,preHandle(){xxxxx}
2:在你的service或者一個方法後呼叫一個方法比如動態代理就是攔截器的簡單實現,在你呼叫方法前打印出字串(或者做其它業務邏輯的操作),也可以在你呼叫方法後打印出字串,甚至在你丟擲異常的時候做業務邏輯的操作
攔截器與過濾器的區別 :
- 攔截器是基於java的反射機制的【因為他用的是動態代理,裡面實現使用的是java反射】,而過濾器是基於函式回撥。
- 攔截器不依賴與servlet容器,過濾器依賴與servlet容器。【因為他的引數是HttpServletrequest,HttpServletresponse】
- 攔截器只能對action請求起作用,而過濾器則可以對幾乎所有的請求起作用。(下面提到,可以過濾html,指定資料夾等)
- 攔截器可以訪問action上下文、值棧裡的物件【因為他的引數是ActionInvocation】,而過濾器不能訪問。
- 在action的生命週期中,攔截器可以多次被呼叫,而過濾器只能在容器初始化時被呼叫一次
執行順序 :過濾前 - 攔截前 - Action處理 - 攔截後 - 過濾後。個人認為過濾是一個橫向的過程,首先把客戶端提交的內容進行過濾(例如未登入使用者不能訪問內部頁面的處理);過濾通過後,
但是人們也發現,在分散程式碼的同時,也增加了程式碼的重複性。什麼意思呢?比如說,我們在兩個類中,可能都需要在每個方法中做日誌。按面向物件的設計方法,我們就必須在兩個類的方法中都加入日誌的內容。也許他們是完全相同的,但就是因為面向物件的設計讓類與類之間無法聯絡,而不能將這些重複的程式碼統一起來。
也許有人會說,那好辦啊,我們可以將這段程式碼寫在一個獨立的類獨立的方法裡,然後再在這兩個類中呼叫。但是,這樣一來,這兩個類跟我們上面提到的獨立的類就有耦合了,它的改變會影響這兩個類。那麼,有沒有什麼辦法,能讓我們在需要的時候,隨意地加入程式碼呢?這種在執行時,動態地將程式碼切入到類的指定方法、指定位置上的程式設計思想就是面向切面的程式設計。
一般而言,我們管切入到指定類指定方法的程式碼片段稱為切面,而切入到哪些類、哪些方法則叫切入點。 有了AOP,我們就可以把幾個類共有的程式碼,抽取到一個切片中,等到需要時再切入物件中去,從而改變其原有的行為。
這樣看來,AOP其實只是OOP的補充而已。OOP從橫向上區分出一個個的類來,而AOP則從縱向上向物件中加入特定的程式碼。有了AOP,OOP變得立體了。如果加上時間維度,AOP使OOP由原來的二維變為三維了,由平面變成立體了。從技術上來說,AOP基本上是通過代理機制實現的。
AOP在程式設計歷史上可以說是里程碑式的,對OOP程式設計是一種十分有益的補充。 大家 一直在說spring aop,關於具體如何aop的,請檢視這篇文章:http://zywang.iteye.com/blog/974226
下面看看靜態代理例項
二者的配置都在web.xml中:
Filter過濾器是一個Web應用元件,和Servlet類似,也需要在Web應用配置檔案中進行配置:首先是過濾器的Web應用定義包含在<filter>…</filer>元素中,其次是Web應用的過濾器對映配置檔案<filter-mapping>…</filter-mapping>
過濾器的應用很廣泛,在這裡介紹利用過濾器進行中文轉碼。
一般在JavaWeb應用中,當利用request.getParameter(String str)方法獲取從表單或是頁面傳過來的中文引數都會是一個亂碼。
通常的做法是:會採用如下的轉碼方式在Servlet或是JSP中進行轉碼設定:
(1)request.setCharacterEncoding("gb2312");
(2)String username = request.getParameter("username");
username = new String(username.getBytes("ISO-8859-1"), "GB2312");
這樣做的缺點是:
假設:一個表單有多資料傳到Servlet或是JSP,那麼就可能在這些Servlet或是JSP中寫下多個request.setCharacterEncoding("gb2312")或是多個類似於String username = request.getParameter("username");
username = new String(username.getBytes("ISO-8859-1"), "GB2312");這樣子肯定加大程式碼工作量。
解決辦法是:
針對上面的一些常見的問題,下面利用過濾器進行中文轉碼就可以迎刃而解。配置Filter的步驟如下:
1.配置web.xml
2.開發過濾器:比如類CharactsetConversion【該類必須實現filter介面】,同時實現Filter介面提供的三個方法:
(1)void doFilter(ServletRequest req,ServletResponse res,FilterChain filterChain)
(2)void init(FilterConfig filterConfig)
(3)void destroy()
對於配置的提升:
1。如果要對映過濾應用程式中所有資源:
<filter-mapping>
<filter-name>loggerfilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
2.過濾指定的型別檔案資源
<filter-mapping>
<filter-name>loggerfilter</filter-name>
<url-pattern>*.html</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>loggerfilter</filter-name>
<url-pattern>*.jsp</url-pattern>
</filter-mapping>
可以一下寫多個過來型別,其中<url-pattern>注意沒有“/”斜槓
3.過濾指定的目錄
<filter-mapping>
<filter-name>loggerfilter</filter-name>
<url-pattern>/folder_name/*</url-pattern>
</filter-mapping>
4.過濾指定的servlet
<filter-mapping>
<filter-name>loggerfilter</filter-name>
<servlet-name>loggerservlet</servlet-name>//注意這裡是servlet
</filter-mapping>
5.過濾指定檔案
<filter-mapping>
<filter-name>loggerfilter</filter-name>
<url-pattern>/simplefilter.html</url-pattern>
</filter-mapping>
下面總結三種經常用到的過濾器:
一、使瀏覽器不快取頁面的過濾器
public class ForceNoCacheFilter implements Filter {
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException
{
((HttpServletResponse) response).setHeader("Cache-Control","no-cache");
((HttpServletResponse) response).setHeader("Pragma","no-cache");
((HttpServletResponse) response).setDateHeader ("Expires", -1);
filterChain.doFilter(request, response);
}
public void destroy()
{
}
public void init(FilterConfig filterConfig) throws ServletException
{
}
}
二、檢測使用者是否登陸的過濾器
/**
* 用於檢測使用者是否登陸的過濾器,如果未登入,則重定向到指的登入頁面
* filter中配置引數
* checkSessionKey 需檢查的在 Session 中儲存的關鍵字
* redirectURL 如果使用者未登入,則重定向到指定的頁面,URL不包括 ContextPath
* notCheckURLList 不做檢查的URL列表,以分號分開,並且 URL 中不包括 ContextPath
*/
public class CheckLoginFilter
implements Filter
{
protected FilterConfig filterConfig = null;
private String redirectURL = null;
private List notCheckURLList = new ArrayList();
private String sessionKey = null;
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException
{
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
HttpSession session = request.getSession();
if(sessionKey == null)
{
filterChain.doFilter(request, response);
return;
}
if((!checkRequestURIIntNotFilterList(request)) && session.getAttribute(sessionKey) == null)
{
response.sendRedirect(request.getContextPath() + redirectURL);
return;
}
filterChain.doFilter(servletRequest, servletResponse);
}
public void destroy()
{
notCheckURLList.clear();
}
private boolean checkRequestURIIntNotFilterList(HttpServletRequest request)
{
String uri = request.getServletPath() + (request.getPathInfo() == null ? "" : request.getPathInfo());
return notCheckURLList.contains(uri);
}
public void init(FilterConfig filterConfig) throws ServletException
{
this.filterConfig = filterConfig;
redirectURL = filterConfig.getInitParameter("redirectURL");
sessionKey = filterConfig.getInitParameter("checkSessionKey");
String notCheckURLListStr = filterConfig.getInitParameter("notCheckURLList");
if(notCheckURLListStr != null)
{
StringTokenizer st = new StringTokenizer(notCheckURLListStr, ";");
notCheckURLList.clear();
while(st.hasMoreTokens())
{
notCheckURLList.add(st.nextToken());
}
}
}
}
三、字元編碼的過濾器 (上面的例項程式碼)
四、資源保護過濾器
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* This Filter class handle the security of the application.
* It should be configured inside the web.xml.
*/
public class SecurityFilter implements Filter {
//the login page uri
private static final String LOGIN_PAGE_URI = "login.jsp";
//the logger object
private Log logger = LogFactory.getLog(this.getClass());
//a set of restricted resources
private Set restrictedResources;
/**
* Initializes the Filter.
*/
public void init(FilterConfig filterConfig) throws ServletException {
this.restrictedResources = new HashSet();
this.restrictedResources.add("/createProduct.jsf");
this.restrictedResources.add("/editProduct.jsf");
this.restrictedResources.add("/productList.jsf");
}
/**
* Standard doFilter object.
*/
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
this.logger.debug("doFilter");
String contextPath = ((HttpServletRequest)req).getContextPath();
String requestUri = ((HttpServletRequest)req).getRequestURI();
this.logger.debug("contextPath = " + contextPath);
this.logger.debug("requestUri = " + requestUri);
if (this.contains(requestUri, contextPath) && !this.authorize((HttpServletRequest)req)) {
this.logger.debug("authorization failed");
((HttpServletRequest)req).getRequestDispatcher(LOGIN_PAGE_URI).forward(req, res);
}
else {
this.logger.debug("authorization succeeded");
chain.doFilter(req, res);
}
}
public void destroy() {}
private boolean contains(String value, String contextPath) {
Iterator ite = this.restrictedResources.iterator();
while (ite.hasNext()) {
String restrictedResource = (String)ite.next();
if ((contextPath + restrictedResource).equalsIgnoreCase(value)) {
return true;
}
}
return false;
}
private boolean authorize(HttpServletRequest req) {
//處理使用者登入
/* UserBean user = (UserBean)req.getSession().getAttribute(BeanNames.USER_BEAN);
if (user != null && user.getLoggedIn()) {
//user logged in
return true;
}
else {
return false;
}*/
}
}
==========================================================================
接下來看看攔截器:
=============================================================================
struts1基本被拋棄了,下面主要討論struts2
核心包:
struts2-core-2.0.11.1.jar
xwork-2.0.4.jar
commons-logging-1.0.4.jar
freemarker-2.3.8.jar
Struts2入口是過濾器:
下面是web.xml檔案中struts的配置:
注意下這裡的dispatcher
<dispatcher>元素,這個元素有四個可能的值:即
1.REQUEST,預設是這個【其實就是redirect】
2.FORWARD,
3.INCLUDE
4.ERROR,
使得filter將會作用於直接從客戶端過來的request,通過forward過來的request,通過include過來的request和通過<error-page>過來的request。如果沒有指定任何<dispatcher>元素,預設值是REQUEST
struts.xml中的配置點:
1.struts2的攔截器intercepter:
首先攔截器是配置在struts.xml檔案中:
其次看結構
從上面的呼叫過程我們可以總結出來:過濾器和攔截器在struts2中呼叫順序:
過濾前 - 攔截前 - Action處理 - 攔截後 - 過濾後。個人認為過濾是一個橫向的過程,首先把客戶端提交的內容進行過濾(例如未登入使用者不能訪問內部頁面的處理);過濾通過後,攔截器將檢查使用者提交資料的驗證,做一些前期的資料處理,接著把處理後的資料發給對應的Action;Action處理完成返回後,攔截器還可以做其他過程(還沒想到要做啥),再向上返回到過濾器的後續操作。
我想說的是:這裡的interceptor-stak,攔截器棧,並且這種寫法是舊的寫法,
JDK5.0以後有了標註,struts2提供了標註寫法支援,不用像上圖中這麼寫了。下面的截圖那樣在action中直接寫
InterceptorRefs({
InterceptorRef("aaaa"),
InterceptorRef("bbbbb"),
})
裡面的多個攔截器interceptor-ref是遞迴呼叫,腫麼解釋呢:
1.aaa攔截器invoke()之前的程式碼,
2.bbb攔截器invoke()之前的程式碼
3.bbb攔截器invoke()之後的程式碼
4.aaa攔截器invoke()之後的程式碼
再次看呼叫[也即是寫Action]
區別在於:
Struts1.x中的動作類必須從Action類中繼承,而Struts2.x的動作類需要從com.opensymphony.xwork2.ActionSupport類繼承
=========== 監聽器[spring用的就是contextLoaderlistener監聽]=============================
監聽器概述
1.Listener是Servlet的監聽器
2.可以監聽客戶端的請求、服務端的操作等。
3.通過監聽器,可以自動激發一些操作,如監聽線上使用者數量,當增加一個HttpSession時,給線上人數加1。
4.編寫監聽器需要實現相應的介面
5.編寫完成後在web.xml檔案中配置一下,就可以起作用了
6.可以在不修改現有系統基礎上,增加web應用程式生命週期事件的跟蹤
常用的監聽介面
1.ServletContextAttributeListener
監聽對ServletContext屬性的操作,比如增加/刪除/修改
2.ServletContextListener
監聽ServletContext,當建立ServletContext時,激發 contextInitialized(ServletContextEvent sce)方法;當銷燬ServletContext時,激發contextDestroyed(ServletContextEvent sce)方法。
3.HttpSessionListener
監聽HttpSession的操作。當建立一個 Session時,激發session Created(SessionEvent se)方法;當銷燬一個Session時,激發sessionDestroyed (HttpSessionEvent se)方法。
4.HttpSessionAttributeListener
監聽HttpSession中的屬性的操作。當在Session增加一個屬性時,激發 attributeAdded(HttpSessionBindingEvent se) 方法;當在Session刪除一個屬性時,激發attributeRemoved(HttpSessionBindingEvent se)方法;當在Session屬性被重新設定時,激發attributeReplaced(HttpSessionBindingEvent se) 方法。
使用範例:
由監聽器管理共享資料庫連線
生命週期事件的一個實際應用由context監聽器管理共享資料庫連線。在web.xml中如下定義監聽器:
<listener>
<listener-class>XXX.MyConnectionManager</listener-class>
</listener> ?server建立監聽器的例項,接受事件並自動判斷實現監聽器介面的型別。要記住的是由於監聽器是配置在部署描述符web.xml中,所以不需要改變任何程式碼就可以新增新的監聽器。
public class MyConnectionManager implements ServletContextListener{
public void contextInitialized(ServletContextEvent e) {
Connection con = // create connection
e.getServletContext().setAttribute("con", con);
}
public void contextDestroyed(ServletContextEvent e) {
Connection con = (Connection) e.getServletContext().getAttribute("con");
try {
con.close();
}
catch (SQLException ignored) { } // close connection
}
}
監聽器保證每新生成一個servlet context都會有一個可用的資料庫連線,並且所有的連線對會在context關閉的時候隨之關閉。
在web.xml中加入:
<listener><listener-class>servletlistener111111.SecondListener</listener-class> </listener>
==================================================
關於使用者超時的例子:
public class OnlineUserListener implements HttpSessionListener {
public void sessionCreated(HttpSessionEvent event) {
}
public void sessionDestroyed(HttpSessionEvent event) {
HttpSession session = event.getSession();
ServletContext application = session.getServletContext();
// 取得登入的使用者名稱
String username = (String) session.getAttribute("username");
// 從線上列表中刪除使用者名稱
List onlineUserList = (List) application.getAttribute("onlineUserList");
onlineUserList.remove(username);
System.out.println(username + "超時退出。");
}
}
以下兩種情況下就會發生sessionDestoryed(會話銷燬)事件:
1.執行session.invalidate()方法時。例如:request.getSession().invalidate();
2.如果使用者長時間沒有訪問伺服器,超過了會話最大超時時間,伺服器就會自動銷燬超時的session。會話超時時間可以在web.xml中進行設定。
========================================
使用HttpSessionBindingListener
HttpSessionBindingListener雖然叫做監聽器,但使用方法與HttpSessionListener完全不同。我們實際看一下它是如何使用的。
我們的OnlineUserBindingListener實現了HttpSessionBindingListener介面,介面中共定義了兩個方法:valueBound()和valueUnbound(),分別對應資料繫結,和取消繫結兩個事件。
所謂對session進行資料繫結,就是呼叫session.setAttribute()把HttpSessionBindingListener儲存進session中。我們在LoginServlet.java中進行這一步。
// 把使用者名稱放入線上列表
session.setAttribute("onlineUserBindingListener", new OnlineUserBindingListener(username));
這就是HttpSessionBindingListener和HttpSessionListener之間的最大區別:HttpSessionListener只需要設定到web.xml中就可以監聽整個應用中的所有session。 HttpSessionBindingListener必須例項化後放入某一個session中,才可以進行監聽。
從監聽範圍上比較,HttpSessionListener設定一次就可以監聽所有session,HttpSessionBindingListener通常都是一對一的。
正是這種區別成就了HttpSessionBindingListener的優勢,我們可以讓每個listener對應一個username,這樣就不需要每次再去session中讀取username,進一步可以將所有操作線上列表的程式碼都移入listener,更容易維護。
valueBound()方法的程式碼如下:
public void valueBound(HttpSessionBindingEvent event) {
HttpSession session = event.getSession();
ServletContext application = session.getServletContext();
// 把使用者名稱放入線上列表
List onlineUserList = (List) application.getAttribute("onlineUserList");
// 第一次使用前,需要初始化
if (onlineUserList == null) {
onlineUserList = new ArrayList();
application.setAttribute("onlineUserList", onlineUserList);
}
onlineUserList.add(this.username);
}
username已經通過構造方法傳遞給listener,在資料繫結時,可以直接把它放入使用者列表。
與之對應的valueUnbound()方法,程式碼如下:
public void valueUnbound(HttpSessionBindingEvent event) {
HttpSession session = event.getSession();
ServletContext application = session.getServletContext();
// 從線上列表中刪除使用者名稱
List onlineUserList = (List) application.getAttribute("onlineUserList");
onlineUserList.remove(this.username);
System.out.println(this.username + "退出。");
}
這裡可以直接使用listener的username操作線上列表,不必再去擔心session中是否存在username。
valueUnbound的觸發條件是以下三種情況:
1.執行session.invalidate()時。
2.session超時,自動銷燬時。
3.執行session.setAttribute("onlineUserListener", "其他物件");或
session.removeAttribute("onlineUserListener");將listener從session中刪除時。
因此,只要不將listener從session中刪除,就可以監聽到session的銷燬
======================================下面看看配置================================================
action的配置:Struts1.x的動作一般都以.do結尾,而Struts2是以.action結尾。
這一步struts1.x和struts2.x都是必須的,只是
在struts1.x中的配置檔案一般叫struts-config.xml(當然也可以是其他的檔名),而且一般放到WEB-INF目錄中。
而在truts2.x中的配置檔案一般為struts.xml
這裡的type可以取:
dispatcher:(其實就是forward),轉發可以儲存request中的值
redirect:
stream:
用標註的新寫法:
還要注意一點:
<?xmlversion="1.0"encoding="UTF-8"?><!DOCTYPEstrutsPUBLIC
"-//ApacheSoftwareFoundation//DTDStrutsConfiguration2.0//EN""http://struts.apache.org/dtds/struts-2.0.dtd"><struts>
<package name="struts2" namespace="/mystruts" extends="struts-default">
<action name="sum" class="action.FirstAction">
<result name="positive">/positive.jsp</result>
<result name="negative">/negative.jsp</result>
</action>
</package>
</struts>
在<struts>標籤中可以有多個<package>,第一個<package>可以指定一個Servlet訪問路徑(不包括動作名),如“/mystruts”
不能這樣寫
===============================================jsp頁面中設計的struts2內容
Struts2自帶的tag:struts2
在
Struts2
中已經將
Struts1.x
的好幾個標籤庫都統一了,
在
Struts2
中只有一個標籤庫
/struts-tags
================================分割線=============================
下面看看struts的執行緒安全問題
sruts1.x是單例模式,所以執行緒不安全
strut2.本身是執行緒安全的,因為他為每一個請求都產生一個新例項,從根源上杜絕了這個問題
但是使用spring來管理Action後,IOC容器中管理的bean都是單例的,所以問題又出來了,和struts1一樣,
解決的辦法是:在spring的bean配置中,設定scope="prototype"
======================================================
spring IOC容器物件的呼叫
如果要想在普通的java程式碼中使用IoC容器中的bean實體:
則這樣寫:
1.例項化spring容器 和 從容器獲取Bean物件
例項化Spring容器常用的兩種方式:
方法一:
在類路徑下尋找配置檔案來例項化容器 [推薦使用]
ApplicationContext ctx = new ClassPathXmlApplicationContext(new String[]{"beans.xml"});
方法二:
在檔案系統路徑下尋找配置檔案來例項化容器 [這種方式可以在開發階段使用]
ApplicationContext ctx = new FileSystemXmlApplicationContext(new String[]{“d:\\beans.xml“});
Spring的配置檔案可以指定多個,可以通過String陣列傳入。
當spring容器啟動後,因為spring容器可以管理bean物件的建立,銷燬等生命週期,
所以我們只需從容器直接獲取Bean物件就行,而不用編寫一句程式碼來建立bean物件。
從容器獲取bean物件的程式碼如下:
ApplicationContext ctx = new ClassPathXmlApplicationContext(“beans.xml”);
OrderService service = (OrderService)ctx.getBean("personService");
檢視文章:http://www.blogjava.net/stevenjohn/archive/2012/08/20/385846.html
============================有關標籤================================
=============================spring 相關===============================
IoC,
直觀地講,就是容器控制程式之間的關係,而非傳統實現中,由程式程式碼直接操控。這也就是所謂“控制反轉”的概念所在。控制權由應用程式碼中轉到了外部容器,控制權的轉移是所謂反轉。IoC還有另外一個名字——“依賴注入(Dependency Injection)”。從名字上理解,所謂依賴注入,即元件之間的依賴關係由容器在執行期決定,形象地說,即由容器動態地將某種依賴關係注入到元件之中。
spring依賴注入的三種方式:
1.通過介面注射--類必須實現容器給定的一個介面,然後容器會利用這個介面給我們這個類注射它所依賴的類。
2.通過setter方法注射,這種方式也是Spring推薦的方式
public class Girl {
private Kissable kissable;
public void setKissable(Kissable kissable) {
this.kissable = kissable;
}
public void kissYourKissable() {
kissable.kiss();
}
}
<beans>
<bean id="boy" class="Boy"/>
<bean id="girl" class="Girl">
<property name="kissable">
<ref bean="boy"/>
</property>
</bean>
</beans>
3.通過構造方法注射類,這種方式Spring同樣給予了實現,它和通過setter方式一樣,都在類裡無任何侵入性,但是,不是沒有侵入性,只是把侵入性轉移了,顯然第1種方式要求實現特定的介面,侵入性非常強,不方便以後移植。
public class Girl {
private Kissable kissable;
public Girl(Kissable kissable) {
this.kissable = kissable;
}
public void kissYourKissable() {
kissable.kiss();
}
}
PicoContainer container = new DefaultPicoContainer();
container.registerComponentImplementation(Boy.class);
container.registerComponentImplementation(Girl.class);
Girl girl = (Girl) container.getComponentInstance(Girl.class);
girl.kissYourKissable();
下面看一個特別的類:OpenSessionInview
=================================三個框架整合===========================================
===================全域性事務與本地事務的區別==========
全域性事務:
資源管理器管理和協調的事務,
可以跨越多個數據庫和程序。
資源管理器一般使用
全域性事務:資源管理器管理和協調的事務,可以跨越多個數據庫和程序。資源管理器一般使用 XA 二階段提交協議與“企業資訊系統”(EIS) 或資料庫進行互動。本地事務:在單個 EIS 或資料庫的本地並且限制在單個程序內的事務。本地事務不涉及多個數據來源
在Hibernate配置檔案中有這麼兩種配置方式: 1.如果使用的是本地事務(jdbc事務)
<property name="hibernate.current_session_context_class">thread</property>,這個是我們常用的選項,只針對一個數據庫進行操作,也就是說只針對一個事務性資源進行操作. 2. 如果使用的是全域性事務(jta事務)
<property name="hibernate.current_session_context_class">jta</property>
以前我們學習的事務型別都屬於本地事務。 JTA(全域性事務)和thread(本地事務)有什麼區別呢?在某些應用場合,只能使用全域性事務,比如:
有兩個資料庫:
1.mysql 2.oracle 現在有個業務需求--轉賬
step 1> update mysql_table set amount=amount-xx where id=aaa 發生扣錢,假設是在mysql資料庫扣錢的。
step 2> update oracle_table set amount=amount+xx where id=bbb 加錢,假設是在oracle資料庫扣錢的。
現在怎麼確保兩個語句在同一個事務裡執行呢?
以前在JDBC裡是這樣做 connection = mysql 連線mysql
connection.setAutoCommit(false); 不自動提交
1> update mysql_table set amount=amount-xx where id=aaa 發生扣錢,假設是在mysql資料庫扣錢的。
2> update oracle_table set amount=amount+xx where id=bbb 發生在oracle資料庫 connection.commit();
執行這兩條語句,然後通過connection物件提交事務.我們這樣子做只能確保這兩個語句在同一個資料庫mysql裡面實現在同一個事務裡執行。 但是問題是我們現在是要連線到oracle資料庫,是不是需要connection2啊?
connection = mysql 連線mysql connection2 = oracle 連線oracle
connection.setAutoCommit(false); 不自動提交
1> update mysql_table set amount=amount-xx where id=aaa 發生扣錢,假設是在mysql資料庫扣錢的。
2> update oracle_table set amount=amount+xx where id=bbb 發生在oracle資料庫 connection.commit();
connection2.setAutoCommit(false)
connection2.commit();
事務只能在一個connection裡開啟,並且確保兩條語句都在該connection裡執行,這樣才能讓兩條語句在同一事務裡執行,現在問題就在於connection2是連線到oracle資料庫的,那麼connection2再開事務有意義嗎?它能確保嗎?不能,所以在這種情況下就只能使用全域性事務了。
這種情況下用普通JDBC操作是滿足不了這個業務需求的,這種業務需求只能使用全域性事務,本地事務是無法支援我們的操作的,因為這時候,事務的生命週期不應該侷限於connection物件的生命週期範圍
全域性事務怎麼做呢?
JPA.getUserTransaction().begin(); 首先要全域性事務的API,不需要我們編寫,通常容器已經提供給我們了,我們只需要begin一下 connection = mysql 連線mysql connection2 = oracle 連線oracle
connection--> update mysql_table set amount=amount-xx where id=aaa 發生扣錢,假設是在mysql資料庫扣錢的。
connection2--> update oracle_table set amount=amount+xx where id=bbb 發生在oracle資料庫 JPA.getUserTransaction().commit();
那麼它是怎麼知道事務該提交還是回滾呢?
這時候它使用了二次提交協議。二次提交協議簡單說就這樣:如果你先執行第一條語句,執行的結果先預提交到資料庫,預提交到資料庫了,資料庫會執行這條語句,然後返回一個執行的結果,這個結果假如我們用布林值表示的話,成功就是true,失敗就是false.然後把執行的結果放入一個(假設是List)物件裡面去,接下來再執行第二條語句,執行完第二條語句之後(也是預處理,資料庫不會真正實現資料的提交,只是說這條語句送到資料庫裡面,它模擬下執行,給你返回個執行的結果),假如這兩條語句的執行結果在List裡面都是true的話,那麼這個事務就認為語句是成功的,這時候全域性事務就會提交。二次提交協議,資料庫在第一次提交這個語句時,只會做預處理,不會發生真正的資料改變,當我們在全域性事務提交的時候,這時候發生了第二次提交,那麼第二次提交的時候才會真正的發生資料的改動。
如果說在執行這兩條語句中,有一個出錯了,那麼List集合裡就有個元素為false,那麼全域性事務就認為你這個事務是失敗的,它就會進行回滾,回滾的時候,哪怕你的第二條語句在第一次提交的時候是成功的,它在第二次提交的時候也會回滾,那麼第一次的更改也會恢復到之前的狀態,這就是二次提交協議。(可以檢視一下資料庫方面的文件來了解二次提交協議
===========================getCurrentSession() 和openSession()=======================
1、getCurrentSession()與openSession()的區別?
* 採用getCurrentSession()建立的session會繫結到當前執行緒中,而採用openSession(),建立的session則不會 * 採用getCurrentSession()建立的session在commit或rollback時會自動關閉,而採用openSession(),建立的session必須手動關閉 2、使用getCurrentSession()需要在hibernate.cfg.xml檔案中加入如下配置: * 如果使用的是本地事務(jdbc事務) <property name="hibernate.current_session_context_class">thread</property> * 如果使用的是全域性事務(jta事務)<property name="hibernate.current_session_context_class">jta</property>
openSession() 與 getCurrentSession() 有何不同和關聯呢?
在 SessionFactory 啟動的時候, Hibernate 會根據配置建立相應的 CurrentSessionContext ,在getCurrentSession() 被呼叫的時候,實際被執行的方法是 CurrentSessionContext.currentSession() 。在currentSession() 執行時,如果當前 Session 為空, currentSession 會呼叫 SessionFactory 的 openSession 。所以 getCurrentSession() 對於 Java EE 來說是更好的獲取 Session 的方法。
一些面試的知識點:
今天想著隨便寫點,為日後回憶做點準備:
=======================過濾器和攔截器===================================================
過濾器<filter>:
攔截器 在服務器 jsp ext resp 應用 改變 每次 常用 fff 一、Filter的功能
filter功能,它使用戶可以改變一個 request和修改一個response. Filter 不是一個servlet,它不能產生一個response,它能夠在一個request到
一、過濾器
servlet3.0提供的註解
@WebFilter
@ServletComponentScan
//註冊器名稱為customFilter,攔截的url為所有
@WebFilter(filterName="customFilter",urlPattern
開發十年,就只剩下這套架構體系了!
>>>
Servlet中的過濾器Filter是實現了javax.servlet.Filter介面的伺服器端程式,主要的用途是過濾字元編碼、做一些業務邏輯判斷等。其工作原理是,只要你在web.xml檔案配置好要攔截的客戶端請求,它都會幫你攔截到請求,此時你就可以對請求或響應(Re windows ron 就是 圖片 渲染 天都 驚人的 領域 其他人 大多數人認為,服務器僅僅是升級後的臺式機。但任何在數據中心工作過的人都知道,它們的差別挺大的。
盡管web服務器每天都要承擔數百萬訪問者的負載,但對於普通用戶來說,它們仍然神秘莫測。以下是關於服務器你可能 ip地址 ces 優勢 現在 增加 升級服務器 com 解決 引擎 大多數小型企業通常都是從公有雲、虛擬主機這些常見的共享托管計劃開始的。因為相對來說,它是最經濟實惠的,而且需要較少的技術知識。
隨著業務的不斷拓展,網站流量越來愈大,對所需的服務器要求就越來越高。這時候就需
簡介
這幾天在回顧Spring的AOP時,對過濾器,攔截器,AOP的關係有點好奇,故記錄做以備份。在實現一些公共邏輯的時候,很多功能通過過濾器,攔截器,AOP都能實現,但是不同的方式有不同的效率。具體有什麼區別,看下文描述。
前後端互動基本邏輯
過濾器
過濾器攔截
迭代器模式,提供了介面訪問容器中的元素,而不需要暴露容器的內部表現。
一、關鍵點
1)先看下這個模式點關鍵點:
遍歷:該模式的最大特點就是提供了遍歷內部集合資料的介面,從而達到訪問集合資料的目
VPN產品中的PKI技術用於CA證書獲取,本地實體資訊配置及VPN證書的生成,目前主流產品有IPSecVPN和SSLVPN。
1、PKI技術是一套Internet安全解決方案,PKI體系結構採用證書管理公鑰,通過第三方的可信機構CA,把使用者的公鑰和使用者的其他標識資訊捆綁
有時候想自動將預製新增到場景中,但是又不想破壞預製的連結關係,這時候可以使用PrefabUtility類進行操作。
1、使用AssetDatabase.GetAssetPath獲取預製路徑
fore
專案啟動時初始化載入 Filter-initFilter--doFilter=====filterChain.dofilter();方法之前的程式執行 Interceptor--preHandle執行springMVC---Controller執行Interceptor--
責任鏈設計模式(Chain of Responsibility)的應用有:Java Web中的過濾器鏈、springmvc中的攔截器鏈,Struts2中的攔截器棧等等。
先看如下一個問題:
給定一個字串“被就業了:),敏感資訊,&l
目錄
1過濾器
全域性過濾器
區域性過濾器
2攔截器
3生命週期
建立
1過濾器
全域性過濾器
格式:第一個引數是過濾器名字,第二個是具體執行方法,方法的引數是即將載入渲染的資料
注意點:全
經過本人的最後測試得出的結論是
由於最近做的專案中有一部分是介面遠端呼叫,用到了接入許可權和業務許可權的鑑定,需要採用SpringMVC的攔截器,以前用Struts2的時候用過攔截器,而SpringMVC的攔截器功能之前沒研究過,所以這次來稍微研究一下,得出的結論是
過濾器,是在java web中,你傳入的request,response提前過濾掉一些資訊,或者提前設定一些引數,然後再傳入servlet或者struts的 action進行業務邏輯,比如過濾掉非法url(不是login.do的地址請求,如果使用者沒有登陸都過濾掉),
自動回帖技術
前言:2012.9月,由於某些原因,我開始編寫一個基於Discuz論壇的自動回帖器,這次的小工作讓我對Cookie有了進一步的認識,充分認識到,利用它實在可以做太多的事了~啊哈哈~話不多說~進入主題吧!
0.驗證碼識別
3年前想做的驗證碼識別已經ok了,參
1、攔截器
package com.wkrj.interceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.sp
前言
這裡瞭解一下restful api的攔截,文字主要介紹三種方式來對api進行攔截,參考本文可實現攔截api,進行一些附加操作,比如列印攔截到的方法所在類名,獲取原始的request,攔截到api https javax request orm bin 支持 exceptio 賬號 intern Spring的HandlerMapping處理器支持攔截器應用。當需要為某些請求提供特殊功能時,例如實現對用戶進行身份認證、登錄檢查等功能。
攔截器必須實現HandlerI 相關推薦
SSH的亂七八糟【過濾器+攔截器+監聽器】
過濾器/攔截器/監聽器 —— Filter、Interceptor、Listener
springboot(5)-- 過濾器 攔截器 監聽器
SpringBoot 過濾器, 攔截器, 監聽器 對比及使用場景
web.xml 中的過濾器(攔截器)Filter與監聽器Listener的作用和區別?
【廣州服務器回收】服務器維護過程中,你需要了解的5個小常識
【廣州服務器租賃】還在用虛擬主機?你的企業該在什麽時候該升級到專用服務器呢?
Spring 過濾器 攔截器 AOP區別
【迭代器模式】—— 資料的遍歷
【閘道器產品】VPN防火牆技術原理
【unity編輯器拓展】使用指令碼新增Prefab到場景中
過濾器+攔截器+controller執行順序
責任鏈設計模式(過濾器/攔截器)
過濾器+攔截器+vue的生命週期
過濾器 攔截器 controller 頁面 的執行順序
過濾器,攔截器適用場合
【自動回帖器/原理】自動回帖器的原理與實現(一)原理篇
【攔截器、過濾器實現單使用者登入】
【SpringBoot】RESTful API攔截-過濾器、攔截器、切片
【Spring】SpringMVC之攔截器