一說到java web 應用的開發,很多人肯定想到的是用spring mvc 、Struts2 這些熱門框架去開發,簡單高效,只要配置好框架,剩下的工作就是體力活了。
但是很多人用慣了框架,一但開發中遇到問題,就束手無策,究其原理是根本不理解java web 最基礎、最核心的東西。其實那些所謂的框架,其本質是在servlet和jdbc的
基礎上擴展功能,封裝常用的函數、以xml配置的方式提供給開發者使用。
言歸正傳,下面就介紹servlet和jdbc的使用:
在web2.5以前,servlet都是在web.xml中配置使用的,相信這個大家都很熟悉,如下:
<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中配置那么一大堆了。
要開發java web 應用 ,首先你得搞清楚后台要做哪些事,也就是大家常說的分層。
最基本的分層就是:控制層+數據訪問層
擴展一點的話就是:控制層(servlet)+服務層(業務邏輯)+數據訪問層(dao)+模型(java bean)

知道了這些,我們就開始一層一層的去解決,首先從數據訪問層開始。
一.數據訪問層
顧名思義,就是要操作數據庫,既然要操作數據庫,我們就要寫個類去做這個事,封裝常用的方法,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,正常運行。
