摘要:前言為了鞏固開(kāi)發(fā)的流程,我們?cè)倌靡粋€(gè)客戶(hù)關(guān)系管理系統(tǒng)來(lái)練手成果圖我們完成的就是下面的項(xiàng)目搭建配置環(huán)境配置導(dǎo)入開(kāi)發(fā)包建立開(kāi)發(fā)用到的程序包在數(shù)據(jù)庫(kù)創(chuàng)建相對(duì)應(yīng)的表開(kāi)發(fā)實(shí)體開(kāi)發(fā)實(shí)體十分簡(jiǎn)單,對(duì)照著數(shù)據(jù)庫(kù)的表就行了各種開(kāi)發(fā)獲取數(shù)據(jù)庫(kù)連接池的導(dǎo)入配置文
前言
為了鞏固開(kāi)發(fā)的流程,我們?cè)倌靡粋€(gè)客戶(hù)關(guān)系管理系統(tǒng)來(lái)練手...!成果圖
我們完成的就是下面的項(xiàng)目!
搭建配置環(huán)境配置Tomcat
導(dǎo)入開(kāi)發(fā)包
建立開(kāi)發(fā)用到的程序包
在數(shù)據(jù)庫(kù)創(chuàng)建相對(duì)應(yīng)的表
CREATE TABLE customer ( id VARCHAR(40) PRIMARY KEY, name VARCHAR(20) NOT NULL, gender VARCHAR(10) NOT NULL, birthday DATE, cellphone VARCHAR(30) NOT NULL, email VARCHAR(30), preference VARCHAR(200), type VARCHAR(20), description VARCHAR(255) );開(kāi)發(fā)實(shí)體
開(kāi)發(fā)實(shí)體十分簡(jiǎn)單,對(duì)照著數(shù)據(jù)庫(kù)的表就行了!
private String id; private String name ; private String gender ; private Date birthday ; private String cellphone ; private String eamil ; private String preference ; private String type ; private String description; //....各種setter、getter開(kāi)發(fā)獲取數(shù)據(jù)庫(kù)連接池的Utils 導(dǎo)入配置文件
開(kāi)發(fā)提供數(shù)據(jù)連接池的工具類(lèi)com.mysql.jdbc.Driver jdbc:mysql://localhost:3306/zhongfucheng root root 5 10 5 20 com.mysql.jdbc.Driver jdbc:mysql://localhost:3306/zhongfucheng root root 5 10 5 20 oracle.jdbc.driver.OracleDriver jdbc:oracle:thin:@//localhost:1521/事例名... 用戶(hù)名 密碼 5 10 5 20
public class Utils2DB { private static ComboPooledDataSource comboPooledDataSource = null; static { //它會(huì)自動(dòng)尋找配置文件,節(jié)點(diǎn)為mysql的數(shù)據(jù)庫(kù)(默認(rèn)就是Mysql) comboPooledDataSource = new ComboPooledDataSource(); } public static DataSource getDataSource() { return comboPooledDataSource ; } public static Connection connection() { try { return comboPooledDataSource.getConnection(); } catch (SQLException e) { e.printStackTrace(); throw new RuntimeException("數(shù)據(jù)庫(kù)初始化失敗了!"); } } }開(kāi)發(fā)UUID工具類(lèi)
public class WebUtils { public static String makeId() { return UUID.randomUUID().toString(); } }開(kāi)發(fā)DAO
DAO應(yīng)該提供增加客戶(hù)和查詢(xún)用戶(hù)的功能
增加用戶(hù)public void addCustomer(Customer customer) { QueryRunner queryRunner = new QueryRunner(Utils2DB.getDataSource()); String sql = "INSERT INTO customer (id,name, gender, birthday, cellphone, preference, type, description) VALUES (?, ?, ?, ?, ?, ?, ?, ?,?)"; //得到用戶(hù)傳遞進(jìn)來(lái)的數(shù)據(jù) String id = customer.getId(); String name = customer.getName(); String gender = customer.getGender(); String cellphone = customer.getCellphone(); String email = customer.getEmail(); String preference = customer.getPreference(); String type = customer.getType(); String description = customer.getDescription(); //對(duì)于日期,要轉(zhuǎn)換一下 Date date = customer.getBirthday(); SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd"); String birthday = simpleDateFormat.format(date); try { //向數(shù)據(jù)庫(kù)插入數(shù)據(jù) queryRunner.update(sql, new Object[]{id, name, gender, birthday, cellphone, email, preference, type, description}); //插入記錄成功! } catch (SQLException e) { //如果出現(xiàn)了異常,就拋出Dao異常吧(自定義的異常) e.printStackTrace(); throw new DaoException("添加用戶(hù)出錯(cuò)了!"); } }測(cè)試增加用戶(hù)
寫(xiě)完一個(gè)功能,不要急著去寫(xiě)其他的功能,先測(cè)試一下!
@Test public void add() { //為了測(cè)試的方便,直接使用構(gòu)造函數(shù)了! Customer customer = new Customer("1", "zhongfucheng", "男", new Date(), "1234", "aa@sina.com", "打代碼", "高貴的用戶(hù)", "我是個(gè)好人"); CustomerDao customerDao = new CustomerDao(); customerDao.addCustomer(customer); }
好的,沒(méi)有報(bào)錯(cuò)!再看看數(shù)據(jù)庫(kù)-----------只要是中文的數(shù)據(jù),都亂碼了!
解決的辦法,看我另外一篇博文:https://zhongfucheng.bitcron....
查詢(xún)用戶(hù)將所有的客戶(hù)查詢(xún)出來(lái)就行了!
//得到所有的用戶(hù) public List測(cè)試查詢(xún)用戶(hù)getAll() { QueryRunner queryRunner = new QueryRunner(Utils2DB.getDataSource()); String sql = "SELECT * FROM customer"; try { List customers = (List ) queryRunner.query(sql, new BeanListHandler(Customer.class)); //如果集合大于個(gè)數(shù)大于0,就返回集合,不大于0,就返回null return customers.size() > 0 ? customers : null; } catch (SQLException e) { e.printStackTrace(); throw new DaoException("獲取所有的用戶(hù)出錯(cuò)了!"); } }
@Test public void find() { CustomerDao customerDao = new CustomerDao(); List修改用戶(hù)信息customers = customerDao.getAll(); for (Customer customer : customers) { System.out.println(customer.getName()); } }
修改用戶(hù)信息首先要知道用戶(hù)的信息,在web端,只有id能唯一標(biāo)識(shí)用戶(hù),我們需要通過(guò)id,獲取用戶(hù)全部信息(也就是Customer對(duì)象)
public Customer find(String id) { QueryRunner queryRunner = new QueryRunner(Utils2DB.getDataSource()); String sql = "SELECT * FROM customer WHERE id = ?"; try { Customer customer = (Customer) queryRunner.query(sql, new BeanHandler(Customer.class), new Object[]{id}); return customer; } catch (SQLException e) { e.printStackTrace(); throw new DaoException("查找用戶(hù)失敗了"); } }
修改用戶(hù)都是外邊傳遞個(gè)對(duì)象進(jìn)來(lái),Dao層取出對(duì)象的數(shù)據(jù),從而對(duì)數(shù)據(jù)庫(kù)的數(shù)據(jù)進(jìn)行修改!
public void update(Customer customer) { QueryRunner queryRunner = new QueryRunner(Utils2DB.getDataSource()); String sql = "UPDATE customer set name=?,gender=?,birthday=?,cellphone=?,email=?,preference=?,type=?,description=? WHERE id = ?"; try { queryRunner.update(sql, new Object[]{customer.getName(), customer.getGender(), customer.getBirthday(),customer.getCellphone(), customer.getEmail(), customer.getPreference(), customer.getType(), customer.getDescription(), customer.getId()}); } catch (SQLException e) { e.printStackTrace(); throw new DaoException("更新失敗"); } }測(cè)試修改用戶(hù)
@Test public void update() { CustomerDao customerDao = new CustomerDao(); //我們已經(jīng)知道了某id,通過(guò)id獲取得到用戶(hù)信息(Customer) String id = "043f7cce-c6f1-4155-b688-ba386cae1636"; Customer customer = customerDao.find(id); //修改用戶(hù)信息 customer.setName("看完博客要點(diǎn)贊"); customerDao.update(customer); }
原來(lái)該用戶(hù)的名字是d
測(cè)試完之后:
刪除用戶(hù)通過(guò)外界傳遞進(jìn)來(lái)的id,就可以刪除數(shù)據(jù)庫(kù)表中的記錄了
public void delete(String id) { QueryRunner queryRunner = new QueryRunner(Utils2DB.getDataSource()); String sql = "DELETE from customer WHERE id = ?"; try { queryRunner.update(sql, new Object[]{id}); } catch (SQLException e) { e.printStackTrace(); throw new DaoException("刪除用戶(hù)失敗了"); } }測(cè)試刪除用戶(hù)
@Test public void delete() { CustomerDao customerDao = new CustomerDao(); //我們已經(jīng)知道了某id,通過(guò)id刪除數(shù)據(jù)庫(kù)中的記錄 String id = "043f7cce-c6f1-4155-b688-ba386cae1636"; customerDao.delete(id); }
數(shù)據(jù)庫(kù)已經(jīng)查詢(xún)不到id為043f7cce-c6f1-4155-b688-ba386cae1636的記錄了!
開(kāi)發(fā)servicepublic class BusinessService { CustomerDao customerDao = new CustomerDao(); public List開(kāi)發(fā)web 的增加和查詢(xún) 提供UI,增加客戶(hù)的ServletgetAll() { return customerDao.getAll(); } public void addCustomer(Customer customer) { customerDao.addCustomer(customer); } public void deleteCustomer(String id) { customerDao.delete(id); } public void updateCustomer(Customer customer) { customerDao.update(customer); } public Customer findCustomer(String id) { return customerDao.find(id); } }
//直接跳轉(zhuǎn)到顯示增加用戶(hù)頁(yè)面的jsp request.getRequestDispatcher("/WEB-INF/addCustomer.jsp").forward(request, response);開(kāi)發(fā)顯示添加客戶(hù)頁(yè)面
效果是這樣子的
我們發(fā)現(xiàn),在日期的下拉框中,只有一個(gè)數(shù)據(jù)(因?yàn)槲覀冊(cè)趘alue中只寫(xiě)了一個(gè)數(shù)據(jù))
要想在下拉框中可以選擇很多的數(shù)據(jù),那么value的值就不能單單只有一個(gè)。當(dāng)然了,也不可能在JSP頁(yè)面中寫(xiě)下面的代碼
我們用javaScript生成下拉框的數(shù)據(jù)就行了!!
獲取年份!
function makeYear() { //得到下拉框的控件 var year = document.getElementById("year"); //要想下拉框有更多的數(shù)據(jù),就需要有更多的option控件 //js獲取得到年份是getFullYear(),單單的getYear()只是獲取兩位數(shù) for (var i=1901; i<= new Date().getFullYear(); i++) { //生成option控件 var option = document.createElement("option"); //option控件的值和文本內(nèi)容為循環(huán)生成的年分! option.value = i; option.innerText = i; //將生成option控件綁定到select控件上 year.appendChild(option); } }
獲取月份和日也類(lèi)似
function makeMonth() { var month = document.getElementById("month"); for (var i = 2; i <= 12; i++) { var option = document.createElement("option"); if (i < 10) { option.value = "0" + i; option.innerText = "0" + i; } else { option.value = i; option.innerText = i; } month.appendChild(option); } } function makeDay() { var day = document.getElementById("day"); for(var i=2;i<=12;i++) { var option = document.createElement("option"); if(i<10) { option.value = "0" + i; option.innerText = "0" + i; }else{ option.value = i; option.innerText = i; } day.appendChild(option); } }
在JSP頁(yè)面中導(dǎo)入javascript文件
注意:javasrcipt文件不能放在WEB-INF下面!?。?!否則是獲取不到的?。?!
這三個(gè)函數(shù)都是在頁(yè)面加載時(shí)就應(yīng)該被初始化了,所以在body上綁定onload時(shí)間即可!!
function pageInit() { makeYear(); makeMonth(); makeDay(); }
效果:
JavaScript拼湊數(shù)據(jù)表單的數(shù)據(jù)非常多,毫無(wú)疑問(wèn),我們會(huì)使用BeanUtils來(lái)將數(shù)據(jù)封裝到Bean對(duì)象中!
對(duì)于表單的數(shù)據(jù),還是有些雜亂的。表單中日期的年月日是分開(kāi)的,我們要么在客戶(hù)端將年月日的數(shù)據(jù)拼湊起來(lái),要么在服務(wù)器端將年月日拼湊起來(lái)!同理,客戶(hù)的喜好可能不單單有一個(gè),但在Customer對(duì)象中,喜好單單用一個(gè)String類(lèi)型來(lái)表示的。我們也要把客戶(hù)的喜好拼湊起來(lái)。
顯然,在客戶(hù)端用javaScript做拼湊是非常方便的!
function makeBirthday() { //獲取下拉框的數(shù)據(jù),把數(shù)據(jù)拼湊成日期字符串 var year = document.getElementById("year"); var month = document.getElementById("month"); var day = document.getElementById("day"); var birthday = year + "-" + month + "-" + day; //想要將拼湊完的字符串提交給服務(wù)器,用隱藏域就行了 var input = document.createElement("input"); input.type = "hidden"; input.value = birthday; input.name = "birthday"; //將隱藏域綁定在form下【為了方便,在form中設(shè)置id,id名字為form】 document.getElementById("form").appendChild(input); } function makePreference() { //獲取喜好的控件 var hobbies = document.getElementsByName("hobbies"); //定義變量,記住用戶(hù)選中的選項(xiàng) var preference = ""; //遍歷喜好的控件,看用戶(hù)選上了什么! for (var i = 0; i < hobbies.length; i++) { if (hobbies[i].checked == true) { preference += hobbies[i].value + ","; } } //剛才拼湊的時(shí)候,最后一個(gè)逗號(hào)是多余的,我們要把它去掉 preference = preference.substr(0, preference.length - 1); //也是用隱藏域?qū)?shù)據(jù)帶過(guò)去給服務(wù)器 var input = document.createElement("input"); input.type = "hidden"; input.value = preference; input.name = "preference"; //將隱藏域綁定到form表單上 document.getElementById("form").appendChild(input); }
當(dāng)表單提交的時(shí)候,觸發(fā)上面兩個(gè)函數(shù)就行了!所以在form表單上綁定onsumit事件!
function makeForm() { makeBirthday(); makePreference(); return true; }
效果:
處理修改表單數(shù)據(jù)的Servlet//將數(shù)據(jù)封裝到Bean中 Customer customer = WebUtils.request2Bean(request, Customer.class); //將id封裝到Customer對(duì)象中?。?!不要忘了id?。?!在表單中獲取到的數(shù)據(jù)是沒(méi)有id的?。。。?!記得?。。?! customer.setId(request.getParameter("id")); //調(diào)用Service層的方法,實(shí)現(xiàn)修改 BusinessService businessService = new BusinessService(); businessService.updateCustomer(customer); //修改成功就跳回查看客戶(hù)界面 request.getRequestDispatcher("/LookCustomer").forward(request, response);
效果:
總結(jié)在dao層中,我們有添加客戶(hù)、通過(guò)id查找用戶(hù)、刪除用戶(hù)、修改用戶(hù)信息的方法。
日期我們一般用下拉框來(lái)給用戶(hù)選取,要想下拉框的信息有足夠多的數(shù)據(jù),我們需要用到JavaScript【DOM編程動(dòng)態(tài)增加和修改數(shù)據(jù)】
javasrcipt文件不能放在WEB-INF目錄下面
日期的數(shù)據(jù)通過(guò)下拉框選取,年、月、日是分散的,我們需要把他們拼接,于是我們也用JavaScript來(lái)拼接【減低服務(wù)器端的壓力】
開(kāi)發(fā)工具方法request2Bean,主要用到了BeanUtils框架,這樣就不用在Servlet一個(gè)一個(gè)封裝了。
在JSP判斷集合是否有元素時(shí),我們可以用EL表達(dá)式${empty(集合)}。
如果記錄數(shù)有很多,我們應(yīng)該使用分頁(yè)技術(shù),一般地,我們使用Page類(lèi)來(lái)封裝分頁(yè)的數(shù)據(jù)
要使用分頁(yè)技術(shù),就必須在數(shù)據(jù)庫(kù)用查詢(xún)總記錄數(shù),通過(guò)總記錄數(shù),就可以算出總頁(yè)數(shù)了【每頁(yè)顯示多少條記錄由我們說(shuō)了算】
在dao層還要編寫(xiě)獲取具體的分頁(yè)數(shù)據(jù),從哪里開(kāi)始,哪里結(jié)束,返回一個(gè)List集合,再把List集合封裝到Page對(duì)象上
由于獲取分頁(yè)數(shù)據(jù)需要當(dāng)前的頁(yè)數(shù)是多少,(所以在service中要判斷當(dāng)前頁(yè)數(shù)是否存在,如果不存在,那么就設(shè)置為1)【更新,我認(rèn)為在Controller判斷會(huì)好一點(diǎn)】
分頁(yè)中,我們還支持上一頁(yè)和下一頁(yè)的功能,如果頁(yè)數(shù)大于1,才顯示上一頁(yè),如果頁(yè)數(shù)小于1,才顯示下一頁(yè)。
給出下拉框進(jìn)行頁(yè)數(shù)跳轉(zhuǎn),使用JavaScript事件機(jī)制,獲取頁(yè)數(shù),再提交給Servlet處理即可
我們還要控制頁(yè)數(shù)的顯示,因?yàn)椴豢赡苡?00頁(yè),我們就顯示100頁(yè),這樣是不可能的。在Page類(lèi)中維護(hù)兩個(gè)變量,startPage,endPage。我們規(guī)定每次只能顯示10頁(yè)數(shù)據(jù),如果第一次訪問(wèn)就顯示1-10頁(yè)。如果當(dāng)前頁(yè)數(shù)大于10,那么就顯示6-15頁(yè)。如果角標(biāo)越界了,那么就顯示前10頁(yè)或者后10頁(yè)
我們把顯示分頁(yè)的頁(yè)面封裝成多帶帶的jsp,使用的Servlet連接也可以用url變量來(lái)維護(hù)。
前臺(tái)數(shù)據(jù)做拼接,最終都是把拼接好的數(shù)據(jù)用一個(gè)隱藏域封裝起來(lái),隨后讓form表單一起提交
如果文章有錯(cuò)的地方歡迎指正,大家互相交流。習(xí)慣在微信看技術(shù)文章的同學(xué),想要獲取更多的Java資源的同學(xué),可以關(guān)注微信公眾號(hào):Java3y
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/68586.html
摘要:中主要是使用語(yǔ)言。將的動(dòng)態(tài)功能和標(biāo)準(zhǔn)的安全性引入大型網(wǎng)絡(luò)應(yīng)用的開(kāi)發(fā)集成部署和管理之中。提供了一個(gè)圖形界面的管理工具,稱(chēng)為信息服務(wù)管理器,可用于監(jiān)視配置和控制服務(wù)。 一、基本概念 1.1、WEB開(kāi)發(fā)的相關(guān)知識(shí) WEB,在英語(yǔ)中web即表示網(wǎng)頁(yè)的意思,它用于表示Internet主機(jī)上供外界訪問(wèn)的資源?! nternet上供外界訪問(wèn)的Web資源分為: 靜態(tài)web資源(如html 頁(yè)面...
摘要:當(dāng)后繼請(qǐng)求相同的頁(yè)面時(shí),容器加載之前生成的類(lèi),并且通知去執(zhí)行已經(jīng)存在的字節(jié)碼,從而省去了轉(zhuǎn)換的過(guò)程,這也是第一次執(zhí)行頁(yè)面時(shí)間較長(zhǎng)的原因。 以往學(xué)習(xí)的時(shí)候大多是看完書(shū)或者看完視頻,動(dòng)手實(shí)踐一下就OK了。然而過(guò)了一段時(shí)間我發(fā)現(xiàn)東西都忘差不多了,需要復(fù)習(xí)才能重新掌握?,F(xiàn)在開(kāi)始學(xué)習(xí)JavaWeb了,我將在這里記錄自己的學(xué)習(xí)的一點(diǎn)一滴,不僅便于自己以后回顧知識(shí)點(diǎn),也希望能對(duì)JavaWeb初學(xué)者有...
摘要:系列文章請(qǐng)查看超詳細(xì)的面試題總結(jié)一之基礎(chǔ)知識(shí)篇超詳細(xì)的面試題總結(jié)二之基礎(chǔ)知識(shí)篇超詳細(xì)的面試題總結(jié)三之集合篇常見(jiàn)問(wèn)題下面的都是自己之前在學(xué)習(xí)的時(shí)候總結(jié)的,對(duì)于鞏固的基礎(chǔ)知識(shí)應(yīng)該有很大幫助。注意多線程的并發(fā)的讀寫(xiě)類(lèi)屬性會(huì)導(dǎo)致數(shù)據(jù)不同步。 系列文章請(qǐng)查看: 超詳細(xì)的Java面試題總結(jié)(一)之Java基礎(chǔ)知識(shí)篇 超詳細(xì)的Java面試題總結(jié)(二)之Java基礎(chǔ)知識(shí)篇 超詳細(xì)的Java面試題總結(jié)(...
摘要:方法的參數(shù)不但可以使相對(duì)于上下文根的路徑,而且可以是相對(duì)于當(dāng)前的路徑。如和都是合法的路徑。 轉(zhuǎn)發(fā)與重定向區(qū)別是什么 在調(diào)用方法上 轉(zhuǎn)發(fā) 調(diào)用 HttpServletRequest 對(duì)象的方法 request.getRequestDispatcher(test.jsp).forward(req, resp); 重定向 調(diào)用 HttpServletResponse 對(duì)象的方法 res...
摘要:實(shí)現(xiàn)不同語(yǔ)言間進(jìn)行協(xié)助開(kāi)發(fā),可以使用通信的方式來(lái)實(shí)現(xiàn),這次實(shí)現(xiàn)和的協(xié)助開(kāi)發(fā),是項(xiàng)目主要服務(wù)端,由于要處理一些系統(tǒng)底層的事務(wù),所以要用提供一個(gè)輔助服務(wù),為主服務(wù)端處理相關(guān)事務(wù),以下是搭建流程和服務(wù)間通信原理。 實(shí)現(xiàn)不同語(yǔ)言間進(jìn)行協(xié)助開(kāi)發(fā),可以使用通信的方式來(lái)實(shí)現(xiàn),這次實(shí)現(xiàn)Nodejs和JavaWeb的協(xié)助開(kāi)發(fā),Nodejs是項(xiàng)目主要服務(wù)端,由于要處理一些系統(tǒng)底層的事務(wù),所以要用JavaW...
閱讀 2553·2021-11-22 15:35
閱讀 3826·2021-11-04 16:14
閱讀 2771·2021-10-20 13:47
閱讀 2585·2021-10-13 09:49
閱讀 2136·2019-08-30 14:09
閱讀 2498·2019-08-26 13:49
閱讀 948·2019-08-26 10:45
閱讀 2839·2019-08-23 17:54