1、写出Cookie的 2、写出Servlet实现页面跳转的方式 3、写出Servlet的生命周期 4、写出Servlet的两种配置方式 5、写出ServletContext的常用方法
1、Cookie的使用 2、Session的使用
1、什么是过滤器 2、过滤器链 3、过滤器的优先级和参数 4、过滤器的典型应用 5、什么是监听器 6、常用的监听器
1、熟悉什么是过滤器 2、掌握过滤器链 3、掌握过滤器的优先级和参数 4、掌握过滤器的典型应用 5、熟悉什么是监听器 6、掌握常用的监听器
首先我们需要知道MVC模式并不是javaweb项目中独有的,MVC是一种软件工程中的一种软件架构模式,把软件系统分为三个基本部分:模型(Model)、视图(View)和控制器(Controller),即为MVC。它是一种软件设计的典范,最早为Trygve Reenskaug提出,为施乐帕罗奥多研究中心(Xerox PARC)的Smalltalk语言发明的一种软件设计模式
虽然MVC并不是Java当中独有的,但是现在几乎所有的B/S的架构都采用了MVC框架模式,但是MVC在B/S架构中并没有完全地实现,其实我们根本不需要掌握未实现的部分。
MVC模式被广泛用于Java的各种框架中,比如Struts2、spring MVC等等都用到了这种思想。
Struts2是基于MVC的轻量级的web应用框架。基于MVC,说明基于Struts2开发的Web应用自然就能实现MVC,也说明Struts2着力于在MVC的各个部分为我们的开发提供相应帮助
JSP Model1是JavaWeb早期的模型,它适合小型Web项目,开发成本低!Model1第一代时期,服务器端只有JSP页面,所有的操作都在JSP页面中,连访问数据库的API也在JSP页面中完成。也就是说,所有的东西都耦合在一起,对后期的维护和扩展极为不利。

JSP Model1第二代有所改进,把业务逻辑的内容放到了JavaBean中,而JSP页面负责显示以及请求调度的工作。虽然第二代比第一代好了些,但还让JSP做了过多的工作,JSP中把视图工作和请求调度(控制器)的工作耦合在一起了。

JSP Model2模式已经可以清晰的看到MVC完整的结构了。
JSP:视图层,用来与用户打交道。负责接收用来的数据,以及显示数据给用户;
Servlet:控制层,负责找到合适的模型对象来处理业务逻辑,转发到合适的视图;
JavaBean:模型层,完成具体的业务工作,例如:开启、转账等。

小结:这就是javaweb经历的三个年代,JSP Model2适合多人合作开发大型的Web项目,各司其职,互不干涉,有利于开发中的分工,有利于组件的重用。但是,Web项目的开发难度加大,同时对开发人员的技术要求也提高了。
通过结合事务和MVC知识,练习一个转账demo
c3p0-0.9.1.2.jar
commons-beanutils-1.8.3.jar
commons-dbutils-1.4.jar
commons-logging-1.1.1.jar
添加c3p0配置文件
c3p0-config.xml
xxxxxxxxxx<c3p0-config> <!-- 默认配置,如果没有指定则使用这个配置 --> <default-config> <property name="driverClass">com.mysql.jdbc.Driver</property> <property name="jdbcUrl">jdbc:mysql://localhost:3306/day16</property> <property name="user">root</property> <property name="password">222</property> <property name="initialPoolSize">10</property> <property name="maxIdleTime">30</property> <property name="maxPoolSize">20</property> <property name="minPoolSize">5</property> <property name="maxStatements">200</property> </default-config> </c3p0-config> x<% page language="java" import="java.util.*" pageEncoding="UTF-8"%><%String path = request.getContextPath();String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";%><html> <head> <base href="<%=basePath%>"> <title>My JSP 'transfer.jsp' starting page</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="styles.css"> --> </head> <body> <form action="${pageContext.request.contextPath }/servlet/AccountServlet" method="post" > 转出方:<input type="text" name="outaccount"/><br/> 转入方:<input type="text" name="intaccount"/><br/> 金额<input type="text" name="money"/><br/> <input type="submit" value="转账"/><br/> </form> </body></html>因为要使用到mvc模式,要对项目代码进行分包
com.itqf.dao
com.itqf.service
com.itqf.controller
com.itqf.utils
DatasoutceUtils工具类,优化获取连接,优化事务操作
xxxxxxxxxxpackage com.itqf.utils;import java.sql.Connection;import java.sql.ResultSet;import java.sql.SQLException;import java.sql.Statement;import javax.sql.DataSource;import com.mchange.v2.c3p0.ComboPooledDataSource;public class DataSourceUtils { private static ComboPooledDataSource ds=new ComboPooledDataSource(); //-- private static ThreadLocal<Connection> tl=new ThreadLocal<>(); /** * 获取数据源 * @return 连接池 */ public static DataSource getDataSource(){ return ds; } /** * 从当前线程上获取连接 * @return 连接 * @throws SQLException */ public static Connection getConnection() throws SQLException{ //-- 从线程获取链接 Connection conn = tl.get(); if(conn==null){ //第一次获取 创建一个连接 和当前的线程绑定 conn=ds.getConnection(); //----绑定 tl.set(conn); } return conn; } /** * ---释放资源 * * @param conn * 连接 * @param st * 语句执行者 * @param rs * 结果集 */ public static void closeResource(Connection conn, Statement st, ResultSet rs) { closeResource(st, rs); closeConn(conn); } public static void closeResource(Statement st, ResultSet rs) { closeResultSet(rs); closeStatement(st); } /** * 释放连接 * * @param conn * 连接 */ public static void closeConn(Connection conn) { if (conn != null) { try { conn.close(); //----和当前的线程解绑 tl.remove(); } catch (SQLException e) { e.printStackTrace(); } conn = null; } } /** * 释放语句执行者 * * @param st * 语句执行者 */ public static void closeStatement(Statement st) { if (st != null) { try { st.close(); } catch (SQLException e) { e.printStackTrace(); } st = null; } } /** * 释放结果集 * * @param rs * 结果集 */ public static void closeResultSet(ResultSet rs) { if (rs != null) { try { rs.close(); } catch (SQLException e) { e.printStackTrace(); } rs = null; } } /** *---- 开启事务 * @throws SQLException */ public static void startTransaction() throws SQLException{ //获取连接//开启事务 getConnection().setAutoCommit(false);; } /** *--- 事务提交 */ public static void commitAndClose(){ try { //获取连接 Connection conn = getConnection(); //提交事务 conn.commit(); //释放资源 conn.close(); //解除绑定 tl.remove(); } catch (SQLException e) { e.printStackTrace(); } } /** * ----事务回滚 */ public static void rollbackAndClose(){ try { //获取连接 Connection conn = getConnection(); //事务回滚 conn.rollback(); //释放资源 conn.close(); //解除绑定 tl.remove(); } catch (SQLException e) { e.printStackTrace(); } }}dao层进行具体数据库操作
xxxxxxxxxxpackage com.itqf.dao;import java.sql.Connection;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.sql.SQLException;import org.apache.commons.dbutils.DbUtils;import org.apache.commons.dbutils.QueryRunner;import com.itqf.utils.DataSourceUtils;import com.itqf.utils.JdbcUtils;public class AccountDaoDButis{ /** * 转出钱 * @param from * @param money * @throws SQLException */ public void out(String from, String money) throws SQLException { // TODO Auto-generated method stub //创建 queryrunner QueryRunner queryRunner = new QueryRunner(); //编写sql String sql ="update account set money = money - ? where name = ?"; //执行sql //手动传入 queryRunner.update(DataSourceUtils.getConnection(),sql,money,from); //不要调DButils操作 //DbUtils.close(conn); } /* * 转入操作 */ public void in(String to, String money) throws SQLException { // TODO Auto-generated method stub QueryRunner queryRunner = new QueryRunner(); //编写sql String sql ="update account set money = money + ? where name = ?"; //执行sql //手动传入 queryRunner.update(DataSourceUtils.getConnection(),sql,money,to); //不要调DButils操作 }} xxxxxxxxxxpackage com.itqf.service;import java.sql.Connection;import java.sql.SQLException;import java.sql.Savepoint;import com.itqf.dao.AccountDao;import com.itqf.dao.AccountDaoDButis;import com.itqf.dao.AccountDaoLocal;import com.itqf.utils.DataSourceUtils;import com.itqf.utils.JdbcUtils;/** * jdbc+threadlocal * * @author Administrator * */public class AccountServiceDButil { /** * 转账业务逻辑 * @param from * @param to * @param money * @throws Exception */ public void transfer(String from, String to,String money) throws Exception { // TODO Auto-generated method stub AccountDaoDButis accountDao = new AccountDaoDButis(); try { //开启事务 DataSourceUtils.startTransaction(); //1.转出 accountDao.out(from,money); int z = 1/0; //2.转入 accountDao.in(to,money); DataSourceUtils.commitAndClose(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); DataSourceUtils.rollbackAndClose(); throw e; //接着向外抛 } }} xxxxxxxxxxpackage com.itqf.web.servlet;import java.io.IOException;import java.io.PrintWriter;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import com.itqf.service.AccountService;import com.itqf.service.AccountServiceDButil;import com.itqf.service.AccountServiceLocal;public class AccountServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //设置编码格式 request.setCharacterEncoding("UTF-8"); response.setContentType("text/html;charset=UTF-8"); PrintWriter writer = response.getWriter(); //获取表单数据 String from = request.getParameter("outaccount"); String to = request.getParameter("intaccount"); String money = request.getParameter("money"); //调用业务逻辑 AccountServiceDButil accountService = new AccountServiceDButil(); try { accountService.transfer(from,to,money); //分发转向 writer.print("转账成功!"); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); writer.print("转账失败!"); }; } /** * The doPost method of the servlet. <br> * * This method is called when a form has its tag value method equals to post. * * @param request the request send by the client to the server * @param response the response send by the server to the client * @throws ServletException if an error occurred * @throws IOException if an error occurred */ public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); }}分页是web应用程序非常重要的一个技术。数据库中的数据可能是成千上万的,不可能把这么多的数据一次显示在浏览器上面。一般根据每行数据在页面上所占的空间每页显示若干行,比如一般20行是一个比较理想的显示状态。
分页的方法主要有以下两种思路
1.取出符合条件的数据,放到数据集或者内存当中,然后逐页浏览。例如,有可能每页只浏览20条记录,但使用这种分页方法需要把所有记录取出来。这种分页的方法叫做“指针分页或假分页”。
2.对于海量的数据查询,看多少就取多少,显然是最佳的解决方法,假如某个表中有200万条记录,第一页取前20条,第二页取21~40条记录。此时可以使用。
select top 当前页每页记录数查询字段列表 from 表A where 主键字段 not in (select top (当前页-1)当前页记录数主键字段 from 表A)
这样的语句来实现,因为这种查询方式要使用主键,所以叫他做“主键分页”
步骤:
1.确定每页显示的数据数量
2.确定分页显示所需的总页数
3.编写SQL查询语句,实现数据查询
4.在JSP页面中进行分页显示设置
代码实现如下:
create database day20_student;
xxxxxxxxxx use day20_student; create table student( studentNo int(4) NOT NULL, loginPwd varchar(20) NOT NULL, studentName varchar(50) NOT NULL, sex char(2) NOT NULL, bornDate datetime ); -- 向数据库中添加100条添加记录
xxxxxxxxxx <c3p0-config> <default-config> <property name="driverClass">com.mysql.jdbc.Driver</property> <property name="jdbcUrl">jdbc:mysql://localhost:3306/day39_myschool</property> <property name="user">root</property> <property name="password">root</property> <property name="acquireIncrement">5</property> <property name="initialPoolSize">10</property> <property name="minPoolSize">5</property> <property name="maxPoolSize">30</property> </default-config></c3p0-config>Student类
xxxxxxxxxxpackage com.qf.myschool.domain;import java.util.Date;/** * 学生类 * @author wgy */public class Student { private int studentNo; private String loginPwd; private String studentName; private String sex; private Date bornDate; public Student() { // TODO Auto-generated constructor stub } public Student(int studentNo, String loginPwd, String studentName, String sex, Date bornDate) { super(); this.studentNo = studentNo; this.loginPwd = loginPwd; this.studentName = studentName; this.sex = sex; this.bornDate = bornDate; } public int getStudentNo() { return studentNo; } public void setStudentNo(int studentNo) { this.studentNo = studentNo; } public String getLoginPwd() { return loginPwd; } public void setLoginPwd(String loginPwd) { this.loginPwd = loginPwd; } public String getStudentName() { return studentName; } public void setStudentName(String studentName) { this.studentName = studentName; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public Date getBornDate() { return bornDate; } public void setBornDate(Date bornDate) { this.bornDate = bornDate; } public String toString() { return "Student [studentNo=" + studentNo + ", loginPwd=" + loginPwd + ", studentName=" + studentName + ", sex=" + sex + ", bornDate=" + bornDate + "]"; } }PageBean类
xxxxxxxxxxpackage com.qf.myschool.domain;import java.util.List;/** * 页面数据类 * @author wgy * */public class PageBean { //页码 private int pageIndex; //页大小 private int pageSize=10; //总数据据个数 private int totalCount; //总页数 private int pageCount; //页面数据 private List<Student> data; //开始的页码 private int startIndex; //结束的页码 private int endIndex; public int getStartIndex() { return startIndex; } public void setStartIndex(int startIndex) { this.startIndex = startIndex; } public int getEndIndex() { return endIndex; } public void setEndIndex(int endIndex) { this.endIndex = endIndex; } public PageBean(int pageIndex,int totalCount){ this.pageIndex=pageIndex; this.totalCount=totalCount; //计算总页数 pageCount=totalCount%pageSize==0?totalCount/pageSize:totalCount/pageSize+1; //开始页码,结束页码 startIndex=pageIndex-5; endIndex=pageIndex+4; //处理特殊情况 if(pageIndex<=5){ startIndex=1; endIndex=10; } if(pageIndex>=pageCount-4){ startIndex=pageCount-9; endIndex=pageCount; } if(pageCount<=10){ startIndex=1; endIndex=pageCount; } } public int getPageIndex() { return pageIndex; } public void setPageIndex(int pageIndex) { this.pageIndex = pageIndex; } public int getPageSize() { return pageSize; } public void setPageSize(int pageSize) { this.pageSize = pageSize; } public int getTotalCount() { return totalCount; } public void setTotalCount(int totalCount) { this.totalCount = totalCount; } public int getPageCount() { return pageCount; } public void setPageCount(int pageCount) { this.pageCount = pageCount; } public List<Student> getData() { return data; } public void setData(List<Student> data) { this.data = data; }}DbUtils类
xxxxxxxxxxpackage com.qf.myschool.utils;import java.sql.Connection;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.sql.SQLException;import java.sql.Statement;import com.mchange.v2.c3p0.ComboPooledDataSource;import com.mysql.jdbc.SQLError;/** * 1加载驱动 * 2建立连接 * 3释放资源 * 4更新操作 * @author wgy * */public class DbUtils { private static ComboPooledDataSource cbds; static{ cbds=new ComboPooledDataSource(); } public static Connection getConnection() throws SQLException{ if(cbds!=null){ return cbds.getConnection(); } return null; } public static void release(ResultSet rs,Statement stat,Connection conn){ if(rs!=null){ try { rs.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } if(stat!=null){ try { stat.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } if(conn!=null){ try { conn.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } public static int executeUpdate(String sql,Object...params){ Connection conn=null; PreparedStatement pstat=null; try { conn=getConnection(); pstat=conn.prepareStatement(sql); for (int i = 0; i < params.length; i++) { pstat.setObject(i+1, params[i]); } return pstat.executeUpdate(); } catch (Exception e) { // TODO: handle exception e.printStackTrace(); throw new RuntimeException(e); }finally { release(null, pstat, conn); } }}StudentDao接口
package com.qf.myschool.dao;
import java.util.List;
import com.qf.myschool.domain.Student;
public interface StudentDao {
/**
*
* @param pageIndex 当前页码 1
* @param pagesize 页大小 10
* @return
*
*/
public List<Student> findByPage(int pageIndex,int pagesize);
//获取总的数据个数
public int getTotalCount();
} StudentDaoImpl类
xxxxxxxxxxpackage com.qf.myschool.dao.impl;import java.sql.Connection;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.util.ArrayList;import java.util.Date;import java.util.List;import com.qf.myschool.dao.StudentDao;import com.qf.myschool.domain.Student;import com.qf.myschool.utils.DbUtils;public class StudentDaoImpl implements StudentDao { public List<Student> findByPage(int pageIndex, int pagesize) { // TODO Auto-generated method stub Connection conn=null; PreparedStatement pstat=null; ResultSet rs=null; List<Student> students=new ArrayList<Student>(); try { conn=DbUtils.getConnection(); pstat=conn.prepareStatement("select * from student limit ?,?"); pstat.setInt(1, (pageIndex-1)*pagesize); pstat.setInt(2, pagesize); rs=pstat.executeQuery(); while(rs.next()){ int studentNo=rs.getInt("studentNo"); String loginPwd=rs.getString("loginPwd"); String studentName=rs.getString("studentName"); String sex=rs.getString("sex"); Date bornDate=rs.getDate("bornDate"); students.add(new Student(studentNo, loginPwd, studentName, sex, bornDate)); } return students; } catch (Exception e) { e.printStackTrace(); throw new RuntimeException(e); }finally { DbUtils.release(rs, pstat, conn); } } public int getTotalCount() { Connection conn=null; PreparedStatement pstat=null; ResultSet rs=null; List<Student> students=new ArrayList<Student>(); try { conn=DbUtils.getConnection(); pstat=conn.prepareStatement("select count(*) from student"); rs=pstat.executeQuery(); int count=0; if(rs.next()){ count=rs.getInt(1); } return count; } catch (Exception e) { e.printStackTrace(); throw new RuntimeException(e); }finally { DbUtils.release(rs, pstat, conn); } }}StudentService接口
xxxxxxxxxxpackage com.qf.myschool.service;import java.util.List;import com.qf.myschool.domain.PageBean;import com.qf.myschool.domain.Student;public interface StudentService { public PageBean getPage(int pageIndex);}StudentServiceImpl实现类
xxxxxxxxxxpackage com.qf.myschool.service.impl;import java.util.List;import com.qf.myschool.dao.StudentDao;import com.qf.myschool.dao.impl.StudentDaoImpl;import com.qf.myschool.domain.PageBean;import com.qf.myschool.domain.Student;import com.qf.myschool.service.StudentService;public class StudentServiceImpl implements StudentService { private StudentDao studentDao=new StudentDaoImpl(); public PageBean getPage(int pageIndex) { //查询数据库一共多少条数据 int totalCount=studentDao.getTotalCount(); PageBean page=new PageBean(pageIndex, totalCount); List<Student> data=studentDao.findByPage(pageIndex, page.getPageSize()); page.setData(data); return page; }} xxxxxxxxxx<% import="com.qf.myschool.domain.PageBean"%><% import="com.qf.myschool.domain.Student"%><% import="com.qf.myschool.service.impl.StudentServiceImpl"%><% import="com.qf.myschool.service.StudentService"%><% page language="java" import="java.util.*" pageEncoding="UTF-8"%><%String path = request.getContextPath();String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";%><html> <head> <base href="<%=basePath%>"> <meta charset="UTF-8"> <title>学生列表</title> <style type="text/css"> #mainbox{ width: 850px;margin: 0 auto;} </style> </head> <body> <div id="mainbox"> <% String pageIndex=request.getParameter("pageIndex"); StudentService studentService=new StudentServiceImpl(); Page p=null; if(pageIndex==null){ p=studentService.getPage(1); }else{ p=studentService.getPage(Integer.parseInt(pageIndex)); } List<Student> students=p.getData(); %> <a href="editstudent.jsp">添加</a> <table border="1" width="800"> <tr> <th>学号</th> <th>密码</th> <th>姓名</th> <th>性别</th> <th>出生日期</th> <th>操作</th> </tr> <% if(students!=null){ for(Student stu :students){ out.println("<tr>"); out.println("<td>"+stu.getStudentNo()+"</td>"); out.println("<td>"+stu.getLoginPwd()+"</td>"); out.println("<td>"+stu.getStudentName()+"</td>"); out.println("<td>"+stu.getSex()+"</td>"); out.println("<td>"+stu.getBornDate()+"</td>"); out.println("<td><a href='editstudent.jsp?studentNo="+stu.getStudentNo()+"'>修改</a> <a href=\"javascript:del("+stu.getStudentNo()+")\">删除</a></td>"); out.println("</tr>"); } } %> </table> <script type="text/javascript"> function del(studentNo){ //alert(studentNo); if(confirm("确定要删除吗?")){ window.location.href='dodel.jsp?studentNo='+studentNo; } } </script> <a href="liststudent.jsp?pageIndex=1">首页</a> <% if(p.getPageIndex()>1){ out.println("<a href='liststudent.jsp?pageIndex="+(p.getPageIndex()-1)+"'>上一页</a>"); } for(int i=p.getStartIndex();i<=p.getEndIndex();i++){ out.println("<a href='liststudent.jsp?pageIndex="+i+"'>"+i+"</a>"); } if(p.getPageIndex()<p.getPageCount()){ out.println("<a href='liststudent.jsp?pageIndex="+(p.getPageIndex()+1)+"'>下一页</a>"); } %> <a href="liststudent.jsp?pageIndex=<%=p.getPageCount() %>">尾页</a> <input type="number" id="pageNum" style="width: 50px" min="1" > <input type="button" value="跳转" onclick="jump()"> 当前第【<%=p.getPageIndex() %>】页,共【<%=p.getPageCount() %>】页 <script type="text/javascript"> function jump(){ //alert('aaa'); var pageNum=document.getElementById("pageNum"); var v=pageNum.value; if(v==null||v.trim()==""){ alert("请输入一个数字"); return; } window.location.href='liststudent.jsp?pageIndex='+v; } </script> </div> </body></html>界面效果如图:


1、实现一个签到管理系统 要求:注册、登录、签到、签到信息查询