【JAVA】基於MVC架構Java技術薈萃案例演練
作者 白寧超
2016年6月9日22:47:08
閱讀前瞻:本文源於對javaweb相關技術和資料彙總,涉及大量javaweb基礎技術諸如:Servlet執行原理、Get/Post請求的區別、jsp的基本原理和執行框架、jsp的9大隱含物件的使用、MVC開發模式的使用、構建封裝自己dao程式碼庫、以及基於MVC的增刪改查操作等;小結最後還有面向介面程式設計的多資料來源配置與儲存,以及工廠模式的使用。除此之外,後續文章會對cookie、session、JavaBean、監聽、許可權管理、檔案上傳與下載、分頁等諸多技術彙總。本文旨在java-web多技術貫穿於單專案中,逐漸深入的過程,使得大家既學習了java技術路線,也知道其怎麼用。最後會附上原始碼,最後一節重點對所有實現技術小結與彙總,此過程會使用作者專案技術理解、網路資源資料、學習視訊和文件截圖檔案等為參考,力求簡單通俗易學。最後,作者文章佈局採用:1、實驗準備;2、需求分析;3、模組化實現;4、實驗優化;5、技術梳理的寫作思路。(本文原創,轉載標明出處
:基於JAVA-MVC技術的顧客管理專案案例總結)
一、實驗準備階段:
1 win*系統,一般配置筆記本或者桌上型電腦
2 安裝MyEclipse開發平臺,本實驗使用MyEclipse2015(點選下載 訪問密碼 eafa)
3 Mysql資料庫,本實驗採用mysql-installer-community-5.6.14.0.msi(點選下載 訪問密碼 39bf)
4 關於資料庫連線的3個JAR包
4.1 JDBC連結資料庫的jar包,本實驗採用mysql-connector-java-5.1.20.jar(點選下載 訪問密碼 8bb1)
4.2 dbUtils資料庫JAR包,本實驗採用commons-dbutils-1.6.jar(
4.3 c3p0資料庫配置JAR包,本實驗採用c3p0-0.9.1.2.jar(點選下載 訪問密碼 9916)
5 兩個公共檔案
5.1 關於編寫Jquery需要的js檔案,本實驗使用jquery.min.js(點選下載 訪問密碼 3357)
5.2 關於c3p0資料庫配置xml原始檔c3p0-config.xml(點選下載 訪問密碼 33a6)
二、需求分析階段
1 對MyEclipse和MySql的正確安裝,並對MyEclipse環境變數配置:(配置參考文件)
2 要求l使用mysql資料庫去建立資料庫test和表customers(id int 主鍵自增,name String 唯一約束,address String,phone String)
3 採用MVC技術開發,實現M/V/C很好的封裝與解耦,在此基礎完成對顧客表的增刪改查,其中要求資料可以回顯、模糊查詢、容錯等
4 servlet初始化啟動控制多資料來源配置
5 其他諸如分頁、cookie、session、JavaBean、監聽、許可權管理、檔案上傳與下載等後續文章繼續完善優化。
三、資料庫建立階段
# 建立資料庫test create database test; use test; #建立customer表id主鍵自增,name唯一 create table customers( id varchar(11) primary key not null, name varchar(70) not null unique, address varchar(70), phone varchar(70) );
四、基於MVC技術開發階段
1 顧客管理專案環境配置簡介
MVC百度百科:MVC全名是Model View Controller,是模型(model)-檢視(view)-控制器(controller)的縮寫,一種軟體設計典範,用一種業務邏輯、資料、介面顯示分離的方法組織程式碼,將業務邏輯聚集到一個部件裡面,在改進和個性化定製介面及使用者互動的同時,不需要重新編寫業務邏輯。MVC被獨特的發展起來用於對映傳統的輸入、處理和輸出功能在一個邏輯的圖形化使用者介面的結構中。(注:詳細MVC可以參照官方文件或者google)
配置簡介:
1 新建java web專案,預設基礎下分別建立MVC對於的包,以及新增需要配置的jar包、js檔案、xml檔案、imgs等檔案,打通整體開發框架。
2 建立需要完成jsp頁面
2 MVC架構搭建
1、配置檔案的引用
mysql-connector-java-5.1.20.jar:連線資料庫的jar包,放於./WEB-INF/lib下
commons-dbutils-1.6.jar:dbutils的jar包,放於./WEB-INF/lib下
c3p0-0.9.1.2.jar:c3p0的jar包,放於./WEB-INF/lib下
jquery.min.js:用於編寫js的檔案,放於./WebRoot/scripts下
c3p0-config.xml:用於配置資料庫,放於./src下
<?xml version="1.0" encoding="UTF-8"?> <c3p0-config> <named-config name="mvcapp"> <property name="user">root</property> <property name="password">root</property> <property name="driverClass">com.mysql.jdbc.Driver</property> <property name="jdbcUrl">jdbc:mysql:///test</property> <property name="acquireIncrement">5</property> <property name="initialPoolSize">10</property> <property name="minPoolSize">10</property> <property name="maxPoolSize">50</property> <!-- intergalactoApp adopts a different approach to configuring statement caching --> <property name="maxStatements">20</property> <property name="maxStatementsPerConnection">5</property> </named-config> </c3p0-config>View Code
2、 資料層配置
com.cuit.mvc.db包:JdbcUtils.java資料庫連線和釋放方法的封裝
package com.cuit.mvc.db; import java.sql.Connection; import java.sql.SQLException; import javax.sql.DataSource; import com.mchange.v2.c3p0.ComboPooledDataSource; /** * JDBC操作工具 * @author 白寧超 http://www.cnblogs.com/baiboy/ */ public class JdbcUtils { /** * 釋放Connection連結 * @param connection */ public static void releaseConnection(Connection connection){ try{ if(connection!=null) connection.close(); }catch(Exception e){ e.printStackTrace(); } } private static DataSource dataSource = null; static{ dataSource=new ComboPooledDataSource("mvcapp"); } /** * 返回資料來源的一個Connection物件 * @return * @throws SQLException */ public static Connection getConnection() throws SQLException{ return dataSource.getConnection(); } }View Code
com.cuit.mvc.model包:Customer.java實體類的封裝
package com.cuit.mvc.model; public class Customer { private int id; private String name; private String address; private String phone; public int getId() { return id; } public Customer() { } public Customer(String name, String address, String phone) { this.name = name; this.address = address; this.phone = phone; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public String getPhone() { return phone; } public void setPhone(String phone) { this.phone = phone; } @Override public String toString(){ return "Customer [id="+id+",name="+name+",address"+address+ ",phone="+phone+"]"; } }View Code
com.cuit.mvc.dao包:DAO.java最底層公共方法封裝;CustomerDAO提供公共方法的介面;
DAO原始碼:
package com.cuit.mvc.dao; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.sql.Connection; import java.util.List; import org.apache.commons.dbutils.QueryRunner; import org.apache.commons.dbutils.handlers.BeanHandler; import org.apache.commons.dbutils.handlers.BeanListHandler; import org.apache.commons.dbutils.handlers.ScalarHandler; import com.cuit.mvc.db.JdbcUtils; /** * 封裝了基本的CRUD的方法,以供子類繼承使用 * 當前DAO直接在方法中獲取資料庫連線 * @param <T> :當前DAO處理實體的型別是什麼 * @author 白寧超 http://www.cnblogs.com/baiboy/ * */ public class DAO<T> { //此步驟前需要/lib加入commons-dbutils-xx.jar private QueryRunner queryRunner=new QueryRunner(); private Class<T> clazz; public DAO(){ //Type通過Ctrl+Shift+O進行反射Type選擇 Type superClass=getClass().getGenericSuperclass(); if(superClass instanceof ParameterizedType){ ParameterizedType parameterizedType=(ParameterizedType)superClass; Type[] typeArgs=parameterizedType.getActualTypeArguments(); if(typeArgs!=null && typeArgs.length>0){ if(typeArgs[0] instanceof Class) clazz=(Class<T>)typeArgs[0]; } } } /** * 返回某一個欄位的值,或者返回資料表中有多少條記錄等。 * @param sql:SQL語句 * @param args:填充SQL語句的佔位符 * @return */ public <E> E getForValue(String sql,Object ... args) { Connection connection=null; try{ connection=JdbcUtils.getConnection(); return (E) queryRunner.query(connection,sql,new ScalarHandler<T>(),args); }catch(Exception e){ e.printStackTrace(); }finally{ JdbcUtils.releaseConnection(connection); } return null; } /** * 返回T所對應的List * @param sql:SQL語句 * @param args:填充SQL語句的佔位符 * @return */ public List<T> getForList(String sql,Object ... args){ Connection connection=null; try{ connection=JdbcUtils.getConnection(); return queryRunner.query(connection,sql,new BeanListHandler<>(clazz),args); }catch(Exception e){ e.printStackTrace(); }finally{ JdbcUtils.releaseConnection(connection); } return null; } /** * 返回對應T的一個實體類物件 * @param sql:SQL語句 * @param args:填充SQL語句的佔位符 * @return */ public T get(String sql,Object ... args){ Connection connection=null; try{ connection=JdbcUtils.getConnection(); return queryRunner.query(connection,sql,new BeanHandler<>(clazz),args); }catch(Exception e){ e.printStackTrace(); }finally{ JdbcUtils.releaseConnection(connection); } return null; } /** * 該方法封裝了INSERT、DELETE、UPDATE操作 * @param sql:SQL語句 * @param args:填充SQL語句的佔位符 */ public void update(String sql,Object ... args){ Connection connection=null; try{ connection=JdbcUtils.getConnection(); queryRunner.update(connection,sql,args); }catch(Exception e){ e.printStackTrace(); }finally{ JdbcUtils.releaseConnection(connection); } } }View Code
CustomerDAO原始碼:
package com.cuit.mvc.dao; import java.util.List; import com.cuit.mvc.model.CriteriaCustomer; import com.cuit.mvc.model.Customer; public interface CustomerDAO { public List<Customer> getAll();//獲取Customer列表資訊 public void save(Customer customer);//對Customer的新增,通過CTRL+T轉到定義 public void update(Customer customer);//對Customer的更新,通過CTRL+T轉到定義 public Customer get(int id);//獲取Customer實體 public void delete(int id);//根據id進行刪除 public long getCountWithName(String name);//返回name相等的記錄數 //cc封裝了查詢條件,返回查詢條件的list public List<Customer> getForListWithCriteriaCustomer(CriteriaCustomer cc); }View Code
com.cuit.mvc.dao.impl包:CustomerDAOJdbcImpl.java:Customer對CustomerDAO具體方法的實現
package com.cuit.mvc.dao.impl; import java.util.List; import com.cuit.mvc.dao.CustomerDAO; import com.cuit.mvc.dao.DAO; import com.cuit.mvc.model.CriteriaCustomer; import com.cuit.mvc.model.Customer; public class CustomerDAOJdbcImpl extends DAO<Customer> implements CustomerDAO{ public List<Customer> getForListWithCriteriaCustomer(CriteriaCustomer cc) { String sql="select * from customers where name like ? and address like ? " + "and phone like ?"; //修改了CriteriaCustomer的getter方法:使其返回字串中有%% //若返回值為null返回%%,若不返回null則返回:"%"+欄位本身的值+"%" //如上效果如:cc.getName()==null?%%:%+name+% System.out.println(sql); return getForList(sql,cc.getName(),cc.getAddress(),cc.getPhone()); } @Override public List<Customer> getAll() { String sql="select * from customers"; return getForList(sql); } @Override public void save(Customer customer) { String sql="insert customers(name,address,phone) values(?,?,?)"; update(sql, customer.getName(),customer.getAddress(),customer.getPhone()); } @Override public Customer get(int id) { String sql="select * from customers where id=?"; return get(sql,id); } @Override public void delete(int id) { String sql="delete from customers where id=?"; update(sql, id); } @Override public long getCountWithName(String name) { String sql="select count(id) from customers where name=?"; return getForValue(sql, name); } @Override public void update(Customer customer) { String sql="update customers set name=?,address=?,phone=? where id=?"; update(sql,customer.getName(),customer.getAddress(),customer.getPhone(),customer.getId()); } }View Code
3 業務邏輯層
com.cuit.mvc.dao.servlet包:CustomerServlet.java對CustomerDAO公共方法具體實現,以及頁面顯示的控制
package com.cuit.mvc.servlet; import java.io.IOException; import java.io.PrintWriter; import java.lang.reflect.Method; import java.util.List; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.cuit.mvc.dao.CustomerDAO; import com.cuit.mvc.dao.factory.CustomerDAOFactory; import com.cuit.mvc.dao.impl.CustomerDAOJdbcImpl; import com.cuit.mvc.dao.impl.CustomerDAOXMLImpl; import com.cuit.mvc.model.CriteriaCustomer; import com.cuit.mvc.model.Customer; public class CustomerServlet extends HttpServlet { //private CustomerDAO customerDAO=new CustomerDAOJdbcImpl(); //private CustomerDAO customerDAO=new CustomerDAOXMLImpl(); private CustomerDAO customerDAO=CustomerDAOFactory.getInstance().getCustomerDAO(); public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doPost(request, response); } /*public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String method=request.getParameter("method"); switch (method) { case "add": add(request,response); break; case "query": query(request,response); break; case "delete": delete(request,response);break; default: break; } }*/ @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //1 獲取servlet路徑 諸如:/add.do String servletPath=req.getServletPath().substring(1); //去除/和.do得到類似於add這樣字串 String methodName=servletPath.substring(0,servletPath.length()-3); //System.out.println(methodName); try { //利用反射獲取獲取methodName對應的方法 Method method = getClass().getDeclaredMethod(methodName, HttpServletRequest.class,HttpServletResponse.class); //利用反射獲取方法 method.invoke(this, req,resp); } catch (Exception e) { //出錯時候響應出來 resp.sendRedirect("error.jsp"); } } private void edit(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{ String forwordPath="/error.jsp"; //1 獲取請求引數id String idstr=request.getParameter("id"); //2 呼叫CustomeDAO的customerDAO.get(id)獲取和id對應的Customer物件customer try{ Customer customer=customerDAO.get(Integer.parseInt(idstr)); if(customer!=null){ forwordPath="/updatecustomer.jsp"; //3 將customer放在request中 request.setAttribute("customer", customer); } }catch(Exception e){} //4 響應updatecustomer.jsp頁面:轉發 request.getRequestDispatcher(forwordPath).forward(request, response); } private void update(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{ //1 獲取請求引數:id,name,address,phone,oldname String id=request.getParameter("id"); String name=request.getParameter("name"); String oldname=request.getParameter("oldname"); String address=request.getParameter("address"); String phone=request.getParameter("phone"); //2 檢驗name是否被佔用 //2.1 比較name和oldname是否相同,若相同name可用,oldname.equals(name)不如equalsIgnoreCase,資料庫預設大小寫一致的,而equals忽略大小寫 if(!oldname.equalsIgnoreCase(name)){ //不相同,呼叫CustomerDAO的getCountWithName(String name)獲取name在資料庫中是否存在 long count=customerDAO.getCountWithName(name); //大於0, 響應updatecustomer.jsp頁面:通過轉發響應newcustomer.jsp if(count>0){ // 通過request.getAttribute("message")顯示資訊,在頁面上request.getAttribute("message")的方式顯示 // 表單據回顯。address,phone顯示提交的新值, name顯示oldname,而不是新值 request.setAttribute("message", "使用者名稱["+name+"]已經被佔用,請重新填寫!"); // 方法結束 request.getRequestDispatcher("/updatecustomer.jsp").forward(request, response); return; } } //3 若驗證通過,把表單引數封裝為一個Customer物件customer Customer customer=new Customer(name,address,phone); customer.setId(Integer.parseInt(id)); //4 呼叫CustomerDAO的update(Customer customer)執行更新操作 customerDAO.update(customer); //5 重定向到query.do response.sendRedirect("query.do"); } //模糊查詢 private void query(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{ String name=request.getParameter("name"); String address=request.getParameter("address"); String phone=request.getParameter("phone"); CriteriaCustomer cc=new CriteriaCustomer(name,address,phone); //1 呼叫CustomerDAO的getALl方法得到Customer集合 //List<Customer> sustomers=customerDAO.getAll();獲取所有資訊列表 List<Customer> customers=customerDAO.getForListWithCriteriaCustomer(cc); //2 把customer的集合放入request request.setAttribute("customers", customers); //3 轉發頁面index.jsp(不能使用重定向) request.getRequestDispatcher("/index.jsp").forward(request,response); } private void delete(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{ String idstr=request.getParameter("id").trim(); int id=0; try{ id=Integer.parseInt(idstr); customerDAO.delete(id); }catch(Exception e){} response.sendRedirect("query.do"); } //此方法名稱跟頁面add新增的action中add.do匹配 private void add(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{ //1 獲取表單引數:name,address,phone String name=request.getParameter("name"); String address=request.getParameter("address"); String phone=request.getParameter("phone"); //2 檢驗name是否被佔用 //2.1 呼叫CustomerDAO的getCountWithName(String name)獲取name在資料庫中是否存在 long count=customerDAO.getCountWithName(name); if(count>0){ //2.2 若返回值大於0,則相應newcustomer.jsp頁面:①在此頁面顯示一個錯誤資訊②此表單值可以回顯 // 通過request.getAttribute("message")顯示資訊 // 通過value="<%=request.getParameter("name")==null?"":request.getParameter("name")%>"回顯 request.setAttribute("message", "使用者名稱["+name+"]已經被佔用,請重新填寫!"); request.getRequestDispatcher("/newcustomer.jsp").forward(request, response); return; } //3 若驗證通過,把表單引數封裝為一個Customer物件customer Customer customer=new Customer(name,address,phone); //4 呼叫CustomerDAO的save(Customer customer)執行儲存操作 customerDAO.save(customer); //5 重定向到success.jsp頁面 response.sendRedirect("success.jsp"); } }View Code
4 單元測試層
com.cuit.mvc.dao.test包:JdbcUtilsTest.java對CustomerServlet.java各個方法單元測試
package com.cuit.mvc.test; import static org.junit.Assert.*; import java.util.List; import org.junit.Test; import com.cuit.mvc.dao.CustomerDAO; import com.cuit.mvc.dao.impl.CustomerDAOJdbcImpl; import com.cuit.mvc.model.CriteriaCustomer; import com.cuit.mvc.model.Customer; public class CustomerDAOJdbcImplTest { private CustomerDAO customerDAO=new CustomerDAOJdbcImpl(); @Test public void getForListWithCriteriaCustomer(){ CriteriaCustomer cc=new CriteriaCustomer("Tom", null, null); List<Customer> customers=customerDAO.getForListWithCriteriaCustomer(cc); System.out.println(customers); } @Test public void testGetAll() { List<Customer> customers=customerDAO.getAll(); System.out.println(customers); } @Test public void testSaveCustomer() { Customer customer=new Customer("Baijing","Shanghai","134-2345-9086"); customerDAO.save(customer); } @Test public void testGetInt() { Customer cust=customerDAO.get(0); System.out.println(cust); } @Test public void testDelete() { customerDAO.delete(2); } @Test public void testGetCountWithName() { long count=customerDAO.getCountWithName("Tom"); System.out.println(count); } }View Code
5 檢視顯示頁面層
index.jsp:顯示顧客資訊,並支援回顯
<%@page import="com.cuit.mvc.model.Customer"%> <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="<%=basePath%>"> <title>My JSP 'index.jsp' starting page</title> <script type="text/javascript" src="scripts/jquery.min.js"></script> <script type="text/javascript"> $(function(){ $('.delete').click(function(){ var content=$(this).parent().parent().find("td:eq(1)").text(); var flag=confirm("確定要刪除此"+content+"資訊?"); return flag; }); }); </script> </head> <body> <form action="query.do"> <table> <tr> <td>CustomerName:</td> <td><input type="text" name="name"/></td> </tr> <tr> <td>CustomerAddress:</td> <td><input type="text" name="address"/></td> </tr> <tr> <td>CustomerPhone:</td> <td><input type="text" name="phone"/></td> </tr> <tr> <td><input type="submit" value="Query"/></td> <td><a href="newcustomer.jsp">Create New Customer</a></td> </tr> </table> </form> <br/><br/> <% List<Customer> customers=(List<Customer>)request.getAttribute("customers"); if(customers!=null && customers.size()>0){ %> <hr> <br/><br/> <table border="1相關推薦
【JAVA】基於MVC架構Java技術薈萃案例演練
作者 白寧超 2016年6月9日22:47:08 閱讀前瞻:本文源於對javaweb相關技術和資料彙總,涉及大量javaweb基礎技術諸如:Servlet執行原理、Get/Post請求的區別、jsp的基本原理和執行框架、jsp的9大隱含物件的使用、MVC開發模式的使用、構建封裝自己dao程式碼庫
【slighttpd】基於lighttpd架構的Server專案實戰(4)—簡單的echo伺服器
轉載地址:https://blog.csdn.net/jiange_zh/article/details/50636536 在這一部分,我們將對上一篇中的master-worker進行拓展,成為一個簡單的echo伺服器。 這一步我們需要新增兩個類:Listener和Connection;
【slighttpd】基於lighttpd架構的Server專案實戰(3)—Master&Worker模式
轉載地址:https://blog.csdn.net/jiange_zh/article/details/50636180 現在,我們開始一步步構建我們的專案了~ Master-Worker模式 本次一共涉及2個類:Master和Worker; 以下是兩者的標頭檔案: /****
【slighttpd】基於lighttpd架構的Server專案實戰(2)—預備知識之libevent
轉載地址:https://blog.csdn.net/jiange_zh/article/details/50631393 簡介 由於本專案是純非同步的,而對於大量 socket 連線,使用 select 並不高效。(參見我的另一篇博文:epoll簡介) 事實上,大部分系統提供了處理大
【slighttpd】基於lighttpd架構的Server專案實戰(7)—http-parser
轉載地址:https://blog.csdn.net/jiange_zh/article/details/50639178 對於http伺服器,http request的解析是比較麻煩的,由於我們的重點並不在這上面,所以這一部分不打算自己編寫,而是使用開源的http-parser庫,下面我們將使
【slighttpd】基於lighttpd架構的Server專案實戰(8)—狀態機機制回顧
轉載地址:https://blog.csdn.net/jiange_zh/article/details/50640270 有限狀態機FSM(Finite State Machine) 關於狀態機的一個極度確切的描述是它是一個有向圖形,由一組節點和一組相應的轉移函式組成。狀態機通過響應一系列
【slighttpd】基於lighttpd架構的Server專案實戰(5)—TCP的TIME_WAIT狀態
轉載地址:https://blog.csdn.net/jiange_zh/article/details/50637549 上一節我們已經開發了一個簡單的echo伺服器,在這裡我們先不急著繼續下去,先看看一些小細節! 在listener的程式碼中,對於監聽套接字,我設定了SO_REUSEAD
【slighttpd】基於lighttpd架構的Server專案實戰(6)—預備知識之Http
接下來,我們開始http部分的開發。在此之前,有必要先學習一下HTTP協議~ 簡介 超文字傳輸協議(Hypertext Transfer Protocol,簡稱HTTP)是應用層協議,是一種請求/響應式的協議,即一個客戶端與伺服器建立連線後,向伺服器傳送
【Java】Spring MVC 擴展和SSM框架整合
nco span con odin typealias eal nag key ping 開發web項目通常很多地方需要使用ajax請求來完成相應的功能,比如表單交互或者是復雜的UI設計中數據的傳遞等等。對於返回結果,我們一般使用JSON對象來表示,那麽Spring MVC
【Java】基於jsoup爬蟲實現(從智聯獲取工作資訊)
這幾天在學習Java解析xml,突然想到Dom能不能解析html,結果試了半天行不通,然後就去查了一些資料,發現很多人都在用Jsoup解析html檔案,然後研究了一下,寫了一個簡單的例項,感覺還有很多地方需要潤色,在這裡分享一下我的例項,歡迎交流指教!後續想通過Java把資料匯入到Excel或者
【轉】基於Redis Lua指令碼實現的分散式鎖(Java實現)
最近專案中需要用到一個分散式的鎖,考慮到基於會話節點實現的zookeeper鎖效能不夠,於是想使用redis來實現一個分散式的鎖。看了網上的幾個實現方案後,發現都不夠嚴謹。比如這篇:用Redis實現分散式鎖裡面設計的鎖有個最大的問題是鎖的超時值TTL會一直被改寫
【Java】基於TCP協議多執行緒伺服器-客戶端互動控制檯聊天室簡例
前兩天想到一個手機APP專案,使用到藍芽,發現BluetoothSocket和J2EE網路變成的Socket差不多,使用之餘順手寫一個多執行緒伺服器與客戶端互動實現聊天室的一個小例子,方便新人學習網路程式設計模組,期間使用到多執行緒和IO輸入輸出流的
【金陽光測試】基於控件核心技術探討---Android自己主動化系列(2)---2013年5月
進程 實用 版本 信號 監聽 dialog otto 設計 核心技術 第一講分享了下安卓自己主動化一些概況和一些自己主動化框架現狀和技術可以解決什麽樣的問題。這次課就深入到android世界裏面。遨遊、翺翔。深入了解自己主動化測試核心技術。
【java】深入了解JAVA可變長度的參數
這一 args 必須 滿足 深入 itl 重載 編碼 創建 到J2SE 1.4為止,一直無法在Java程序裏定義實參個數可變的方法——因為Java要求實參(Arguments)和形參(Parameters)的數量和類型都必須逐一匹配,而形參的數目是在
【轉】JavaScript MD5 與 Java MessageDigest 加密後的值相同
cda padding highlight xe7 net abs algorithm urn -a function integer(n) { return n%(0xffffffff+1); } function shr(a,b) { a=integer(a);
【轉】基於localStorage的資源離線和更新技術
同時 前端 event 原來 read 前端資源 獲取 tex tor ServiceWorker的資源離線與更新 ServiceWorker是替代Application Cache的機制,目前為止其兼容性很差。 localStorage資源離線緩存與更新 基本思路:將
【MySQL】【高可用】基於MHA架構的MySQL高可用故障自動切換架構
bin candidate nlog repo sage $1 內容 data from 基於MHA架構的MySQL高可用切換架構 環境: ? CentOS7+MySQL 5.7 + GTID 業務系統:mainBusiness ? nod
【轉】JMeter完成一個java請求的壓測
span 依賴 壓測 雙擊 led long urn 相關 記錄 JMeter完成java請求的壓力測試詳解以及問題總結 原文地址:http://www.cnblogs.com/zhaoxd07/p/4895224.html 作者:KK_Yolan
【Java】「深入理解Java虛擬機器」學習筆記(1) - Java語言發展趨勢
這本書寫的比較早,現在這些功能都已經不同程度的實現了。 1、模組化 JDK9之前的版本都是一個整體,使用者可能只需要使用一個小功能,但他不得不下載整個JDK。不能滿足定製化需求,顯然Java語言的發展因此大大受限。 所以,Sun公司在OpenJDK建立了一個Jigsaw(拼圖)的專案來推動模
【Java】「深入理解Java虛擬機器」學習筆記(2)-記憶體管理
一、執行時資料區 JVM在執行Java程式的時候,將其執行時資料區劃分為若干不同區域。它們的用途和建立及銷燬的時間不同。 1、程式計數器(Program Counter Register) 是一塊很小的記憶體空間。當執行緒執行的是Java方法,它記錄的是當前正在執行的