目录
使用Servlet处理业务,收集数据; 使用JSP展示数据!
(1)将之前原型模板中的".html"文件,全部修改为".jsp",然后在所有的".jsp"文件头部添加page指令(指定contentType防止中文乱码),将所有的JSP直接拷贝到web目录下。
补充:ctrl+shift+del清除浏览器的缓存!
<%@page contentType="text/html;charset=UTF-8"%>
(2)完成所有页面的正常流转。(页面仍然能够正常的跳转,修改超链接的请求路径)
①这里就需要把所有的超连接路径更改,改成.jsp文件的格式;并加上项目名!
②这里就能体现出.jsp的优势,在jsp中是可以写java代码的;对于前端中的项目名,就可以通过java代码获取,不需要写死了!
③例如:对于欢迎页面index.jsp
- <%=request.getContextPath()%> 在JSP中动态的获取应用的根路径
(3)目前所有原型页面如下:都是静态的页面,都是直接跳转到jsp展示数据,中间没有经过servlet获取数据!
①index.jsp 可以跳转到 list.jsp
- <%@page contentType="text/html;charset=UTF-8"%>
- html>
- <html>
- <head>
- <meta charset="utf-8">
- <title>欢迎使用OA系统title>
- head>
- <body>
- <a href="<%=request.getContextPath()%>/list.jsp">查看部门列表a>
- <hr>
-
- body>
- html>
②以list.jsp为展开对象,可以跳转到:detail.jsp、modify.jsp、add.jsp
- <%@page contentType="text/html;charset=UTF-8"%>
- html>
- <html>
- <head>
- <meta charset="utf-8">
- <title>部门列表页面title>
- head>
- <body>
-
- <script type="text/javascript">
- function del(dno){
- // 弹出确认框,用户点击确定,返回true,点击取消返回false
- var ok = window.confirm("亲,删了不可恢复哦!");
- if(ok){
- document.location.href = "<%=request.getContextPath()%>/dept/delete?deptno=" + dno;
- }
- }
- script>
-
- <h1 align="center">部门列表h1>
- <hr >
- <table border="1px" align="center" width="50%">
- <tr>
- <th>序号th>
- <th>部门编号th>
- <th>部门名称th>
- <th>操作th>
- tr>
- <tr>
- <td>1td>
- <td>10td>
- <td>销售部td>
- <td>
- <a href="javascript:void(0)" onclick="del(10)">删除a>
- <a href="<%=request.getContextPath()%>/modify.jsp">修改a>
- <a href="<%=request.getContextPath()%>/detail.jsp">详情a>
- td>
- tr>
- table>
-
- <hr >
- <a href="<%=request.getContextPath()%>/add.jsp">新增部门a>
-
- body>
- html>
③detail.jsp展示完以后在跳转到list.jsp
- <%@page contentType="text/html;charset=UTF-8" %>
- html>
- <html>
- <head>
- <meta charset="utf-8">
- <title>部门详情title>
- head>
- <body>
- <h1>部门详情h1>
- <hr >
- 部门编号:20 <br>
- 部门名称:销售部<br>
- 部门位置:北京<br>
-
- <input type="button" value="后退" onclick="window.history.back()"/>
- body>
- html>
④modify.jsp展示完以后在跳转到list.jsp
- <%@page contentType="text/html;charset=UTF-8"%>
- html>
- <html>
- <head>
- <meta charset="utf-8">
- <title>修改部门title>
- head>
- <body>
- <h1>修改部门h1>
- <hr >
- <form action="<%=request.getContextPath()%>/list.jsp" method="get">
- 部门编号<input type="text" name="deptno" value="20" readonly /><br>
- 部门名称<input type="text" name="dname" value="销售部"/><br>
- 部门位置<input type="text" name="loc" value="北京"/><br>
- <input type="submit" value="修改"/><br>
- form>
- body>
- html>
⑤add.jsp展示完以后在跳转到list.jsp
- <%@page contentType="text/html;charset=UTF-8"%>
- html>
- <html>
- <head>
- <meta charset="utf-8">
- <title>新增部门title>
- head>
- <body>
- <h1>新增部门h1>
- <hr >
- <form action="<%=request.getContextPath()%>/list.jsp" method="get">
- 部门编号<input type="text" name="deptno"/><br>
- 部门名称<input type="text" name="dname"/><br>
- 部门位置<input type="text" name="loc"/><br>
- <input type="submit" value="新增"/><br>
- form>
- body>
- html>
前面我们已经完成了jsp做数据展示的操作,但是并没有进行连接数据库;所以要先跳转到servlet完成数据的收集操作,然后通过servlet再跳到jsp做数据展示的操作!
(1)先对index.jsp模板原型进行修改;把超链接路径修改为跳转到一个servlet
- <a href="<%=request.getContextPath()%>/list.jsp">查看部门列表a>
- <a href="<%=request.getContextPath()%>/dept/list">查看部门列表a>
(2)通过注解式开发,连接数据库,取出数据!(要有封装对象的意识---面向抽象编程)
此时取出的数据实际上是很零散的,所以不妨封装一个Dept对象,把取出来的数据封装到这个对象里面。同时在创建一个ArrayList集合depts,把所有的对象在放到这个集合里。然后在通过请求域调用setAttribute方法,把这个集合放到请求域当中。最后在调用getRequestDispatcher方法,通过转发的方式调转到另一个jsp进行数据的展示
①封装的Dept对象用来存放取出来的零散数据
- package com.bjpowernode.oa.bean;
-
- import java.util.Objects;
-
- /**
- * 普通的java类,张个java类可以封装零散的数据
- * @Author:朗朗乾坤
- * @Package:com.bjpowernode.oa.bean
- * @Project:JavaWeb
- * @name:Dept
- * @Date:2022/11/28 10:59
- */
-
- public class Dept {
- private String deptno;
- private String dname;
- private String loc;
- // 构造方法
- public Dept() {
- }
- public Dept(String deptno, String dname, String loc) {
- this.deptno = deptno;
- this.dname = dname;
- this.loc = loc;
- }
- // setter and getter
- public String getDeptno() {
- return deptno;
- }
- public void setDeptno(String deptno) {
- this.deptno = deptno;
- }
-
- public String getDname() {
- return dname;
- }
- public void setDname(String dname) {
- this.dname = dname;
- }
-
- public String getLoc() {
- return loc;
- }
- public void setLoc(String loc) {
- this.loc = loc;
- }
-
- // 重写toString方法
- @Override
- public String toString() {
- return "Dept{" +
- "deptno='" + deptno + '\'' +
- ", dname='" + dname + '\'' +
- ", loc='" + loc + '\'' +
- '}';
- }
-
- // 重写equals方法 和 hashCode方法
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
- Dept dept = (Dept) o;
- return Objects.equals(deptno, dept.deptno) &&
- Objects.equals(dname, dept.dname) &&
- Objects.equals(loc, dept.loc);
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(deptno, dname, loc);
- }
- }
②跳转到的servlet进行数据的收集
- package com.bjpowernode.oa.web.action;
-
- import com.bjpowernode.oa.bean.Dept;
- import com.bjpowernode.oa.utils.DBUtil;
-
- 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.sql.Connection;
- import java.sql.PreparedStatement;
- import java.sql.ResultSet;
- import java.sql.SQLException;
- import java.util.ArrayList;
-
- /**
- * @Author:朗朗乾坤
- * @Package:com.bjpowernode.oa.web.action
- * @Project:JavaWeb
- * @name:DeptServlet
- * @Date:2022/11/28 10:39
- */
- @WebServlet({"/dept/list"})
- public class DeptServlet extends HttpServlet {
- @Override
- protected void service(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
- // 获取servlet path
- String servletPath = request.getServletPath();
- if ("/dept/list".equals(servletPath)){
- doList(request,response);
- }
-
- }
-
- /**
- *1、 连接数据库,查询所有的部门信息,然后跳转到jsp做页面展示
- * @param request
- * @param response
- * @throws ServletException
- * @throws IOException
- */
- private void doList(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException{
-
- // 再创建一个容器,用来存储部门
- ArrayList
depts = new ArrayList<>(); -
- Connection conn = null;
- PreparedStatement ps = null;
- ResultSet rs = null;
-
- try {
- // 连接数据库
- conn = DBUtil.getCoonetion();
- // 获取预编译的数据库操作对象
- String sql = "select deptno,dname,loc from dept";
- ps = conn.prepareStatement(sql);
- // 执行sql
- rs = ps.executeQuery();
- // 遍历查询结果集
- while (rs.next()) {
- // 取出数据
- String deptno = rs.getString("deptno");
- String dname = rs.getString("dname");
- String loc = rs.getString("loc");
- // 将零散的数据封装一个对象放进去
- Dept dept = new Dept();
- dept.setDeptno(deptno);
- dept.setDname(dname);
- dept.setLoc(loc);
- // 肯定不止一个对象,所以创建一个集合(容器),用来存储部门对象
- depts.add(dept);
- }
- } catch (SQLException e) {
- e.printStackTrace();
- }finally {
- DBUtil.close(conn,ps,rs);
- }
-
- // 将集合放到请求域当中
- request.setAttribute("deptList",depts);
-
- // 转发(不要重定向)
- request.getRequestDispatcher("/list.jsp").forward(request,response);
-
- }
- }
③通过转发的方式跳转到的另一个list.jsp,进行数据的展示
重点:对于for循环打印,这里实际上是拆分开了,但是转化为java代码还是一个完整的for循环;第一次见到这种输出方式,可能会比较不适应!
- <%@ page import="com.bjpowernode.oa.bean.Dept" %>
- <%@ page import="java.util.List" %>
-
- <%@page contentType="text/html;charset=UTF-8"%>
- html>
- <html>
- <head>
- <meta charset="utf-8">
- <title>部门列表页面title>
- head>
- <body>
-
- <script type="text/javascript">
- function del(dno){
- // 弹出确认框,用户点击确定,返回true,点击取消返回false
- var ok = window.confirm("亲,删了不可恢复哦!");
- if(ok){
- document.location.href = "<%=request.getContextPath()%>/dept/delete?deptno=" + dno;
- }
- }
- script>
-
- <h1 align="center">部门列表h1>
- <hr >
- <table border="1px" align="center" width="50%">
- <tr>
- <th>序号th>
- <th>部门编号th>
- <th>部门名称th>
- <th>操作th>
- tr>
-
- <%
- // 从request域当中取出集合
- // getAttribute取出来的是Object类型,这里进行了强制类型转换
- List<Dept> deptList = (List<Dept>)request.getAttribute("deptList");
- // 循环遍历
- int i =0;
- for(Dept dept:deptList){
- %>
-
- <tr>
- <td><%=++i%>td>
- <td><%=dept.getDeptno()%>td>
- <td><%=dept.getLoc()%>td>
- <td>
- <a href="javascript:void(0)" onclick="del(10)">删除a>
- <a href="<%=request.getContextPath()%>/modify.jsp">修改a>
- <a href="<%=request.getContextPath()%>/detail.jsp">详情a>
- td>
- tr>
-
- <%
- }
- %>
-
- table>
-
- <hr >
- <a href="<%=request.getContextPath()%>/add.jsp">新增部门a>
-
- body>
- html>
④思考:如果只使用JSP这一个技术,能不能开发web应用?
①当然可以使用JSP来完成所有的功能。因为JSP就是Servlet,在JSP的<%%>里面写的代码就是在service方法当中的,所以在<%%>当中完全可以编写JDBC代码,连接数据库,查询数据,也可以在这个方法当中编写业务逻辑代码,处理业务都是可以的,所以使用单独的JSP开发web应用完全没问题。
②虽然JSP一个技术就可以完成web应用,但是不建议,还是建议采用servlet + jsp的方式进行开发;这样都能将各自的优点发挥出来。JSP就是做数据展示!Servlet就是做数据的收集!(JSP中编写的Java代码越少越好)一定要职责分明!
⑤思考:JSP文件的扩展名必须是xxx.jsp吗?
①jsp文件的扩展名是可以配置的,不是固定的。
②在CATALINA_HOME/conf/web.xml,在这个文件当中配置jsp文件的扩展名。
③xxx.jsp文件对于Tomcat来说,只是一个普通的文本文件,web容器会将xxx.jsp文件最终生成java程序,最终调用的是java对象相关的方法,真正执行的时候,和jsp文件没有关系。
④小窍门:如果JSP代码看不懂,建议把jsp翻译成java代码,就能看懂了!
- <servlet-mapping>
- <servlet-name>jspservlet-name>
- <url-pattern>*.jspurl-pattern>
- <url-pattern>*.jspxurl-pattern>
- servlet-mapping>
①对list.jsp中的详情超链接路径进行更改;并把部门编号也传过去
- <a href="<%=request.getContextPath()%>/detail.jsp">详情a>
- <a href="<%=request.getContextPath()%>/dept/detail?deptno=<%=dept.getDeptno()%>">详情a>
②跳转到servlet,根据deptno进行数据的收集
这里就和上面不同,上面我们是查询所有的数据,有很多组,需要先把数据放到对象里,再把对象放到集合里;而这里每次使根据depto编号进行查询,就一组数据,所以不需要集合!
- /**
- *2、 根据部门编号,获取部门的详细信息
- * @param request
- * @param response
- * @throws ServletException
- * @throws IOException
- */
- private void doDetail(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException{
- // 创建一个集合,用来存放数据
- Dept dept = new Dept();
- // 通过key获取value,获取部门标号
- String deptno = request.getParameter("deptno");
- // 根据部门编号获取部门信息,将部门信息封装成对象
- // 不需要集合,因为只有一个对象的数据
- Connection conn = null;
- PreparedStatement ps = null;
- ResultSet rs = null;
-
- try {
- // 获取连接
- conn = DBUtil.getCoonetion();
- // 获取预编译的数据库操作对象
- String sql = "select dname,loc from dept where deptno = ?";
- ps = conn.prepareStatement(sql);
- ps.setString(1,deptno);
- // 执行sql
- rs = ps.executeQuery();
- // 处理查询结果集,实际上就一条数据
- if (rs.next()){
- String dname = rs.getString("dname");
- String loc = rs.getString("loc");
- // 把数据封装成一个对象
- // Dept dept = new Dept(); 定义到这里,下面转发使用不了
- dept.setDeptno(deptno);
- dept.setDname(dname);
- dept.setLoc(loc);
- }
-
- } catch (SQLException e) {
- e.printStackTrace();
- }finally {
- DBUtil.close(conn,ps,rs);
- }
-
- // 将封装的对象放到请求域当中
- request.setAttribute("deptList",dept);
-
- // 转发(不要重定向)
- request.getRequestDispatcher("/detail.jsp").forward(request,response);
-
- }
③通过转发的方式跳转到的另一个detail.jsp,进行数据的展示
- <%@ page import="com.bjpowernode.oa.bean.Dept" %>
- <%@page contentType="text/html;charset=UTF-8" %>
-
-
- html>
- <html>
- <head>
- <meta charset="utf-8">
- <title>部门详情title>
- head>
- <body>
- <h1>部门详情h1>
- <hr >
-
- <%
- // 从request域当中取出数据,强制类型转换
- Dept dept = (Dept)request.getAttribute("deptList");
- %>
-
- 部门编号:<%=dept.getDeptno()%> <br>
- 部门名称:<%=dept.getDname()%><br>
- 部门位置:<%=dept.getLoc()%><br>
-
- <input type="button" value="后退" onclick="window.history.back()"/>
- body>
- html>
①对list.jsp中的删除超链接路径进行更改;这里是使用一个回调函数进行路径的跳转
- <a href="javascript:void(0)" onclick="del(10)">删除a>
- // 修改为
- <a href="javascript:void(0)" onclick="del(<%=dept.getDeptno()%>)">删除a>
-
- // 回调函数如下,没有修改:
- <script type="text/javascript">
- function del(dno) {
- // 弹出确认框,用户点击确定,返回true,点击取消返回false
- var ok = window.confirm("亲,删了不可恢复哦!");
- if (ok) {
- document.location.href = "<%=request.getContextPath()%>/dept/delete?deptno=" + dno;
- }
- }
- script>
②跳转到servlet,根据deptno进行数据的收集;并且再次跳转到/dept/list页面进行数据的展示,这里使用的是重定向,因为不涉及从域中存取数据,所以尽可能使用重定向!
- /**
- *3、 根据部门编号,删除部门
- * @param request
- * @param response
- * @throws ServletException
- * @throws IOException
- */
- private void doDel(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
- // 获取部门编号
- String deptno = request.getParameter("deptno");
- // 连接数据库
- Connection conn = null;
- PreparedStatement ps = null;
- int count = 0;
- try {
- conn = DBUtil.getCoonetion();
- String sql = "delete from dept where deptno=?";
- ps = conn.prepareStatement(sql);
- ps.setString(1,deptno);
- count = ps.executeUpdate();
- } catch (SQLException e) {
- e.printStackTrace();
- }finally {
- DBUtil.close(conn,ps,null);
- }
-
- if (count==1) {
- // 删除成功,重定向到list页面;因为这里没有想域中放入数据,所以使用重定向
- // 重定向是要加项目名的,动态获取
- String contextPath = request.getContextPath();
- response.sendRedirect(contextPath+"/dept/list");
- }
- }
①对list.jsp中的详新增超链接路径不要更改,因为需要一个提交的表单;从add.jsp这个表单中跳转到servlet
注:这里是提交数据,所以应该使用post请求!
- <a href="<%=request.getContextPath()%>/add.jsp">新增部门a>
-
- <form action="<%=request.getContextPath()%>/list.jsp" method="get">
- <form action="<%=request.getContextPath()%>/dept/add" method="post">
②add.jsp
- <%@page contentType="text/html;charset=UTF-8"%>
- html>
- <html>
- <head>
- <meta charset="utf-8">
- <title>新增部门title>
- head>
- <body>
- <h1>新增部门h1>
- <hr >
- <%--<form action="<%=request.getContextPath()%>/list.jsp" method="get">--%>
- <form action="<%=request.getContextPath()%>/dept/add" method="post">
- 部门编号<input type="text" name="deptno"/><br>
- 部门名称<input type="text" name="dname"/><br>
- 部门位置<input type="text" name="loc"/><br>
- <input type="submit" value="新增"/><br>
- form>
- body>
- html>
③跳转到servlet,根据前端提交的数据,调用getParameter方法获取到后,进行数据的插入;然后再通过重定向/dept/list页面,进行数据的展示
- /**
- * 4、根据前端提交的数据,新增部门
- * @param request
- * @param response
- * @throws ServletException
- * @throws IOException
- */
- private void doAdd(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
- // 获取部门的信息
- // 注意乱码问题(Tomcat10不会出现这个问题)
- request.setCharacterEncoding("UTF-8");
- String deptno = request.getParameter("deptno");
- String dname = request.getParameter("dname");
- String loc = request.getParameter("loc");
-
- // 连接数据库执行insert语句
- Connection conn = null;
- PreparedStatement ps = null;
- int count = 0;
- try {
- conn = DBUtil.getCoonetion();
- String sql = "insert into dept(deptno, dname, loc) values(?,?,?)";
- ps = conn.prepareStatement(sql);
- ps.setString(1, deptno);
- ps.setString(2, dname);
- ps.setString(3, loc);
- count = ps.executeUpdate();
- } catch (SQLException e) {
- e.printStackTrace();
- } finally {
- DBUtil.close(conn, ps, null);
- }
- if (count == 1) {
- response.sendRedirect(request.getContextPath() + "/dept/list");
- }
- }
思考:我们已经知道对于修改实际上有两次连接数据库的操作;第一次点击list页面的修改实际上就相当于查询;所以我们不妨就让 修改和详情 共享一个页面;然后在打一个标记;根据标记决定最终是跳转到detail.jsp还是modify.jsp
①修改list.jsp代码;两个走的是通过一个servlet(/dept/detail),有一个标记f
- <a href="<%=request.getContextPath()%>/dept/detail?f=modify&deptno=<%=dept.getDeptno()%>">修改a>
- <a href="<%=request.getContextPath()%>/dept/detail?f=detail&deptno=<%=dept.getDeptno()%>">详情a>
②修改/dept/detail代码,就需要获取标记f,根据标记f来决定跳转的页面
- // 方法1:获取这个标记,然后讨论
- String f = request.getParameter("f");
- if ("modify".equals(f)){
- request.getRequestDispatcher("/modify.jsp").forward(request,response);
- }else if ("detail".equals(f)){
- request.getRequestDispatcher("/detail.jsp").forward(request,response);
- }
-
- // 方法2:进行拼串
- String forward = "/"+request.getParameter("f")+".jsp";
- request.getRequestDispatcher(forward).forward(request,response);
③对modify.jsp进行修改,也要修改成post请求
- <%@ page import="com.bjpowernode.oa.bean.Dept" %>
- <%@page contentType="text/html;charset=UTF-8"%>
- html>
- <html>
- <head>
- <meta charset="utf-8">
- <title>修改部门title>
- head>
- <body>
- <h1>修改部门h1>
- <hr >
-
- <%
- Dept dept = (Dept)request.getAttribute("dept");
- %>
-
-
-
- <form action="<%=request.getContextPath()%>/dept/modify" method="post">
- 部门编号<input type="text" name="deptno" value="<%=dept.getDeptno()%>" readonly /><br>
- 部门名称<input type="text" name="dname" value="<%=dept.getDname()%>"/><br>
- 部门位置<input type="text" name="loc" value="<%=dept.getLoc()%>"/><br>
- <input type="submit" value="修改"/><br>
- form>
- body>
- html>
④跳转到/dept/modify,进行数据的更改
- /**
- * 5、根据部门名称,进行修改
- * @param request
- * @param response
- * @throws ServletException
- * @throws IOException
- */
- private void doModify(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
- // 解决请求体的中文乱码问题。
- request.setCharacterEncoding("UTF-8");
-
- // 获取表单中的数据
- String deptno = request.getParameter("deptno");
- String dname = request.getParameter("dname");
- String loc = request.getParameter("loc");
- // 连接数据库执行更新语句
- Connection conn = null;
- PreparedStatement ps = null;
- int count = 0;
- try {
- conn = DBUtil.getCoonetion();
- String sql = "update dept set dname = ?, loc = ? where deptno = ?";
- ps = conn.prepareStatement(sql);
- ps.setString(1, dname);
- ps.setString(2, loc);
- ps.setString(3, deptno);
- count = ps.executeUpdate();
- } catch (SQLException e) {
- e.printStackTrace();
- } finally {
- DBUtil.close(conn, ps, null);
- }
-
- if (count == 1) {
- // 更新成功
- response.sendRedirect(request.getContextPath() + "/dept/list");
- }
- }