使用Echarts柱状图显示收入统计信息-业务层和DAO层
(1) 后台如何拼接对应的json字符串?
StringBuilder typeArr=new StringBuilder("[");
StringBuilder amountArr=new StringBuilder("[");
List
收支管理-财务添加支出
(1) 当前审批人假如是财务,那么要进行什么操作,简述逻辑。
需要向支出表写入支出信息,调用dao层对象,想支出表插入数据。
(2) 截止到这里,审批报销单功能彻底完成,再次概述整个审批逻辑。
首先判断审核是否通过,拒绝或打回,则添加审核记录,修改报销单的状态,通过则判断是否是财务,是财务则添加支出信息,修改报销单状态,不是财务则判断报销金额是否大于2500,小于2500则添加审核记录,修改报销单状态,交给财务审核,金额大于2500,则判断当前审核人是否为总裁,是总裁则添加审核记录,修改报销单状态,交给财务审核,不是总裁,则则添加审核记录,修改报销单状态,交给总裁审核。
收支管理-查看支出
(1) 到这里,对于查看收支功能实现应该是不陌生了,重点就是查询收支的sql,请问这个sql怎么编写呢?
String sql="select * from (select rownum r,d.* from (\r\n" +
"select *\r\n" +
"from income ic\r\n" +
"join employee emp on emp.empid=ic.userid where ";
for (String key : map.keySet()) {
if(!map.get(key).equals("null")) {
if(key.equals("beginTime")) {
sql+=" icdate >= to_date('"+map.get(key)+"','yyyy-mm-dd') and ";
continue;
}else if(key.equals("endTime")) {
sql+=" icdate <= to_date('"+map.get(key)+"','yyyy-mm-dd') and ";
continue;
}else if(key.equals("icType")) {
sql+=" ictype='"+map.get(key)+"' and ";
continue;
}
}
}
sql+="1=1 order by ic.icid desc) d where rownum<=?) where r>?";
收支管理-使用饼图显示支出
(1) 如何使用Echarts完成饼图展示?
(2) 如何将后台查出来的集合转换成为json字符串?
使用StringBuffer将字符字符串拼接成符合规范的json字符串。
public String showOut(int i) {
String[] type= {"通信费用","办公室耗材","住宿费用","房租水电","其他"};//1 通信费用 2 办公室耗材 3 住宿费用 4 房租水电 5 其他
PaymentDao paymentDao=new PaymentDaoImpl();
StringBuilder typeArr=new StringBuilder("[");
StringBuilder Arr=new StringBuilder("[");
List<Object[]> list=paymentDao.selPayment(i);
System.out.println(list);
//[['通信费用','办公室耗材','住宿费用','房租水电','其他'],
// [{value:335, name:'通信费用'},{value:310, name:'办公室耗材'},{value:234, name:'住宿费用'},{value:135, name:'房租水电'},{value:1548, name:'其他'}]
//]
for (Object[] obj : list) {
typeArr.append("\""+type[Integer.parseInt((String) obj[0])-1]+"\",");
Arr.append("{value:"+obj[1]+",name:\""+type[Integer.parseInt((String) obj[0])-1]+"\"},");
}
String jsonStr="["+typeArr.substring(0, typeArr.length()-1)+"],"+Arr.substring(0, Arr.length()-1)+"]]";
//System.out.println(jsonStr);
return jsonStr;
}
收支管理-使用饼图显示指定时间段的支出
(1) 如何在代码中加入逻辑:显示指定时间段的支出。
使用下拉框显示不同时间段,添加change事件,当触发事件时向后台发送ajax请求,请求该时间段内的支出数据,并拼接成规定格式的json字符串。再次初始化饼图。显示不同时间段的数据。
sxtoa项目总结
(1) 项目中大量应用到请求转发和重定向,再次简述请求转发和重定向的区别。
重定向:服务器向浏览器响应,要求浏览器访问另一个页面,地址栏会变。
请求转发,在服务器内部,请求被转发到另一个servlet,最后返回给浏览器,浏览器不知道请求被转发,地址栏不变。
(2) 简述MVC分层模式,并简述一下分层开发的优点
(3) 总结JSP的四个作用域。
(4) 简述 ajax异步请求的步骤
(5) 概述我们在项目中用到过哪些插件?
富文本编辑器、日历插件、echarts图表插件
(6) 项目整个做下来,最直观的感受是什么?
一个完整的项目所涉及的知识点非常全,很容易发现自身的薄弱点,我们需要在自身薄弱的地方多下功夫,补漏补差。
(7) 在做项目中经常伴随着各种各样的错误,对于程序出错,你有哪些收获?
学会了debug调试,使用输出语句输出关键信息。
分页意义和实现思路
(1) 为什么需要分页?分页跟增删改查中的哪个操作有关系?
分页可以有效提高界面的交互性,有大量数据时,一个页面不便显示全部数据,进行分页符合人民的日常习惯,便于交互。
和查操作有关。
(2) 简述分页的实现思路
查询数据时使用limit子句设置查询数据的条数,将查询到的有限的数据封装成一个既带有页数信息(总页数,当前页数等)有带有数据的对象,将该对象发送到浏览器,实现数据的分页显示。
理解PageBean
(1) PageBean中有哪些属性?作用是什么?
int size = 5; //每页显示记录
int index = 1; // 当前页号
int totalCount = 0; // 记录总数
int totalPageCount = 1; // 总页数
int[] numbers; //展示页数集合
List list; //要显示到页面的数据集
基本分页的后台操作
(1) 基本分页的后台操作控制层如何处理,业务层如何处理,数据访问层如何处理?
控制层:
接受查询数据的请求,接收参数,调用服务层对象获取查询结果,将查询结果转换为json字符串发送给浏览器
控制层:
根据需要查询的页码和每页的数据量调用dao层查询数据、数据总条数,封装成PageBean对象,返回给控制层
Dao层:
查询查询结果的所有数据量和查询结果
基本分页的前台操作
(1) 基本分页的前台操作,如何处理?贴出代码,并解释代码的含义
<script type="text/javascript">
/* page存储当前页 */
var page;
$(document).ready(function(){
getData(1);
getDept();
$("#sel").on("click",function(){
getData(1);
});
$("#export").on("click",function(){
var url="duty?method=export&data="+$("#form").serialize();
window.location.href=url;
});
});
/*获取部门信息,向查询条件列表插入数据*/
function getDept(){
$.get("dept",{method:"deptList"},function(data){
eval("var dept="+data);
var str=null;
for(var i in dept){
str+="+dept[i].deptName+"";
}
$("#deptList").append(str);
});
}
/* 发送ajax获取查询数据
参数为需要获取的页数
*/
function getData(pageindex){
$.get("duty",{method:"dutyList",page:pageindex,data:$("#form").serialize()},function(data){
eval("page="+data);
$("#tbody").empty();
var str;/*存放查询结果的html代码*/
for(var i in page.list){
str+=" "+
""+page.list[i].emp.empid+" "+
""+page.list[i].emp.realname+" "+
""+page.list[i].emp.dept.deptName+" "+
""+page.list[i].dtDate+" "+
""+page.list[i].signinTime+" "+
""+page.list[i].signoutTime+" ";
}
$("#tbody").append(str);/*将查询结果的html代码追加到对于的div*/
$("#num").text(page.totalCount);
$("#page").text(page.Index);
$("#pageList").empty();
var str=" ";
for(var i in page.numbers){
str+="" +page.numbers[i]+"";
}
str+=" ";
$("#pageList").append(str);
$("#page").text(page.index);
$("#"+page.index).addClass("current");
$("#"+page.index).attr("href","javascript:return false;");
});
};
/*前一页*/
function pre(){
if(page.index!=1){
getData(page.index-1);
}
}
/*后一页*/
function next(){
if(page.index!=page.totalPageCount){
getData(page.index+1);
}
}
</script>
<html>
<head>
<base href="<%=basePath%>">
<title>查询并显示所有学生信息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">
<script type="text/javascript">
function changeIndex(index){
window.location.href="servlet/ShowAllServlet?index="+index;
}
function changeSize(size){
//alert(size);
window.location.href="servlet/ShowAllServlet?size="+size;
}
function change(index,size){
window.location.href="servlet/ShowAllServlet?index="+index+"&size="+size;
}
script>
head>
<body>
<table align="center" border="1" width="60%">
<tr>
<th>学生 编号th>
<th>学生姓名th>
<th>学生年龄th>
<th>学生成绩th>
<th>vs.indexth>
<th>更新操作th>
<th>删除操作th>
tr>
<c:forEach items="${pageBean.list}" var="stu" varStatus="vs">
<tr>
<td>${stu.id }td>
<td>${stu.name }td>
<td>${stu.age }td>
<td>${stu.score }td>
<td>${vs.index }td>
<td><a href="/stumanager/servlet/StudentServlet?operate=preupdate&sid=${stu.id}">更新a>td>
<td><a href="/stumanager/servlet/StudentServlet?operate=delete&sid=${stu.id}">删除a>td>
tr>
c:forEach>
<tr>
<td colspan="7" align="center">
<a href="servlet/ShowAllServlet?index=1&size=${pageBean.size }">首页a>
<c:if test="${pageBean.index !=1 }">
<a href="servlet/ShowAllServlet?index=${pageBean.index-1 }&size=${pageBean.size }">上一页a>
c:if>
<c:if test="${pageBean.index ==1 }">
上一页
c:if>
<c:forEach items="${pageBean.numbers }" var="num">
<c:if test="${num ==pageBean.index }">
[<a href="servlet/ShowAllServlet?index=${num }&size=${pageBean.size }">${num}a> ]
c:if>
<c:if test="${num !=pageBean.index }">
<a href="servlet/ShowAllServlet?index=${num }&size=${pageBean.size }">${num}a>
c:if>
c:forEach>
<c:if test="${pageBean.index !=pageBean.totalPageCount }">
<a href="servlet/ShowAllServlet?index=${pageBean.index+1 }&size=${pageBean.size }">下一页 a>
c:if>
<c:if test="${pageBean.index ==pageBean.totalPageCount }">
下一页
c:if>
<a href="servlet/ShowAllServlet?index=${pageBean.totalPageCount}&size=${pageBean.size }">末页a>
每页
<select onchange="changeSize(this.value)">
<c:forEach begin="5" end="25" step="5" var="i">
<c:if test="${i==pageBean.size }">
<option value="${i }" selected="selected">${i }option>
c:if>
<c:if test="${i!=pageBean.size }">
<option value="${i }">${i }option>
c:if>
c:forEach>
select>
条记录
直接跳转到
<select onchange="change(this.value,${pageBean.size })">
<c:forEach begin="1" end="${pageBean.totalPageCount }" var="num">
<c:if test="${num ==pageBean.index }">
<option value="${num }" selected="selected">${num }option>
c:if>
<c:if test="${num !=pageBean.index }">
<option value="${num }" >${num }option>
c:if>
c:forEach>
select>
页
共${pageBean.totalCount}条记录
td>
tr>
table>
body>
html>
Servlet
public class ShowAllServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//response.setCharacterEncoding("text/html; charset=utf-8");
request.setCharacterEncoding("utf-8");
//1.1、接收视图层传来的当前页码(处理在空值情况)
String sindex=request.getParameter("index");
int index=1;//如果index为空值 默认页数为1
try {
index=Integer.parseInt(sindex);
} catch (NumberFormatException e) {
e.printStackTrace();
}
//1.2、接收视图层显示的每页显示的记录数
String sszie=request.getParameter("size");
int size=5;
try {
size=Integer.parseInt(sszie);
} catch (NumberFormatException e) {
e.printStackTrace();
}
//1.3 接收视图层的姓名信息
String name= request.getParameter("name");
//1.4 接收视图层的分数信息
String sminScore =request.getParameter("minScore");
double minScore=0;
if (sminScore ==null) {//java.lang.NullPointerException的解决
sminScore="";
}
try {
minScore =Double.parseDouble(sminScore);
} catch (NumberFormatException e) {
e.printStackTrace();
}
//2、给工具类赋值当前页数
PageBean<Student> pageBean = new PageBean<Student>();
pageBean.setIndex(index);
pageBean.setSize(size);
StudentService stu = new StudentServiceImpl();
//List stuList =stuBiz.findAll();
//stu.findStu(pageBean);
stu.findStu(pageBean,name,minScore);
request.setAttribute("pageBean",pageBean);//!!!!!!!
request.setAttribute("name", name);
request.setAttribute("minScore", minScore);
//3
request.getRequestDispatcher("/jsp/showAll.jsp").forward(request, response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
this.doGet(request, response);
}
}
ServiceImpl
public class StudentServiceImpl implements StudentService {
private StudentDao stuDao = new StudentDaoImpl();
public List<Student> findAll() {
return this.stuDao.findAll();
}
public void findStu(PageBean<Student> pageBean) {
//1、获取数据库记录中的总数
//int totalCount=stuDao.findAll().size();//效率低下,因为会先查数据再改条数
int totalCount=stuDao.findtotalCount();
//System.out.println("totalCount:"+totalCount);
//2、使用记录计算pagebean中的其他属性(totalCount,totalPageCount,numbers),还剩list属性
pageBean.setTotalCount(totalCount);
//3、调用到层来获取指定页的学生数据,并放入pagebeande 的list属性
int start=pageBean.getStartRow();
int end=pageBean.getEndRow();
List<Student> stuList=stuDao.findStu(start,end);
pageBean.setList(stuList);
}
public void findStu(PageBean<Student> pageBean, String name, double minScore) {
//1、获取数据库记录中的总数
int totalCount=stuDao.findtotalCount(name,minScore);
System.out.println("totalCount:"+totalCount);
//2、使用记录计算pagebean中的其他属性(totalCount,totalPageCount,numbers),还剩list属性
pageBean.setTotalCount(totalCount);
//3、调用到层来获取指定页的学生数据,并放入pagebeande 的list属性
int start=pageBean.getStartRow();
int end=pageBean.getEndRow();
//List stuList=stuDao.findStu(start,end);
List<Student> stuList=stuDao.findStu(start,end,name,minScore);
pageBean.setList(stuList);
}
}
DaoImpl
public class StudentDaoImpl implements StudentDao {
public int findtotalCount() {
Connection conn =DBUtil.getConnection();
Statement stmt =null;
ResultSet rs =null;
int totalCount=0;
try {
stmt =conn.createStatement();
rs = stmt.executeQuery("select count(*) from student");
rs.next();
totalCount=rs.getInt(1);
} catch (SQLException e) {
e.printStackTrace();
}finally{
DBUtil.closeAll(rs, stmt, conn);
}
return totalCount;
}
public List<Student> findAll() {
Connection conn =DBUtil.getConnection();
Statement stmt =null;
ResultSet rs =null;
List <Student> stuList = new ArrayList<Student>();
try {
stmt =conn.createStatement();
rs = stmt.executeQuery("select * from student");
while(rs.next()){
Student stu = new Student();
stu.setId(rs.getInt("id"));
stu.setName(rs.getString("name"));
stu.setAge(rs.getInt("age"));
stu.setScore(rs.getDouble("score"));
stuList.add(stu);
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
DBUtil.closeAll(rs, stmt, conn);
}
return stuList;
}
public List<Student> findStu(int start, int end) {
Connection conn =DBUtil.getConnection();
Statement stmt =null;
ResultSet rs =null;
List <Student> stuList = new ArrayList<Student>();
try {
stmt =conn.createStatement();
String sql="select * from (select rownum rn,stu2.* "
+" from (select stu.* from student stu order by score desc) stu2 "
+" where rownum <="+end+" ) "
+" where rn >"+start;
rs = stmt.executeQuery(sql);
while(rs.next()){
Student stu = new Student();
stu.setId(rs.getInt("id"));
stu.setName(rs.getString("name"));
stu.setAge(rs.getInt("age"));
stu.setScore(rs.getDouble("score"));
stuList.add(stu);
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
DBUtil.closeAll(rs, stmt, conn);
}
return stuList;
}
带查询条件的分页
(1) 带查询条件的分页跟不带查询条件的分页有什么区别?
区别:条件查询分页需要拼接sql语句,不带条件的不需要
(2) 贴出带查询条件分页的前端代码,后端代码,并写出注释
Jsp页面
<html>
<head>
<base href="<%=basePath%>">
<title>查询并显示所有学生信息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">
<script type="text/javascript">
function changeIndex(index){
window.location.href="servlet/ShowAllServlet?index="+index;
}
function changeSize(size){
//alert(size);
window.location.href="servlet/ShowAllServlet?size="+size;
}
function change(index,size){
//window.location.href="servlet/ShowAllServlet?index="+index+"&size="+size;
/* 如何让 点击页码提交超链接的同时提交表单呢?forms[0]:代表第一个form表单 */
document.forms[0].action="servlet/ShowAllServlet?index="+index+"&size="+size;
document.forms[0].submit();
}
script>
姓名 | 分数>= |
学生 编号
学生姓名
学生年龄
学生成绩
vs.index
更新操作
删除操作
${stu.id }
${stu.name }
${stu.age }
${stu.score }
${vs.index }
更新
删除
首页
上一页
上一页
[${num} ]
${num}
下一页
下一页
末页
每页
条记录
直接跳转到
页
共${pageBean.totalCount}条记录
```
(1) 完善了哪些功能?简述完善的思路.
提交表单后并传入当前页号
删除后仍跳转到当前页,而不是第一页
选择每页几条记录变更后,没有机组当前页号
思路:
在提交相关变更时,传入当前页号和每页显示几条记录的信息
分享/讲解/扩展思考
点名提问从第一节课到最后一节课分别学到了什么,直到同学们把所有的知识点都说出来并且保证无误。