一說到java web 應用的開發,不少人確定想到的是用spring mvc 、Struts2 這些熱門框架去開發,簡單高效,只要配置好框架,剩下的工做就是體力活了。java
可是不少人用慣了框架,一但開發中遇到問題,就一籌莫展,究其原理是根本不理解java web 最基礎、最核心的東西。其實那些所謂的框架,其本質是在servlet和jdbc的mysql
基礎上擴展功能,封裝經常使用的函數、以xml配置的方式提供給開發者使用。web
言歸正傳,下面就介紹servlet和jdbc的使用:spring
在web2.5之前,servlet都是在web.xml中配置使用的,相信這個你們都很熟悉,以下:sql
<servlet> <servlet-name>testServlet</servlet-name> <servlet-class>com.qthh.web.servlet.TestServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>testServlet</servlet-name> <url-pattern>/test/list</url-pattern> </servlet-mapping>
web3.0後,servlet的使用更加方便,支持註解了,以下:數據庫
@WebServlet("/test/list") public class TestServlet extends HttpServlet {
這樣就不用再web.xml中配置那麼一大堆了。json
要開發java web 應用 ,首先你得搞清楚後臺要作哪些事,也就是你們常說的分層。tomcat
最基本的分層就是:控制層+數據訪問層 安全
擴展一點的話就是:控制層(servlet)+服務層(業務邏輯)+數據訪問層(dao)+模型(java bean)mvc
知道了這些,咱們就開始一層一層的去解決,首先從數據訪問層開始。
一.數據訪問層
顧名思義,就是要操做數據庫,既然要操做數據庫,咱們就要寫個類去作這個事,封裝經常使用的方法,JDBC爲咱們提供了操做數據庫的方法,咱們須要瞭解JDBC的使用方法
步驟以下:
1.加載驅動:咱們熟知的Class.forName
2.驅動管理器創建鏈接:DriverManager.getConnection
3.建立Statement(或PreparedStatement)對象
4.執行操做:query或者update
爲了方便你們,直接貼出封裝部分代碼:
public class DBHelper { private static final String DRIVENAME = "com.mysql.jdbc.Driver"; private static final String URL = "jdbc:mysql://192.168.1.200:3306/web"; private static final String USER = "root"; private static final String PASSWORD = "123456"; private Connection conn = null; private Statement st = null; private PreparedStatement ppst = null; private ResultSet rs = null; /** * 加載驅動 */ static{ try { Class.forName(DRIVENAME).newInstance(); } catch (Exception e) { System.out.println("驅動加載失敗:"+e.getMessage()); } } /** * 鏈接數據庫 * @return */ public Connection getConn(){ try { conn = DriverManager.getConnection(URL,USER,PASSWORD); } catch (SQLException e) { System.out.println("數據庫鏈接失敗:"+e.getMessage()); } return conn; } /** * 獲取結果集(無參) * @param sql * @return */ private ResultSet getRs(String sql){ conn = this.getConn(); try { st = conn.createStatement(); rs = st.executeQuery(sql); } catch (SQLException e) { System.out.println("查詢(無參)出錯:"+e.getMessage()); } return rs; } /** * 獲取結果集 * @param sql * @param params * @return */ private ResultSet getRs(String sql,Object[] params){ conn = this.getConn(); try { ppst = conn.prepareStatement(sql); if(params!=null){ for(int i = 0;i<params.length;i++){ ppst.setObject(i+1, params[i]); } } rs = ppst.executeQuery(); } catch (SQLException e) { System.out.println("查詢出錯:"+e.getMessage()); } return rs; } /** * 查詢 * @param sql * @param params * @return */ public List<Object> query(String sql,Object[] params){ List<Object> list = new ArrayList<Object>(); ResultSet rs = null; if(params!=null){ rs = getRs(sql, params); }else{ rs = getRs(sql); } ResultSetMetaData rsmd = null; int columnCount = 0; try { rsmd = rs.getMetaData(); columnCount = rsmd.getColumnCount(); while(rs.next()){ Map<String, Object> map = new HashMap<String, Object>(); for(int i = 1;i<=columnCount;i++){ map.put(rsmd.getColumnLabel(i), rs.getObject(i)); } list.add(map); } } catch (SQLException e) { System.out.println("結果集解析出錯:"+e.getMessage()); } finally { closeConn(); } return list; } /** * 更新(無參) * @param sql */ public int update(String sql){ int affectedLine = 0;//受影響的行數 conn = this.getConn(); try { st = conn.createStatement(); affectedLine = st.executeUpdate(sql); } catch (SQLException e) { System.out.println("更新(無參)失敗:"+e.getMessage()); } finally { closeConn(); } return affectedLine; } /** * 更新 * @param sql * @param params * @return */ public int update(String sql,Object[] params){ int affectedLine = 0;//受影響的行數 conn = this.getConn(); try { ppst = conn.prepareStatement(sql); if(params!=null){ for(int i = 0;i<params.length;i++){ ppst.setObject(i+1, params[i]); } } affectedLine = ppst.executeUpdate(); } catch (SQLException e) { System.out.println("更新失敗:"+e.getMessage()); } finally { closeConn(); } return affectedLine; } private void closeConn(){ if(rs!=null){ try { rs.close(); } catch (SQLException e) { System.out.println(e.getMessage()); } } if(st!=null){ try { st.close(); } catch (SQLException e) { System.out.println(e.getMessage()); } } if(ppst!=null){ try { ppst.close(); } catch (SQLException e) { System.out.println(e.getMessage()); } } if(conn!=null){ try { conn.close(); } catch (SQLException e) { System.out.println(e.getMessage()); } } } }
JDBC封裝好了,接下來,就是在dao層中定義接口,而後去實現接口
public interface TestDao { List<Object> query(String sql,Object[] params); int update(String sql,Object[] params); }
public class TestDaoImpl implements TestDao { @Override public List<Object> query(String sql,Object[] params) { DBHelper db = new DBHelper(); return db.query(sql, params); } @Override public int update(String sql,Object[] params) { DBHelper db = new DBHelper(); return db.update(sql, params); } }
以上就是一個很簡單的dao層示例。實際開發中,會對經常使用的方法進行封裝成baseDao,這裏不作介紹。
二.服務層
服務層也叫業務層,編寫業務邏輯的地方;關聯控制層和dao層,負責從dao層取數據,而後返回給控制層。實現方式和dao層相似,先定義接口,而後去實現接口。
(這裏確定不少人有疑問,爲啥非要定義接口,直接寫個類不就好了麼。固然你這麼作也是能實現功能,可是從設計規範和安全的角度的來說是很差的,之後也不方便維護。)
public interface TestService { List<Object> getTestList();//獲取列表 int insertTest(Object[] params);//插入一條 int modifyTest(Object[] params);//修改 int deleteTest(Object[] params);//刪除 }
public class TestServiceImpl implements TestService { TestDao testDao = new TestDaoImpl(); @Override public List<Object> getTestList() { String sql = "select * from test"; return testDao.query(sql, null); } @Override public int insertTest(Object[] params) { String sql ="insert into test(name) values(?)"; return testDao.update(sql, params); } @Override public int modifyTest(Object[] params) { String sql ="update test set name = ? where id = ?"; return testDao.update(sql, params); } @Override public int deleteTest(Object[] params) { String sql ="delete from test where id = ?"; return testDao.update(sql, params); } }
三.控制層
這一層是咱們最熟悉的地方,建立一個servlet,文章一開始咱們也提到了,至於他的做用,就不用我多說了,直接貼代碼
@WebServlet("/test/list") public class TestServlet extends HttpServlet { private static final long serialVersionUID = 1L; TestService testService = new TestServiceImpl(); protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setCharacterEncoding("UTF-8"); response.setContentType("application/json; charset=utf-8"); List<Object> list = testService.getTestList(); PrintWriter out = null; System.out.println("list:"+list.toString()); try { out = response.getWriter(); out.write(list.toString()); } catch (Exception e) { System.out.println(e.getMessage()); } out.flush(); out.close(); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
由於是例子,因此寫的很簡單。關於servlet如何返回不一樣的數據格式,好比json,將在後面的篇章中介紹。
四. 模型
其實就是一個javabean,用來被填充數據的。若是咱們作了orm(對象關係映射)的話,就沒必要操做數據庫,直接操做這個對象,也就是這裏的模型。
本案例沒用到,就不說了。
麻雀雖小五臟俱全,到這裏,web的整個後臺已經完成了,接下來要作的就是發佈到tomcat上測試一下。
ok,正常運行。