MySQL---数据库从入门走向大神系列(十二)-构建MVC项目
生活随笔
收集整理的這篇文章主要介紹了
MySQL---数据库从入门走向大神系列(十二)-构建MVC项目
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
這個是對前面技術的一個小總結吧,用到的大概技術有:
MVC框架,加注解,Struts框架的思想,動態代理,線程管理對象ThreadLocal,Connection對象池,Properties文件讀取,EL表達式,JSTL,JavaBean,Java訪問MySQL數據庫,增刪改查…
其實做出來界面挺簡單:
完整的項目鏈接:
https://github.com/chenhaoxiang/Java/tree/master/myMvcWeb2
這里只寫出一些核心的類的代碼:
Book.java:
package cn.hncu.domain;/* alter table book add constraint fk_book foreign key (studid) references stud(id); 設置studid為book的外鍵(fk_book)為stud的主鍵id*/public class Book {private Integer id;private String namem;private Double price;// ※一對多關系中的多方(外鍵字段): 在寫JavaBean時,要包含對方(一方)的整個值對象類型的變量private Stud stud;//設置書的主人public Book() {super();}public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getNamem() {return namem;}public void setNamem(String namem) {this.namem = namem;}public Double getPrice() {return price;}public void setPrice(Double price) {this.price = price;}public Stud getStud() {return stud;}public void setStud(Stud stud) {this.stud = stud;}@Overridepublic int hashCode() {final int prime = 31;int result = 1;result = prime * result + ((id == null) ? 0 : id.hashCode());return result;}@Overridepublic boolean equals(Object obj) {if (this == obj)return true;if (obj == null)return false;if (getClass() != obj.getClass())return false;Book other = (Book) obj;if (id == null) {if (other.id != null)return false;} else if (!id.equals(other.id))return false;return true;}}Stud.java
package cn.hncu.domain;import java.util.ArrayList; import java.util.List;public class Stud {private String id;private String name;//※一對多中的一方: 添加一個集合(用set也行)以表示該關系private List<Book > books = new ArrayList<Book>();public Stud() {super();}public String getId() {return id;}public void setId(String id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public List<Book> getBooks() {return books;}public void setBooks(List<Book> books) {this.books = books;}@Overridepublic int hashCode() {final int prime = 31;int result = 1;result = prime * result + ((id == null) ? 0 : id.hashCode());return result;}@Overridepublic boolean equals(Object obj) {if (this == obj)return true;if (obj == null)return false;if (getClass() != obj.getClass())return false;Stud other = (Stud) obj;if (id == null) {if (other.id != null)return false;} else if (!id.equals(other.id))return false;return true;}//注意,如果要添加toString()方法,注意一對多關系中的信息輸出嵌套}TxProxy.java:
package cn.hncu.pubs.tx;import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.sql.Connection;import cn.hncu.pubs.ConnsUtil;public class TxProxy implements InvocationHandler{private Object srcObj;public TxProxy(Object srcObj) {this.srcObj = srcObj;}/* 版本1public static Object getProxy(Object srcObj){Object proxiedObj = Proxy.newProxyInstance(TxProxy.class.getClassLoader(),srcObj.getClass().getInterfaces(),new TxProxy(srcObj));return proxiedObj;}*//* 版本2public static<T> T getProxy(Object srcObj, Class<T> cls){Object proxiedObj = Proxy.newProxyInstance(TxProxy.class.getClassLoader(),srcObj.getClass().getInterfaces(),new TxProxy(srcObj));return (T)proxiedObj;}*//* 版本3public static<T> T getProxy(Class<T> cls){Object srcObj = null;try {srcObj = cls.newInstance();} catch (InstantiationException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();}Object proxiedObj = Proxy.newProxyInstance(TxProxy.class.getClassLoader(),srcObj.getClass().getInterfaces(),new TxProxy(srcObj));return (T)proxiedObj;}*///版本4public static<T> T getProxy(T srcObj){Object proxiedObj = Proxy.newProxyInstance(TxProxy.class.getClassLoader(),srcObj.getClass().getInterfaces(),new TxProxy(srcObj));return (T)proxiedObj;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args)throws Throwable {//判斷method方法是不是添加了注解if(method.isAnnotationPresent(Transaction.class)){Connection con=null;Object returnValue =null;try {con = ConnsUtil.getConnection();con.setAutoCommit(false);System.out.println("在動態代理中開啟一個事務....");returnValue = method.invoke(srcObj, args);con.commit();System.out.println("在動態代理中提交一個事務....");} catch (Exception e) {con.rollback();System.out.println("在動態代理中回滾一個事務....");}finally{if(con!=null){try {con.setAutoCommit(true);con.close();} catch (Exception e) {throw new RuntimeException("數據庫連接關閉失敗", e);}}}return returnValue;}else{//沒有添加注解,直接放行return method.invoke(srcObj, args);}} }Transaction.java:注解
package cn.hncu.pubs.tx;import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;@Retention(RetentionPolicy.RUNTIME) @Target(value=ElementType.METHOD) public @interface Transaction { }BaseServlet.java:
package cn.hncu.pubs;import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method;import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse;/*** @author 陳浩翔** 2016-8-15*/ public abstract class BaseServlet extends HttpServlet{@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp)throws ServletException, IOException {doPost(req, resp);}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp)throws ServletException, IOException {req.setCharacterEncoding("utf-8");resp.setCharacterEncoding("utf-8");String cmd = req.getParameter("cmd");if(cmd==null){cmd="execute";}try {System.out.println("this:"+this);//下面這句不能訪問私有方法//Method m = this.getClass().getMethod(cmd, HttpServletRequest.class,HttpServletResponse.class );//如果要用類反射實現訪問類的私有方法,則需要這2步,這樣子類的方法就不用設置成public了。//1獲得私有方法 Method m = this.getClass().getDeclaredMethod(cmd, HttpServletRequest.class,HttpServletResponse.class );//2設置私有方法可以被訪問 m.setAccessible(true);m.invoke(this, req,resp);//這里的this是子類對象,誰調用這里的,這個this就是誰 //下面這幾句是給大家啟發Struts框架的思想 // String str =(String) m.invoke(this, request,response); // String resPage = "";//從配置struts.xml文件中讀取str所對應的結果頁面的地址 // request.getRequestDispatcher(resPage).forward(request,response);} catch (NoSuchMethodException e) {e.printStackTrace();} catch (SecurityException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();} catch (IllegalArgumentException e) {e.printStackTrace();} catch (InvocationTargetException e) {e.printStackTrace();}}//如果沒有參數cmd為null,轉向的界面,由子類自己實現public abstract void execute(HttpServletRequest request, HttpServletResponse response); }ConnsUtil.java
package cn.hncu.pubs;import java.io.IOException; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; import java.util.Properties;public class ConnsUtil {private static List<Connection> pool = new ArrayList<Connection>();private static final int NUM = 3;private static ThreadLocal<Connection> t = new ThreadLocal<Connection>();static{try {//讀取配置文件Properties p = new Properties();p.load(ConnsUtil.class.getClassLoader().getResourceAsStream("jdbc.properties"));String driver = p.getProperty("driver");String url = p.getProperty("url");String user = p.getProperty("username");String password = p.getProperty("password");Class.forName(driver);for(int i=0;i<NUM;i++){final Connection conn = DriverManager.getConnection(url, user, password);//System.out.println(conn.getClass().getClassLoader());//AppClassLoader//使用動態代理,代理conn對象,實現對close方法的攔截Object obj = Proxy.newProxyInstance(ConnsUtil.class.getClassLoader(),new Class[]{Connection.class},new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args)throws Throwable {//攔截close方法if(method.getName().equalsIgnoreCase("close") &&(args==null||args.length==0) ){pool.add((Connection)proxy);//proxy為代理后的對象t.set(null);//把存儲在本地線程管理類中的當前線程對應的對象設為空return null;}//conn為被代理的對象return method.invoke(conn, args);}});pool.add( (Connection)obj);//把代理后的conn對象即obj加入池中}} catch (IOException e) {e.printStackTrace();} catch (ClassNotFoundException e) {e.printStackTrace();} catch (SQLException e) {e.printStackTrace();}}public static synchronized Connection getConnection() throws InterruptedException{//從本地線程管理對象t中拿Connection con = t.get();if(con==null){if(pool.size()<=0){Thread.sleep(50);return getConnection();}con=pool.remove(0);//放入到t中t.set(con);}return con;} }StudServlet.java:
package cn.hncu.stud;import java.io.IOException; import java.sql.SQLException; import java.util.List; import java.util.Map;import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse;import cn.hncu.domain.Book; import cn.hncu.domain.Stud; import cn.hncu.pubs.BaseServlet; import cn.hncu.pubs.tx.TxProxy; import cn.hncu.stud.service.IStudService; import cn.hncu.stud.service.StudService;public class StudServlet extends BaseServlet {//版本1//private IStudService service = (IStudService) TxProxy.getProxy(new StudService());//版本2//private IStudService service = TxProxy.getProxy(new StudService(),IStudService.class);//版本3//private IStudService service = TxProxy.getProxy(StudService.class);//用實現類的class//版本4private IStudService service = TxProxy.getProxy(new StudService());//用實現類的classprivate void save(HttpServletRequest request, HttpServletResponse response) throws InterruptedException, ServletException, IOException {//收集并封裝studString name = request.getParameter("name");if(name==null||name.trim().length()<=0){response.sendRedirect("index.jsp");//重定向return ;}Stud stud = new Stud();stud.setName(name);//收集并封裝所有bookString bookNames[] = request.getParameterValues("bookname");//獲取多個值String prices[] = request.getParameterValues("price");if(bookNames!=null){for(int i=0;i<bookNames.length;i++){Book book = new Book();if(bookNames[i]==null || bookNames[i].trim().length()<=0){continue;}book.setNamem(bookNames[i]);if(prices[i]!=null && prices[i].trim().length()!=0 ){Double price=0.0;try {price = Double.parseDouble(prices[i]);} catch (NumberFormatException e) {price=0.0;}book.setPrice(price);}book.setStud(stud);//繼續封裝stud----為stud中的books屬性賦值--一方中的集合stud.getBooks().add(book);}}try {service.save(stud);} catch (SQLException e) {e.printStackTrace();}}private void query(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {List<Map<String, String>> studs = service.query();request.setAttribute("studs", studs);request.getRequestDispatcher("/jsps/show.jsp").forward(request, response);}@Overridepublic void execute(HttpServletRequest request, HttpServletResponse response) {System.out.println("調用默認業務處理方法....");} }BookDAOJdbc.java:
package cn.hncu.stud.dao;import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; import java.util.List;import cn.hncu.domain.Book; import cn.hncu.pubs.ConnsUtil;public class BookDAOJdbc implements IBookDAO {@Overridepublic void save(List<Book> books) throws InterruptedException, SQLException {Connection con = ConnsUtil.getConnection();String sql = "insert into book(name,price,studid) values(?,?,?)";PreparedStatement pst = con.prepareStatement(sql);for(Book book:books){pst.setString(1, book.getNamem());pst.setDouble(2, book.getPrice());//stud中設置了uuid這里才能設置成功pst.setString(3, book.getStud().getId());pst.addBatch();}pst.executeBatch();} }StudDAOJdbc.java
package cn.hncu.stud.dao;import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.UUID;import cn.hncu.domain.Stud; import cn.hncu.pubs.ConnsUtil;public class StudDAOJdbc implements StudDAO {@Overridepublic List<Map<String, String>> query() {List<Map<String, String>> list = new ArrayList<Map<String,String>>();Connection con = null;try {con = ConnsUtil.getConnection();String sql="select * from stud";Statement st = con.createStatement();ResultSet rs = st.executeQuery(sql);while(rs.next()){Map<String, String> map = new HashMap<String, String>();map.put("id", rs.getString("id"));map.put("name", rs.getString("name"));//一個map就是一條記錄(數據行)list.add(map);}} catch (InterruptedException e) {e.printStackTrace();} catch (SQLException e) {e.printStackTrace();}finally{if(con!=null){try {con.close();} catch (SQLException e) {throw new RuntimeException("數據庫連接關閉失敗", e);}}}return list;}@Overridepublic void save(Stud stud) throws InterruptedException, SQLException {Connection con = ConnsUtil.getConnection();String sql = "insert into stud values(?,?)";PreparedStatement pst = con.prepareStatement(sql);String uuid = UUID.randomUUID().toString().replaceAll("-","");pst.setString(1, uuid);pst.setString(2, stud.getName());pst.executeUpdate();//在這里為book補外鍵字段的值stud.setId(uuid);//這一句執行在前,這樣在BookDAOJdbc中會調用book.getStud().getId()就可以拿到該id值了}}IStudService.java:
package cn.hncu.stud.service;import java.sql.SQLException; import java.util.List; import java.util.Map;import cn.hncu.domain.Stud; import cn.hncu.pubs.tx.Transaction;public interface IStudService {public abstract List< Map<String, String> > query();@Transaction//注意,注解必須加在接口上,加在實現類上是無效的!,因為我們的動態代理是面向接口的public abstract void save(Stud stud) throws InterruptedException, SQLException; }StudService.java:
package cn.hncu.stud.service;import java.sql.SQLException; import java.util.List; import java.util.Map;import cn.hncu.domain.Stud; import cn.hncu.stud.dao.BookDAOJdbc; import cn.hncu.stud.dao.IBookDAO; import cn.hncu.stud.dao.StudDAO; import cn.hncu.stud.dao.StudDAOJdbc;public class StudService implements IStudService {//注入private StudDAO studDao = new StudDAOJdbc();private IBookDAO bookDao = new BookDAOJdbc();@Overridepublic List<Map<String, String>> query() {return studDao.query();}//※利用動態代理在背后幫忙實現事務功能,注意:該方法內部的異常必須拋出來給動態代理捕捉處理@Overridepublic void save(Stud stud) throws InterruptedException, SQLException {studDao.save(stud);//在這個內部為stud對象補id--先執行bookDao.save(stud.getBooks());//通過book拿到stud對象,進而拿到studid,完成外鍵字段的賦值}}jdbc.properties:
##MySQL driver=com.mysql.jdbc.Driver url=jdbc:mysql://127.0.0.1:3306/hncu?useUnicode=true&characterEncoding=utf-8 username=root password=1234##Oracle #driver=oracle.jdbc.driver.OracleDriver #url=jdbc:oracle:thin:@localhost:1521:orcl #username=scott #password=tigerindex.jsp:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%><%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html><head><title>mvc示例演示</title></head><body><br/><a href='<c:url value="/StudServlet?cmd=query"></c:url>'>學生信息查詢</a><hr/><form action="<c:url value='/StudServlet?cmd=save'/>" method="post">姓名:<input type="text" name="name" /><br/><fieldset style="width: 200px"><legend>圖書1</legend>書名:<input type="text" name="bookname" /><br/><br/>價格:<input type="text" name="price" /></fieldset><fieldset style="width: 200px"><legend>圖書2</legend>書名:<input type="text" name="bookname" /><br/><br/>價格:<input type="text" name="price" /></fieldset><br/><input type="submit" value="保存"></form><br/><a href="<c:url value='/StudServlet'/>">默認請求</a></body> </html>show.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html><head><title>學生信息查詢</title><style type="text/css">table,tr,td,th{border: 1px;border-style: solid;margin: auto;}</style></head><body style="text-align: center;"><h2>學生信息</h2><table><tr> <th>ID</th> <th>姓名</th></tr><c:forEach items="${studs}" var="stud"><tr> <td>${stud.id }</td> <td>${stud.name }</td> </tr></c:forEach></table></body> </html>web.xml
<servlet><servlet-name>StudServlet</servlet-name><servlet-class>cn.hncu.stud.StudServlet</servlet-class></servlet><servlet-mapping><servlet-name>StudServlet</servlet-name><url-pattern>/StudServlet</url-pattern></servlet-mapping>嗯,我就不做過多的解釋啦,這個只是自己對以前知識點的一個小總結吧。
轉載請附上原文博客鏈接:
http://blog.csdn.net/qq_26525215
總結
以上是生活随笔為你收集整理的MySQL---数据库从入门走向大神系列(十二)-构建MVC项目的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Nginx + CGI/FastCGI
- 下一篇: builds error