学号 | 密码 | 姓名 | 性别 | 出生日期 | 操作 |
---|---|---|---|---|---|
${stu.studentNo} | ${stu.loginPwd} | ${stu.studentName} | ${stu.sex} |
首先我们需要知道MVC模式并不是javaweb项目中独有的,MVC是一种软件工程中的一种设计模式,把软件系统分为三个基本部分:模型(Model)、视图(View)和控制器(Controller),即为MVC。它是一种软件设计的典范,最早为Trygve Reenskaug提出,为施乐帕罗奥多研究中心(Xerox PARC)的Smalltalk语言发明的一种软件设计模式。
虽然MVC并不是Java当中独有的,但是现在几乎所有的B/S的架构都采用了MVC框架模式。
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的优化(Model1第二代)
JSP Model1优化后有所改进,把业务逻辑和数据访问的内容放到了JavaBean(狭义JavaBean:实体类,广义JavaBean:实体类,dao,service,工具类)中,而JSP页面负责显示以及请求调度的工作。虽然第二代比第一代好了些,但还让JSP做了过多的工作,JSP中把视图工作和请求调度(控制器)的工作耦合在一起了。
JSP Model2模式已经可以清晰的看到MVC完整的结构了。
JSP:视图层,用来与用户打交道。负责接收数据,以及显示数据给用户;
Servlet:控制层,负责找到合适的模型对象来处理业务逻辑,转发到合适的视图;
JavaBean:模型层,完成具体的业务工作,例如:开启事务、转账等。
小结:这就是javaweb经历的两个时期,JSP Model2适合多人合作开发大型的Web项目,各司其职,互不干涉,有利于开发中的分工,有利于组件的重用。但是,Web项目的开发难度加大,同时对开发人员的技术要求也提高了。
虽然MVC把程序分成三部分,每个部分负责不同的功能,但是这只是逻辑的分离,实际代码并没有真正分离,特别是Model(包括业务、数据访问和实体类、工具类等)部分的代码,为了增强代码的维护性和降低代码耦合性,需要把代码分层管理,于是就有了三层架构:
分别是:web层(表示|界面层)、service层(业务逻辑层)、dao层(数据访问层、持久层)
web层对应MVC中的Servlet和JSP
其他层都属于MVC中的Model
通过结合事务和MVC知识,练习一个转账demo
ThreadLocal:线程局部变量:作用实现把数据绑定到线程中,从而实现线程安全。
创建web项目
导入需要jar包
mysql驱动
druid.jar
commons-beanutils-1.8.3.jar
commons-collections.jar
commons-dbutils-1.4.jar
commons-logging-1.1.1.jar
添加数据库配置文件
db.properties
#连接设置
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/myschool
username=root
password=root
#
initialSize=10
#最大连接数量
maxActive=50
#
minIdle=5
#
maxWait=5000
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
My JSP 'transfer.jsp' starting page
因为要使用到mvc模式,要对项目代码进行分包
com.qf.dao
com.qf.dao.impl
com.qf.service
com.qf.service.impl
com.qf.web.servlet
com.qf.utils
com.qf.domain
DatasoutceUtils工具类,优化获取连接,优化事务操作
ThreadLocal的实例代表了一个线程局部的变量,每条线程都只能看到自己的值,并不会意识到其它的线程中也存在该变量。它采用采用空间来换取时间的方式,解决多线程中相同变量的访问冲突问题。
package 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.qf.utils.DruidUtils;
public class DataSourceUtils {
private static DruidDataSource ds=null;
private static ThreadLocal<Connection> tl=new ThreadLocal<Connection>();
//静态代码块
static {
InputStream is = DruidUtils.class.getClassLoader().getResourceAsStream("db.properties");
Properties properties=new Properties();
try {
properties.load(is);
dataSource= (DruidDataSource) DruidDataSourceFactory.createDataSource(properties);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 获取数据源
* @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 {
//----和当前的线程解绑
tl.remove();
conn.close();
} 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层进行具体数据库操作
package 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 AccountDaoImpl{
/**
* 转出钱
* @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操作
}
}
package 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 AccountServiceImpl {
/**
* 转账业务逻辑
* @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; //接着向外抛
}
}
}
package 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.
*
* 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);
}
}
常见用两种方式
1 通过JavaScript屏蔽提交按钮(不推荐)
通过js代码,当用户点击提交按钮后,屏蔽提交按钮使用户无法点击提交按钮或点击无效,从而实现防止表单重复提交。
缺点:js代码很容易被绕过。比如用户通过刷新页面方式,或使用postman等工具绕过前段页面仍能重复提交表单。因此不推荐此方法。
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<html>
<head>
<title>表单title>
<script type="text/javascript">
//默认提交状态为false
var commitStatus = false;
function dosubmit(){
if(commitStatus==false){
//提交表单后,将提交状态改为true
commitStatus = true;
return true;
}else{
return false;
}
}
script>
head>
<body>
<form action="/path/post" onsubmit="return dosubmit()" method="post" target="_blank">
用户名:<input type="text" name="username">
<input type="submit" value="提交" id="submit">
form>
body>
html>
2 利用Session防止表单重复提交(推荐)
实现原理:
服务器返回表单页面时,会先生成一个subToken保存于session,并把该subToken传给表单页面。当表单提交时会带上subToken,服务器判断session中的subToken和表单提交subToken是否一致。若不一致或session的subToken为空或表单未携带subToken则不通过。
首次提交表单时session的subToken与表单携带的subToken一致走正常流程,然后服务器会删除session保存的subToken。当再次提交表单时由于session的subToken为空则不通过。从而实现了防止表单重复提交。
代码如下:
TokenProccessor.java
package com.qf.utils;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Random;
/**
* wgy 2019/4/23 11:47
*/
public class TokenProccessor {
private TokenProccessor(){}
private static final TokenProccessor instance=new TokenProccessor();
public static TokenProccessor getInstance(){
return instance;
}
public String makeToken(){
String str=System.currentTimeMillis()+new Random().nextInt(999999999)+"";
try {
//1使用md5加密
MessageDigest digest=MessageDigest.getInstance("md5");
digest.update(str.getBytes());
byte[] digest1 = digest.digest();
//2使用base64
return Base64.getEncoder().encodeToString(digest);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
TokenTools.java
package com.qf.utils;
import javax.servlet.http.HttpServletRequest;
/**
* wgy 2019/4/23 11:54
*/
public class TokenTools {
//把token放入session
public static void createToken(HttpServletRequest request,String tokenkey){
String token=TokenProccessor.getInstance().makeToken();
request.getSession().setAttribute(tokenkey, token);
}
//把token从session删除
public static void removeToken(HttpServletRequest request,String tokenkey){
request.getSession().removeAttribute(tokenkey);
}
}
tranview.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>转账title>
<script type="text/javascript">
//默认提交状态为false
var commitStatus = false;
function dosubmit(){
if(commitStatus==false){
//提交表单后,将提交状态改为true
commitStatus = true;
document.getElementById("btnsubmit").disabled=true;
return true;
}else{
return false;
}
}
script>
head>
<body>
<%
//向session中添加令牌
TokenTools.createToken(request, "mytoken");
%>
<h2>转账h2>
<form action="${pageContext.request.contextPath}/trans" onsubmit="return dosubmit()" method="post" target="_blank">
<input type="text" name="from" placeholder="请输入转出账号"><br/>
<input type="text" name="to" placeholder="请输入转入账号"><br/>
<input type="text" name="money" placeholder="请输入金额"><br/>
<input type="hidden" name="mytoken" value="${mytoken}">
<input id="btnsubmit" type="submit" value="转账">
form>
body>
html>
TransServlet.java
package com.qf.web.servlet;
import com.qf.domain.Account;
import com.qf.service.AccountService;
import com.qf.service.impl.AccountServiceImpl;
import com.qf.utils.TokenTools;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.math.BigDecimal;
/**
* wgy 2019/4/23 11:05
*/
@WebServlet(name = "TransServlet",urlPatterns = "/trans")
public class TransServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
//判断是否是重复提交
boolean b=isRepeatSubmit(request, "mytoken");
if(b){
response.getWriter().write("不好意思,重复提交了...");
return;
}
//通过验证
TokenTools.createToken(request, "mytoken");
//接受数据
String from = request.getParameter("from");
String to = request.getParameter("to");
String money = request.getParameter("money");
//验证金额
BigDecimal m=new BigDecimal(money);
if(m.doubleValue()<=0){
response.getWriter().write("转账金额不能小于0");
return;
}
//转账
AccountService accountService=new AccountServiceImpl();
Account accfrom=new Account(Integer.parseInt(from),"宁宁",new BigDecimal(0));
Account accto=new Account(Integer.parseInt(to),"春春",new BigDecimal(0));
try {
accountService.transMoney(accfrom, accto, m);
response.getWriter().write("转账成功");
} catch (Exception e) {
e.printStackTrace();
response.getWriter().write("转账失败");
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
public boolean isRepeatSubmit(HttpServletRequest request,String clientTokeyKey){
//1 判断session有没有
String serverToken = (String) request.getSession().getAttribute(clientTokeyKey);
if(serverToken==null){
return true;
}
//2 判断客户端有没有token
String clientToken=request.getParameter(clientTokeyKey);
if(clientToken==null){
return true;
}
//3 两个是否相同
if(!serverToken.equals(clientToken)){
return true;
}
return false;
}
}
分页是web应用程序非常重要的一个技术。数据库中的数据可能是成千上万的,不可能把这么多的数据一次显示在浏览器上面。一般根据每行数据在页面上所占的空间每页显示若干行,比如一般20行是一个比较理想的显示状态。
分页的思路
对于海量的数据查询,需要多少就取多少,显然是最佳的解决方法,假如某个表中有200万条记录,第一页取前20条,第二页取21~40条记录。
select * from 表名 order by id limit 0,20 ;
select * from 表名 order by id limit 20,20;
select * from 表名 order by id limit 40,20;
步骤:
1.确定每页显示的数据数量
2.确定分页显示所需的总页数
3.编写SQL查询语句,实现数据查询
4.在JSP页面中进行分页显示设置
代码实现如下:
create database day16;
use day16;
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条添加记录
[外链图片转存失败(img-TJvxEqZf-1567856749561)(pic/01.jpg)]
#连接设置
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/myschool
username=root
password=root
#
initialSize=10
#最大连接数量
maxActive=50
#
minIdle=5
#
maxWait=5000
Student类
package 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;
}
@Override
public String toString() {
return "Student [studentNo=" + studentNo + ", loginPwd=" + loginPwd + ", studentName=" + studentName
+ ", sex=" + sex + ", bornDate=" + bornDate + "]";
}
}
PageBean类
package com.qf.myschool.domain;
import java.util.List;
/**
* 页面数据类
* @author wgy
*
*/
public class PageBean<T> {
//页码
private int pageIndex;
//页大小
private int pageSize;
//总数据据个数
private int totalSize;
//总页数
private int pageCount;
//页面数据
private List<T> data;
public PageBean(){
}
public PageBean(int pageIndex,int pageSize,int totalSize,List<T> data){
this.pageIndex=pageIndex;
this.totalSize=totalSize;
this.pageSize=pageSize;
this.data=data;
//计算总页数
pageCount=totalCount%pageSize==0?totalCount/pageSize:totalCount/pageSize+1;
}
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 getTotalSize() {
return totalCount;
}
public void setTotalSize(int totalSize) {
this.totalSize = totalSize;
}
public int getPageCount() {
return pageCount;
}
public void setPageCount(int pageCount) {
this.pageCount = pageCount;
}
public List<T> getData() {
return data;
}
public void setData(List<T> data) {
this.data = data;
}
}
DruidUtils类
package 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.alibaba.druid.pool.DruidDataSource;
import com.mysql.jdbc.SQLError;
/**
* 1加载驱动
* 2建立连接
* 3释放资源
* 4更新操作
* @author wgy
*
*/
public class DruidUtils {
private static DruidDataSource dataSource=null;
static {
InputStream is = DruidUtils.class.getClassLoader().getResourceAsStream("db.properties");
Properties properties=new Properties();
try {
properties.load(is);
dataSource= (DruidDataSource) DruidDataSourceFactory.createDataSource(properties);
} catch (Exception e) {
e.printStackTrace();
}
}
public static DataSource getDataSource(){
return dataSource;
}
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类
package 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 {
@Override
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);
}
}
@Override
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接口
package 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实现类
package 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();
@Override
public PageBean getPage(int pageIndex,int pageSize) {
//查询数据库一共多少条数据
int totalCount=studentDao.getTotalCount();
List<Student> data=studentDao.findByPage(pageIndex, pageSize);
PageBean<Student> page=new PageBean<Student>(pageIndex,pageSize,totalCount,data);
return page;
}
}
StudentListServlet.java类
@WebServlet(name = "StudentListServlet",value = "/stulist")
public class StudentListServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1获取参数 pageIndex pageSize 1 10
String _pageIndex = request.getParameter("pageIndex"); // "" null "abc"
String _pageSize = request.getParameter("pageSize");
int pageIndex=1;
int pageSize=10;
if(_pageIndex!=null&&_pageIndex.trim().length()!=0){
pageIndex=Integer.parseInt(_pageIndex);
if(pageIndex<=0){
pageIndex=1;
}
}
if(_pageSize!=null&&_pageSize.trim().length()!=0){
pageSize=Integer.parseInt(_pageSize);
}
//2调用业务
StudentService studentService=new StudentServiceImpl();
PageBean pageBean = studentService.findByPage(pageIndex, pageSize);
//3把pageBean放入域中
request.setAttribute("pageBean", pageBean);
//4转发到jsp
request.getRequestDispatcher("listStudent.jsp").forward(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
}
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
学生列表
1 MVC Model模型 View 视图 Controller 控制:是一种设计模式,属于架构模式,把程序逻辑上分成三部分
Model: 负责获取、处理数据
View: 负责展示数据
Controller:负责接受请求,调用Model, 转发或重定向
2 Jsp开发模式
Model1 Jsp+Javaban
Model2 Servlet+JSP+JavaBean
3 基于MVC三层的实现
web 层 :servlet+jsp
业务层:负责业务处理 service
持久层 :负责数据库的访问 dao
utils:工具类
domain:实体类
4 使用javaweb实现事务转账
TheadLocal:线程局部变量 key线程 value:数据
5 防止重复提交
session token(令牌)
TokenProccessor
TokenTools
6 分页查询
PageBean
pageIndex;
pageSize;
totalSize;
pageCount;
data;