一说到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,正常运行。