摘要:現在,我們使用了的話,那么框架內部就能幫我們封裝了。每個中都有和這樣的方法,沒必要的。我們抽取出來,通過配置文件來把這兩個方法替換掉,那么我們的程序就會更加優雅了。于是乎,就應運而生了。因此,學習的時候,不了解是沒有任何關系的。
前言
這是Strtus的開山篇,主要是引入struts框架...為什么要引入struts,引入struts的好處是什么,以及對Struts2一個簡單的入門....
為什么要引入struts?既然Servlet能夠完成的事,我們為啥要用框架呢??
框架幫我們封裝了很多常用的功能
把Web帶過來的參數自動封裝到JavaBean中[以前,我們剛開始學的時候是單個單個來獲取參數的,后來我們又使用了BeanUtils寫工具方法來幫我們封裝]。現在,我們使用了Struts2的話,那么框架內部就能幫我們封裝了。
更加靈活[不用把路徑等信息寫死在程序上],對于路徑我們使用配置文件來進行管理,如果目錄發生了變化,也不用一個一個去修改每個程序的路徑。
每個Servlet中都有doGet和doPost這樣的方法,沒必要的。我們抽取出來,通過配置文件來把這兩個方法替換掉,那么我們的程序就會更加優雅了。
于是乎,struts2就應運而生了。
自定義struts在正式講解struts之前,我們來看一下,以我們現在的水平,能夠怎么優化它。。
以用戶的登陸注冊案例來進行說明
傳統的用戶登陸注冊dao
public class UserDao { public User login(User user) { if ("aaa".equals(user.getUsername()) && "123".equals(user.getPsd())) { System.out.println("登陸成功!"); return user; } else { System.out.println("登陸失敗!"); return null; } } public void register(User user) { System.out.println("注冊成功!" + user.getUsername()); } }
service
public class UserService { private UserDao userDao = new UserDao(); public User longin(User user) { return userDao.login(user); } public void register(User user) { userDao.register(user); } }
loginServlet
@javax.servlet.annotation.WebServlet(name = "LoginServlet",urlPatterns = "/LoginServlet") public class LoginServlet extends javax.servlet.http.HttpServlet { protected void doPost(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException { //得到用戶帶過來的數據,封裝到Bean對象中 String username = request.getParameter("username"); String psd = request.getParameter("psd"); User user = new User(); user.setPsd(psd); user.setUsername(username); try { //調用Service方法 UserService userService = new UserService(); userService.longin(user); //登陸成功跳轉到首頁 request.getRequestDispatcher("/index.jsp").forward(request, response); } catch (Exception e) { e.printStackTrace(); //登陸失敗,跳轉到相關的提示頁面 request.setAttribute("message","登陸失敗了!!!"); request.getRequestDispatcher("/message.jsp").forward(request, response); } } protected void doGet(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException { this.doPost(request, response); } }
registerServlet
@javax.servlet.annotation.WebServlet(name = "RegisterServlet",urlPatterns = "/RegisterServlet") public class RegisterServlet extends javax.servlet.http.HttpServlet { protected void doPost(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException { //得到用戶帶過來的數據,封裝到Bean對象中 String username = request.getParameter("username"); String psd = request.getParameter("psd"); User user = new User(); user.setPsd(psd); user.setUsername(username); try { //調用Service方法 UserService userService = new UserService(); userService.register(user); //注冊成功跳轉到登陸界面 request.getRequestDispatcher("/login.jsp").forward(request, response); //注冊成功,我也可以跳轉到首頁 //request.getRequestDispatcher("/index.jsp").forward(request, response); } catch (Exception e) { e.printStackTrace(); //注冊失敗,跳轉到相關的提示頁面 request.setAttribute("message","注冊失敗了!!!"); request.getRequestDispatcher("/message.jsp").forward(request, response); } } protected void doGet(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException { this.doPost(request, response); } }
login.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>$Title$
register.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>$Title$
上面的代碼已經經過了測試,是可以跑起來的。
①:跳轉頁面的路徑是寫死的。我在注冊成功了以后,我可以跳轉到首頁上,也可以跳轉到登陸的界面上。如果我要選擇其中的一個,就必須修改源代碼...
②:一個功能對應一個Servlet,太麻煩了...寫了LoginServlet,還要寫RegisterServlet....
新型的用戶登陸注冊我們會發現,無論什么Servlet上最終還是跳轉到相對應的JSP頁面的...也就是說,第一和第二步驟【封裝數據、調用Service】我們可以封裝起來...只要返回uri給Servlet跳轉到JSP頁面就好了。
LoginAction返回的uri分兩種情況:
如果是轉發,那么返回的是RequestDispatcher對象
如果是重定向,那么返回的是字符串
/** * Created by ozc on 2017/4/26. ** 一個Action對應一個Servlet,Action負責處理具體的請求 */ public class LoginAction { public Object login(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException { Object uri ; //得到用戶帶過來的數據,封裝到Bean對象中 String username = request.getParameter("username"); String psd = request.getParameter("psd"); User user = new User(); user.setPsd(psd); user.setUsername(username); try { //調用Service方法 UserService userService = new UserService(); userService.longin(user); //登陸成功跳轉到首頁 request.getSession().setAttribute("user", user); //跳轉到首頁的時候需要重定向 //response.sendRedirect(request.getContextPath() + "/index.jsp"); //如果是重定向,那么返回的是字符串 uri = "/index.jsp"; return uri; } catch (Exception e) { e.printStackTrace(); //登陸失敗,跳轉到相關的提示頁面 request.setAttribute("message","登陸失敗了!!!"); //request.getRequestDispatcher("/message.jsp").forward(request, response); //如果是轉發,那么返回的是RequestDispatcher對象 uri = request.getRequestDispatcher("/message.jsp"); return uri; } } }
LoginServlet就可以寫成這樣了:
protected void doPost(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException { //得到LoginAction對象 LoginAction loginAction = new LoginAction(); Object uri = loginAction.login(request, response); //是重定向 if (uri instanceof String) { response.sendRedirect(request.getContextPath() + uri); } else { //是轉發,強轉成是RequestDispatcher對象 ((RequestDispatcher) uri).forward(request, response); } }RegisterAction
RegisterAction
/** * Created by ozc on 2017/4/26. * * 一個Action對應一個Servlet,Action負責處理具體的請求 */ public class RegisterAction { public Object register(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException { Object uri ; //得到用戶帶過來的數據,封裝到Bean對象中 String username = request.getParameter("username"); String psd = request.getParameter("psd"); User user = new User(); user.setPsd(psd); user.setUsername(username); try { //調用Service方法 UserService userService = new UserService(); userService.register(user); //登陸成功跳轉到登陸頁面 uri = request.getRequestDispatcher("/login.jsp"); return uri; } catch (Exception e) { e.printStackTrace(); //注冊失敗,跳轉到相關的提示頁面 request.setAttribute("message","注冊失敗了!!!"); //request.getRequestDispatcher("/message.jsp").forward(request, response); uri = request.getRequestDispatcher("/message.jsp"); return uri; } } }
RegisterServlet
protected void doPost(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException { //得到RegisterAction RegisterAction registerAction = new RegisterAction(); Object uri = registerAction.register(request, response); //是重定向 if (uri instanceof String) { response.sendRedirect(request.getContextPath() + uri); } else { //是轉發,強轉成是RequestDispatcher對象 ((RequestDispatcher) uri).forward(request, response); } }思考
到目前為止,我們搞了兩個Action類來封裝Servlet的邏輯代碼,我們再次看回Servlet的代碼。
可以很清楚地發現:兩個實現不同功能的Servlet僅僅是調用的Action不同....如果是僅僅調用的Action不同【通過反射來調用不同的Action】,那么我們應該想到使用一個Servlet來管理整個項目,也就是說:整個web項目只有一個核心的控制器
問題:
①:我們在之前是直接指明Servlet的映射路徑了,現在要ActionServlet處理所有的請求,我們只要定一個規則:只要后綴為.action的,那么都交由核心控制器ActionServlet來控制....
②:現在全部的請求已經交由ActionServlet控制,那怎么知道調用的是哪個Action???我們可以通過請求的uri,比如:http://localhost:8080/login.action,其中login就代表的是調用LoginAction..也就是說login=LoginAction,我們可以通過properties文件來配置..
③:現在我們已經知道了調用的是哪個Action了,但是Action可能不僅僅只有一個方法,我們還要在調用的時候,指定的方法名是什么.這很簡單,一般我們都是職責分工明確的,method=login....并且,調用的Action和具體的方法也是有關系的,不可能是孤立存在的。因此,我們的配置文件是不能使用properties的,需要使用XML
④:在調用方法的時候,是返回一個Object的uri的,uri的類型可能是String、也可以能是RequestDispatcher、并且返回的結果可能有幾種情況的【可能跳轉到首頁,也可能跳轉到登陸界面】
⑤:Action調用的方法和返回的uri也是是有關系的!.....不同的Action調用不同的方法,返回的uri也是不同的....
⑥:要跳轉到哪個頁面上,可以通過標識量來識別....比如:success表示成功執行,如果要重定向那么多加個type類型,如果不重定向就沒有type類型..路徑使用path來表示..因此,在具體的Action中,就不需要返回具體的uri,只要返回一個標識量即可
畫一張圖來梳理一下思路:
XML配置我們可以寫出這樣的XML配置,當ActionServlet初始化的時候,讀取XML配置文件,就知道調用的是什么Action,Action中的什么方法,以及跳轉到哪個頁面上了。
/index.jsp /message.jsp /message.jsp /message.jsp
為了更好地管理這些信息,我們應該使用JavaBean來對它們封裝
ActionMappingManager-------管理全部的Action
/** * Created by ozc on 2017/4/26. * * 該類管理著全部的Action * * 要管理全部的Action,就需要用一個容器來裝載這些Action * * 選擇Map集合是最合適的,可以通過key來得到Action,key就是中的name屬性 * */ public class ActionMappingManager { private Map map = new HashMap<>(); //注意:外界都是通過name來得到對應的Action的,并不會獲取得到整個Manager public ActionMapping getActionMapping(String name) { return map.get(name); } }
ActionMapping----表示單個的Action
public class ActionMapping { //所有的results private Mapresults; //關鍵字name private String name; //要調用的Action路徑 private String className; //Action中的方法 private String method; public Map getResults() { return results; } public void setResults(Map results) { this.results = results; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getClassName() { return className; } public void setClassName(String className) { this.className = className; } public String getMethod() { return method; } public void setMethod(String method) { this.method = method; } }
Results---表示的是結果視圖
/** * Created by ozc on 2017/4/26. * * 該類表示的是結果視圖 * * * */ public class Results { //方法返回的標識 private String name; //要跳轉的方式 private String type; //要跳轉的頁面 private String page; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getType() { return type; } public void setType(String type) { this.type = type; } public String getPage() { return page; } public void setPage(String page) { this.page = page; } }ActionMappingManager讀取配置文件
在ActionMappingManager中,應該讀取配置文件,然后把信息全部封裝到里邊去...
/** * Created by ozc on 2017/4/26. * * 該類管理著全部的Action * * 要管理全部的Action,就需要用一個容器來裝載這些Action * * 選擇Map集合是最合適的,可以通過key來得到Action,key就是ActionServlet中的name屬性 * */ public class ActionMappingManager { private Map allAction ; public ActionMappingManager() { this.allAction = new HashMap<>(); //讀取配置文件信息 init(); } public void init() { /********通過DOM4J讀取配置文件信息*********/ try { //得到解析器 SAXReader saxReader = new SAXReader(); //讀取在類目錄下的mystruts.xml文件 InputStream stream = ActionMappingManager.class.getClassLoader().getResourceAsStream("mystruts.xml"); //得到代表XML文件的Document對象 Document document = saxReader.read(stream); //通過XPATH直接得到所有的Action節點 List list = document.selectNodes("http://action"); //得到每個Action節點 for (int i = 0; i < list.size(); i++) { Element action = (Element) list.get(i); //把得到每個Action的節點信息封裝到ActionMapping中 ActionMapping actionMapping = new ActionMapping(); String name = action.attributeValue("name"); String method = action.attributeValue("method"); String className = action.attributeValue("className"); actionMapping.setName(name); actionMapping.setMethod(method); actionMapping.setClassName(className); //得到action節點下的所有result節點 List results = action.elements("result"); //得到每一個result節點 for (int j = 0; j < results.size(); j++) { Element result = (Element) results.get(j); //把得到每個result節點的信息封裝到Results中 Results results1 = new Results(); //得到節點的信息 String name1 = result.attributeValue("name"); String type = result.attributeValue("type"); String page = result.getText(); results1.setName(name1); results1.setType(type); results1.setPage(page); //把result節點添加到ActionMapping的集合中 actionMapping.getResults().put(name1, results1); } //最后把得到每個ActionMapping的信息添加到ActionMappingManager中 allAction.put(name, actionMapping); } } catch (DocumentException e) { new RuntimeException("初始化的時候出錯了!“" + e); } } //注意:外界都是通過name來得到對應的Action的,并不會獲取得到整個Manager public ActionMapping getActionMapping(String name) { return allAction.get(name); } }
使用init()方法只加載創建一個ActionManagerMapping對象,并設置在Web容器啟動了該Servlet就啟動
/** * Created by ozc on 2017/4/26. * * * Web容器一啟動的時候,該類就應該加載了,在web.xml文件中配置onloadStart */ public class ActionServlet extends HttpServlet { //該對象封裝了所有的XML信息 ActionMappingManager actionMappingManager ; @Override public void init() throws ServletException { //讓ActionMappingManager對象只有一個! actionMappingManager = new ActionMappingManager(); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { try { //得到用戶的uri String uri = request.getRequestURI(); //截取uri的關鍵部分-----截完應該是login uri = uri.substring(uri.lastIndexOf("/") + 1, uri.lastIndexOf(".")); //通過uri得到配置文件中的action信息 ActionMapping actionMapping = actionMappingManager.getActionMapping(uri); //得到action的類名,方法名 String className = actionMapping.getClassName(); String method = actionMapping.getMethod(); //通過反射創建出Action的對象,調用對應的方法 Class t = Class.forName(className); Object o = t.newInstance(); //注意:這里的參數是接口的class,不是單純的request的class,單純的class是實現類 Method m = t.getMethod(method, HttpServletRequest.class, HttpServletResponse.class); //調用方法,得到標記 String returnFlag = (String) m.invoke(o, request, response); //通過標記得到result的具體信息 Results result = actionMapping.getResults().get(returnFlag); String type = result.getType(); String page = result.getPage(); //判斷是重定向還是轉發,為空就是轉發,反則是重定向 if (type == null) { response.sendRedirect(page); } else { request.getRequestDispatcher(request.getContextPath() + page).forward(request, response); } } catch (Exception e) { e.printStackTrace(); } } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } }
具體的Action的方法只要返回一個標識量即可,我們通過標識量來得到具體的跳轉頁面url和跳轉的方法的。。。
效果: 自定義MyStruts總結:由于傳統web的Controller模塊存在弊端:
一些功能重復使用,代碼過于重復了。
跳轉的頁面寫死了。改變需求的時候需要更改源代碼
本博文主要模擬Struts的開發流程
使用一個ActionServlet核心控制器來管理全部的Web請求,寫XML配置文件,讀取配置文件。
ActionMapping封裝了Action的基本信息,在XML配置文件中就是讀取Action的基本信息,封裝到JavaBean上,最后使用ActionMapping類的集合統一管理起來。
當用戶訪問的時候,我們根據url也就是Action的名稱反射出對應的類,來對其進行操作。
再根據XML文件的配置信息來確定跳轉方法、跳轉的url
我們現在學習的是Struts2,其實Struts1和Struts2在技術上是沒有很大的關聯的。 Struts2其實基于Web Work框架的,只不過它的推廣沒有Struts1好,因此就拿著Struts這個名氣推出了Struts2框架。
因此,學習Struts2的時候,不了解Struts1是沒有任何關系的。
在前面,已經說明了為什么要引入Struts框架,其實就是為了提高開發效率...
Struts2框架預先實現了一些功能:
請求數據自動封裝
文件上傳的功能
對國際化功能的簡化
數據效驗功能.......等等
Struts2開發步驟我們就直接來講解Struts2的開發步驟是什么吧....在了解它的細節之前,先要把配置環境搭好!
引入jar文件完整的struts中的jar包有80多個,我們日常開發是不需要那么多個的。一般我們導入的jar包有8個:
commons-fileupload-1.2.2.jar 【文件上傳相關包】
commons-io-2.0.1.jar【文件上傳相關包】
struts2-core-2.3.4.1.jar 【struts2核心功能包】
xwork-core-2.3.4.1.jar 【Xwork核心包】
ognl-3.0.5.jar 【Ognl表達式功能支持表】
commons-lang3-3.1.jar 【struts對java.lang包的擴展】
freemarker-2.3.19.jar 【struts的標簽模板庫jar文件】
javassist-3.11.0.GA.jar 【struts對字節碼的處理相關jar】
配置web.xml在web.xml中配置的過濾器,其實就是在為struts進行初始化工作
值得注意的是:如果該web.xml配置了多個fileter,那么struts的filter需要在最后面!
開發Actionstruts2 org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter struts2 /*
開山篇我們已經說了,Servlet的業務代碼,我們都使用Action來代替...Action類一般繼承著ActionSupport
Action類也叫動作類,處理請求的類。
public class HelloAction extends ActionSupport { @Override public String execute() throws Exception { System.out.println("helloworld"); return "success"; } }
至于execute()方法是什么,我們先不要去管它,為啥要返回一個String,我們也不要去管它....只要記住開發步驟,并且,我們的Action類是要繼承ActionSupport類的
配置struts.xml至于配置struts.xml,我們可以在文件中找到相對應的模版代碼的...最終修改成下面這個樣子就行了:
/index.jsp
看完上面的配置文件,是非常像我們開山篇寫的struts框架的配置文件的....
效果:在地址欄中直接輸入hello,就跳轉到index.jsp頁面了。并且,execute()中的語句被執行了...
Struts2執行流程我們來簡單地了解一下Struts的執行流程,然后再慢慢對上面的開發步驟的部分進行講解....
服務器啟動下邊我說的都是struts流程的重點:
加載web.xml文件
找到我們配置的filter中的StrutsPrepareAndExecuteFilter
StrutsPrepareAndExecuteFilter在里邊執行init()方法
一直到Dispatcher dispatcher = init.initDispatcher(config);,初始化dispatcher
在初始化dispatcher的時候加載struts-default.xml和我們配置的struts.xml
下面用GIF圖來看看它的執行過程:
細心的朋友可能會發現,我們在struts.xml的package節點下,extends了struts-default....那struts-default究竟是什么東西呢?
我們找到它的源碼:
我們發現了一大堆的Bean,interceptor,result-type,interceptor-stack...下邊我來講解一下它們是干嘛用的...
bean指定了struts在運行的時候需要創建的對象類型
在運行struts的時候,可能需要創建一些對象,那么就通過Bean來指定
interceptor是struts定義的攔截器,一共有32個
前邊已經說了,Struts為我們實現了一些功能,就是通過攔截器來實現的。
result-type是跳轉結果的類型
Action業務方法中的返回值,我們發現幾個實用的:redirect【重定向】、dispatcher【轉發】、redirectAction【重定向到Action資源】、stream【文件下載的時候用】...跳轉結果的類型也在這里定義了
interceptor-stack是攔截器的棧
攔截器有32個,我們可能會使用很多的攔截器,不可能一個一個來調用,于是提供了攔截器棧...其實可以簡單看成文件夾和文件之間的關系
default-interceptor-ref是默認執行的攔截器棧
default-class-ref class是默認的執行Action類
還要補充的就是:默認的攔截器棧有18個攔截器....
攔截器和過濾器攔截器和過濾器都是攔截資源的
攔截器只攔截Action請求,是struts的概念...
過濾器攔截web的所有資源,是Servlet的概念...
小總結服務器啟動的時候,其實就是加載了web.xml文件,然后調用init()方法去加載struts.xml和struts-default.xml之類的文件.....
注意:此時的攔截器是還沒有被調用的。
訪問階段在服務器啟動的階段,僅僅是加載了各種的xml文件...那么當我們訪問Action的時候,它的執行流程是怎么的呢?
首先,它會創建我們在struts.xml中配置的Action對象
接著,它會按照默認的順序執行18個攔截器【也就是調用默認攔截器棧】
最后,它會執行Action的業務方法【也就是execute(),我們在struts.xml文件中配置了什么,就執行什么業務方法】
值得注意的是:每訪問Action一次,它就會創建一個對象...它并不是和Servlet一樣只有一個對象...因此它是線程安全的.
深入講解struts.xml這是我們的struts.xml的內容,相信現在對它也不會太陌生了...
package/index.jsp
package其實就是包,那包用來干什么?包就是用來管理Action
通常來說,我們都是一個業務模版對應一個package
namename是包的名字,值得注意的是,包的名稱是不能重復的。
extendsextends代表的是當前包繼承著哪個包。在struts中,包一定要繼承著struts-default
abstract在package中還有abstract這個屬性,使用該屬性時:表明當前包被其他的包繼承...并且,在package下不能有action,否則會出錯!
namespace在package中還有namespace這個屬性---名稱空間....它是作為路徑的一部分的,默認是"/"
actoinaction:配置請求路徑與Action類的映射關系
namename是請求路徑的名字
classclass是處理action類的全名
methodmethod是調用的方法名稱
resultresult代表的是Action中業務方法返回的值
namename是action處理返回的值
typetype是跳轉的類型
文本值文本值是跳轉的路徑
細節前邊已經說了,一個package應該對應一個業務模塊..目的就是把職能細分出來...
struts為了讓我們更好地管理xml文件,它還可以這樣做:在不同的模塊中用不同的xml文件進行描述...
最后在struts.xml文件中將其引入即可..
如果文章有錯的地方歡迎指正,大家互相交流。習慣在微信看技術文章,想要獲取更多的Java資源的同學,可以關注微信公眾號:Java3y
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/68730.html
摘要:前言由于寫的文章已經是有點多了,為了自己和大家的檢索方便,于是我就做了這么一個博客導航。 前言 由于寫的文章已經是有點多了,為了自己和大家的檢索方便,于是我就做了這么一個博客導航。 由于更新比較頻繁,因此隔一段時間才會更新目錄導航哦~想要獲取最新原創的技術文章歡迎關注我的公眾號:Java3y Java3y文章目錄導航 Java基礎 泛型就這么簡單 注解就這么簡單 Druid數據庫連接池...
摘要:要是使用到日歷的話,我們想到使用這個日歷類上面僅僅是我個人總結的要點,如果有錯誤的地方還請大家給我指正。 納稅服務系統總結 納稅服務系統是我第一個做得比較大的項目(不同于javaWeb小項目),該項目系統來源于傳智Java32期,十天的視頻課程(想要視頻的同學關注我的公眾號就可以直接獲取了) 我跟著練習一步一步完成需求,才發覺原來Java是這樣用來做網站的,Java有那么多的類庫,頁面...
摘要:性能會有所降低一點內容,刷新整個頁面用戶的操作頁面會中斷整個頁面被刷新了就是能夠做到局部刷新三對象是中最重要的一個對象。頭信息已經接收,響應數據尚未接收。 一、什么是Ajax Ajax(Asynchronous JavaScript and XML) 異步JavaScript和XML Ajax實際上是下面這幾種技術的融合: (1)XHTML和CSS的基于標準的表示技術 (2)DOM進...
摘要:甲乙交易活動不需要雙方見面,避免了雙方的互不信任造成交易失敗的問題。這就是的核心思想。統一配置,便于修改。帶參數的構造函數創建對象首先,就要提供帶參數的構造函數接下來,關鍵是怎么配置文件了。 前言 前面已經學習了Struts2和Hibernate框架了。接下來學習的是Spring框架...本博文主要是引入Spring框架... Spring介紹 Spring誕生: 創建Spring的...
摘要:前言上一次我們對的應用進行了一次全面的分析,這一次我們來聊聊。 showImg(https://segmentfault.com/img/remote/1460000020077803?w=1280&h=853); 前言 上一次我們對Paging的應用進行了一次全面的分析,這一次我們來聊聊WorkManager。 如果你對Paging還未了解,推薦閱讀這篇文章: Paging在Recy...
閱讀 1637·2019-08-30 15:54
閱讀 2383·2019-08-30 15:52
閱讀 2067·2019-08-29 15:33
閱讀 3047·2019-08-28 17:56
閱讀 3245·2019-08-26 13:54
閱讀 1680·2019-08-26 12:16
閱讀 2455·2019-08-26 11:51
閱讀 1655·2019-08-26 10:26