赞
踩
实现步骤
第一步:准备一张数据库表(sql脚本)
CREATE TABLE `dept` (
`deptno` int(11) NOT NULL,
`dname` varchar(255) DEFAULT NULL,
`loc` varchar(255) DEFAULT NULL,
PRIMARY KEY (`deptno`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
---
第二步:准备一套HTML页面(项目原型)先把页面项目跑通即可,后面会做功能具体实现
把HTML页面准备好
然后将HTML页面中的链接都能跑通
应该设计那些页面呢?
新增页面:add.html
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>新增部门</title> </head> <body> <h1>新增部门</h1> <hr> <form action="list.html" method="get"> 部门编号<input type="text" name="deptno"><br> 部门名称<input type="text" name="dname"><br> 部门位置<input type="text" name="loc"><br> <input type="submit" value="保存"> </form> </body> </html>
修改页面:edit.html
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>修改部门</title> </head> <body> <h1>修改部门</h1> <hr> <form action="list.html" method="get"> 部门编号<input type="text" name="deptno" value="20"><br> 部门名称<input type="text" name="dname" value="销售部"><br> 部门位置<input type="text" name="loc" value="北京"><br> <input type="submit" value="保存"> </form> </body> </html>
查看详情页面:detail.html
<!DOCTYPE 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>
欢迎页面(首页面):index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>欢迎使用OA系统</title>
</head>
<body>
<a href="list.html">查看部门列表</a>
</body>
</html>
列表页面:list.html
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>部门列表</title> </head> <body> <h1 align="center">部门列表</h1> <hr> <table border="1px" align="center" width="50%"> <tr> <th>序号</th> <th>部门编号</th> <th>部门名称</th> <th>操作</th> </tr> <tr> <td>1</td> <td>10</td> <td>销售部</td> <td> <a href="">删除</a> <a href="edit.html">修改</a> <a href="detail.html">详情</a> </td> </tr> <tr> <td>2</td> <td>20</td> <td>研发部</td> <td> <a href="">删除</a> <a href="edit.html">修改</a> <a href="detail.html">详情</a> </td> </tr> <tr> <td>3</td> <td>30</td> <td>运营部</td> <td> <a href="">删除</a> <a href="edit.html">修改</a> <a href="detail.html">详情</a> </td> </tr> </table> <hr> <a href="add.html">新增部门</a> </body> </html>
第三步:分析我们这个系统包括了哪些功能?
第四步:在IDEA当中搭建开发环境
创建一个webapp(给这个webapp添加servlet-api.jar和jsp-api.jar)
向webapp中添加数据库jar包(MySQL驱动)
JDBC的工具类
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XM9ynL2H-1688370813817)(C:\Users\26332\AppData\Roaming\Typora\typora-user-images\9.png)]
//配置文件信息
driver=con.musql.jdbc.Driver
url=jdbc:mysql://localhost:3306/javaweb
user=root
password=123456
package ServletProject.utils; import java.beans.Statement; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ResourceBundle; /* * JDBC的工具类 * */ public class DButil { //静态变量,在类加载时执行 private static ResourceBundle bundle=ResourceBundle.getBundle("resources.jdbc");//绑定资源文件 //根据属性配置文件的key配置value private static String driver=bundle.getString("driver"); private static String url=bundle.getString("url"); private static String user=bundle.getString("user"); private static String password=bundle.getString("password"); static { //注册驱动,执行一次即可,放在静态代码块当中,类加载时执行 try{ //"com.mysql.jdbc.Driver"是链接数据库的驱动,不能写死,因为以后可能会链接Oracle数据库,以防修改Java源代码,保证项目正常。 Class.forName(driver); }catch (ClassNotFoundException e){ e.printStackTrace(); } } //获取数据库链接对象 public static Connection getConnection() throws SQLException { //获取链接 Connection conn= DriverManager.getConnection(url,user,password); return conn; } //释放资源 public static void close(Connection conn, Statement ps, ResultSet rs){ if (rs!=null){ try { rs.close(); }catch (SQLException e){ e.printStackTrace(); } } if (ps!=null){ try { ps.close(); }catch (SQLException e){ e.printStackTrace(); } } if (conn!=null){ try { conn.close(); }catch (SQLException e){ e.printStackTrace(); } } } }
第五步:实现第一个功能:查看部门列表
第一:先修改前端欢迎页面的超链接,因为用户先点击的就是这个超链接
<!-- 前端超链接发送请求的时候,请求路径以/开始,并且要带着项目名-->
<a href="/ServletProject/dept/list">查看部门列表</a>
第二:编写web.xm文件
<servlet>
<servlet-name>list</servlet-name>
<servlet-class>????</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>list</servlet-name>
<url-pattern>/dept/list</url-pattern>
</servlet-mapping>
第三:编写DeptListServlet类继承HttpServlet类,然后重写doGet方法
package action; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServlet; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; public class DeptListServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } }
第四:在DeptListServlet类的doGet方法中链接数据库,查询所有的部门,动态展示部门列表页面
分析list.html页面那部分是固定死的,那部分是变化的
package action; //查看部门列表功能实现 import ServletProject.utils.DButil; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServlet; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; public class DeptListServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html"); PrintWriter out= response.getWriter(); out.print(" <!DOCTYPE html>"); out.print("<html>"); out.print(" <head>"); out.print(" <meta charset='utf-8'>"); out.print(" <title>部门列表</title>"); out.print(" </head>"); out.print(" <body>"); out.print(" <h1 align='center'>部门列表</h1>"); out.print(" <hr>"); out.print(" <table border='1px' align='center' width='50%'>"); out.print(" <tr>"); out.print(" <th>序号</th>"); out.print(" <th>部门编号</th>"); out.print(" <th>部门名称</th>"); out.print(" <th>操作</th>"); out.print(" </tr>"); //连接数据库,查询所有的部门 Connection conn=null; PreparedStatement ps=null; ResultSet rs=null; try { conn=DButil.getConnection(); String sql="select deptno,dname,loc from dept"; ps=conn.prepareStatement(sql); rs= ps.executeQuery(); int i=0; //获取到的数据库数据 while (rs.next()){ String deptno=rs.getString("deptno"); String dname=rs.getString("dname"); String loc=rs.getString("loc"); out.print(" <tr>"); out.print(" <td>"+(++i)+"</td>"); out.print(" <td>"+deptno+"</td>"); out.print(" <td>"+dname+"</td>"); out.print(" <td>"); out.print(" <a href=''>删除</a>"); out.print(" <a href='edit.html'>修改</a>"); out.print(" <a href='detail.html'>详情</a>"); out.print(" </td>"); out.print(" </tr>"); } } catch (SQLException throwables) { throwables.printStackTrace(); }finally { //释放资源 DButil.close(conn,ps,rs); } out.print(" </table>"); out.print(" <hr>"); out.print(" <a href='add.html'>新增部门</a>"); out.print(" </body>"); out.print("</html>"); } }
现在写完这个功能之后,你会有一种感觉,感觉开发很繁琐,只写servlet代码太麻烦了
第六步:实现查看部门详情功能(从前端往后端一步一步实现)
首先要考虑的是,用户点击的是什么?用户点击的东西在哪里?
一定要先找到用户点的“详情”在哪里,在Java程序中找到了
<a href='/ServletProject/dept/detail'>详情</a>
详情这里是需要连接数据库的,所以这个超链接点击之后也是需要执行一段Java代码的,所以这里的超链接路径是servlet对象
注意:修改路径之后,这个路径是需要加项目名的(前端向后端发送请求需要加项目名)
又因为根路径可以动态获取,所以这里可以更改为:
//获取应用的根路径
String contextPath = request.getContextPath();
<a href='"+contextPath+"/dept/detail'>详情</a>
又又因为详情需要有判断具体是那个部门的详情,所以在发送请求的时候可以把部门编号发送给后端,后端通过数据库来选出相应的部门信息:
<a href='"+contextPath+"/dept/detail?"+deptno+"'>详情</a>
接下来就需要完成该功能的servlet对象就行了:
编写一个DeptDetailServlet继承HttpServlet,重写doGet方法,在该方法中连接数据库,查询相应部门信息
package action; import ServletProject.utils.DButil; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServlet; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; public class DeptDetailServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //获取请求中url的部门编号 String deptno=request.getParameter("deptno"); response.setContentType("text/html"); PrintWriter out = response.getWriter(); out.print(" <!DOCTYPE html>"); out.print("<html>"); out.print(" <head>"); out.print(" <meta charset='utf-8'>"); out.print(" <title>部门详情</title>"); out.print(" </head>"); out.print(" <body>"); out.print(" <h1>部门详情</h1>"); out.print(" <hr>"); out.print(" 部门编号:"+deptno+" <br />"); //连接数据库,根据部门编号查询信息 Connection conn=null; PreparedStatement ps=null; ResultSet rs=null; try { conn= DButil.getConnection(); String sql="select deptno,dname,loc from dept where deptno=?"; ps=conn.prepareStatement(sql); ps.setString(1,deptno); rs= ps.executeQuery(); if (rs.next()){ String dname= rs.getString("dname"); String loc=rs.getString("loc"); out.print(" 部门名称:"+dname+"<br />"); out.print(" 部门位置:"+loc+"<br />"); } } catch (SQLException throwables) { throwables.printStackTrace(); }finally { DButil.close(conn,ps,rs); } out.print(" <input type='button' value='后退' οnclick='window.history.back()'>"); out.print(" </body>"); out.print("</html>"); } }
第七步:删除功能
怎么开始?从哪开始?从前端页面开始,用户点击删除按钮,提示用户是否删除
<a href='javascript:void(0)' onclick='del("+deptno+")'>删除</a>
out.print(" <script type='text/javascript'>");
out.print(" function del(dno){");
out.print(" if (window.confirm('亲,删了就不能恢复了哦')){");
out.print(" document.location.href='/ServletProject/dept/delete?deptno='+dno");
out.print(" }");
out.print(" }");
out.print(" </script>");
以上的前端程序要写到后端的Java代码当中
删除功能servlet对象代码
package action; import ServletProject.utils.DButil; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServlet; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; public class DeptDeleteServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String deptno=request.getParameter("deptno"); response.setContentType("text/html"); PrintWriter out = response.getWriter(); int count=0; Connection conn=null; PreparedStatement ps=null; try { conn=DButil.getConnection(); //开启事务 conn.setAutoCommit(false); String sql ="delete from dept where deptno=?"; ps=conn.prepareStatement(sql); ps.setString(1,deptno); //返回值是影响了数据库几行数据的结果 count=ps.executeUpdate(); //事务提交 conn.commit(); } catch (SQLException throwables) { //遇到异常回滚 if (conn!=null){ try { conn.rollback(); } catch (SQLException e) { e.printStackTrace(); } } }finally { DButil.close(conn,ps,null); } if (count==1){ //删除成功,回到列表页面 //目前使用转发 request.getRequestDispatcher("/dept/list").forward(request,response); }else { //删除失败 } } }
第八步:新增部门
package action; import ServletProject.utils.DButil; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServlet; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; public class DeptSaveServlet extends HttpServlet { @Override protected void doPost(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"); //连接数据库执行插入语句 Connection conn=null; PreparedStatement ps=null; ResultSet rs=null; int count=0; try { conn=DButil.getConnection(); String sql="INSERT INTO dept (deptno, dname, loc) VALUES ('"+deptno+"', '"+dname+"', '"+loc+"')"; ps=conn.prepareStatement(sql); count=ps.executeUpdate(); } catch (SQLException throwables) { throwables.printStackTrace(); }finally { DButil.close(conn,ps,rs); } if (count==1){ //保存成功跳转到列表页面 //转发是一次请求,之前是post请求,后面也是post请求,转发的下一个servlet对象只有doget方法,所以会报405错误 //解决这个错误的暂时的方法是在list对象中写一个dopost方法,该方法调用doget方法 request.getRequestDispatcher("/dept/list").forward(request,response); }else { //保存失败跳转到错误页面 } } }
第九步:跳转到修改部门的界面
package action; import ServletProject.utils.DButil; import jakarta.servlet.RequestDispatcher; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServlet; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; public class DeptEditServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //获取部门编号 String deptno = request.getParameter("deptno"); response.setContentType("text/html"); PrintWriter out = response.getWriter(); Connection conn=null; PreparedStatement ps=null; ResultSet rs=null; out.print(" <!DOCTYPE html>"); out.print("<html>"); out.print(" <head>"); out.print(" <meta charset='utf-8'>"); out.print(" <title>修改部门</title>"); out.print(" </head>"); out.print(" <body>"); out.print(" <h1>修改部门</h1>"); out.print(" <hr>"); out.print(" <form action='/dept/list' method='post'>"); out.print(" 部门编号<input type='text'' name='deptno' value='"+deptno+"'><br>"); try { conn= DButil.getConnection(); String sql="select deptno,dname,loc from dept where deptno=?"; ps=conn.prepareStatement(sql); ps.setString(1,deptno); rs=ps.executeQuery(); if (rs.next()){ String dname=rs.getString("dname"); String loc=rs.getString("loc"); out.print(" 部门名称<input type='text'' name='dname'' value='"+dname+"'><br>"); out.print(" 部门位置<input type='text' name='loc' value='"+loc+"'><br>"); String sql1="INSERT INTO dept (deptno, dname, loc) VALUES ('"+deptno+"', '"+dname+"', '"+loc+"')"; } } catch (SQLException throwables) { throwables.printStackTrace(); }finally { DButil.close(conn,ps,rs); } out.print(" <input type='submit'' value='保存'>"); out.print(" </form>"); out.print(" </body>"); out.print("</html>"); } }
第十步:修改部门功能实现
package action; import ServletProject.utils.DButil; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServlet; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; public class DeptModifyServlet extends HttpServlet { @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("UTF-8"); response.setContentType("text/html"); PrintWriter out = response.getWriter(); //获取修改表单的数据 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.getConnection(); 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 throwables) { throwables.printStackTrace(); }finally { DButil.close(conn,ps,null); } if (count==1){ //更新成功,返回list页面 request.getRequestDispatcher("/dept/list").forward(request,response); } } }
注意犯得一个错误:
String sql="update dept set dname=?,loc=? where deptno=?";
ps=conn.prepareStatement(sql);//这一句要写在下面三句前面,否则无法执行成功,浏览器报500错误
ps.setString(1,dname);
ps.setString(2,loc);
ps.setString(3,deptno);
在一web应用中有两种方式完成资源的跳转:
转发:在一次请求中,像是通过当前网页加载到要跳转的网页,请求资源不变(张三问李四借钱,李四没钱就向王五借了钱,然后李四把借到的钱再借给张三)
request.getRequestDispatcher("/dept/list").forward(request,response);
重定向:不在一次请求中,像当前网页告诉web应用它像进入的网页的url,然后web应用再通过该网址加载到目标网页(张三问李四借钱,李四没钱,就告诉张三,王五有钱,然后张三就直接向王五借到钱)
response.sendRedirect(request.getContextPath()+"/dept/list");
分析项目中的web.xml文件
Servlet3.0版本之后,推出了各种Servlet基于注解开发
优点:开发效率高,不要编写大量配置信息。
有一些需要改变的信息,还是要配置到web.xml文件。
XML文件的内容
<servlet>
<servlet-name>delete</servlet-name>
<servlet-class>action.DeptDeleteServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>delete</servlet-name>
<url-pattern>/dept/delete</url-pattern>
</servlet-mapping>
我们的第一个注解:
import jakarta.servlet.annotation.WebServlet;
在Servlet类上使用:@WebServlet,WebSevlet注解中有哪些属性呢?
name属性:用来指定Servlet的名字,等同于delete
urlPatterns属性:用来指定Servlet的映射路径,可以指定多个字符串,等同于/dept/delete
loadOnStartup属性:用来指定在服务器启动阶段是否加载该Servlet,等同于
value属性,等同于urlPatterns,在此以上还可以省略value不写**@WebServlet(“/url”)**
package servlet; import jakarta.servlet.ServletException; import jakarta.servlet.annotation.WebInitParam; import jakarta.servlet.annotation.WebServlet; import jakarta.servlet.http.HttpServlet; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; @WebServlet(name="hello",urlPatterns = {"/hello1","/hello2"},loadOnStartup = 1, initParams = {@WebInitParam(name="username",value ="root"),@WebInitParam(name = "password",value = "123456")}) public class HelloServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { } }
注解对象使用格式:
上面的注解解决了配置文件的问题,但是现在项目仍然存在一个比较臃肿的问题:
怎么解决类爆炸问题?
package action; import jakarta.servlet.ServletException; import jakarta.servlet.annotation.WebServlet; import jakarta.servlet.http.HttpServlet; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import utils.DButil; import java.io.IOException; import java.io.PrintWriter; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; @WebServlet({"/dept/list","/dept/save","/dept/edit","/dept/detail","/dept/delete","/dept/modify"}) 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); }else if ("/dept/save".equals(servletPath)){ doSave(request,response); }else if ("/dept/edit".equals(servletPath)){ doEdit(request,response); }else if ("/dept/detail".equals(servletPath)){ doDetail(request,response); }else if ("/dept/delete".equals(servletPath)){ doDel(request,response); }else if ("/dept/modify".equals(servletPath)){ doModify(request,response); } } private void doModify(HttpServletRequest request, HttpServletResponse response) throws IOException { request.setCharacterEncoding("UTF-8"); response.setContentType("text/html"); PrintWriter out = response.getWriter(); //获取修改表单的数据 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.getConnection(); 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 throwables) { throwables.printStackTrace(); }finally { DButil.close(conn,ps,null); } if (count==1){ //更新成功,返回list页面 response.sendRedirect(request.getContextPath()+"/dept/list"); } } private void doDetail(HttpServletRequest request, HttpServletResponse response) throws IOException { //获取请求中url的部门编号 String deptno=request.getParameter("deptno"); response.setContentType("text/html"); PrintWriter out = response.getWriter(); out.print(" <!DOCTYPE html>"); out.print("<html>"); out.print(" <head>"); out.print(" <meta charset='utf-8'>"); out.print(" <title>部门详情</title>"); out.print(" </head>"); out.print(" <body>"); out.print(" <h1>部门详情</h1>"); out.print(" <hr>"); out.print(" 部门编号:"+deptno+" <br />"); //连接数据库,根据部门编号查询信息 Connection conn=null; PreparedStatement ps=null; ResultSet rs=null; try { conn= DButil.getConnection(); String sql="select deptno,dname,loc from dept where deptno=?"; ps=conn.prepareStatement(sql); ps.setString(1,deptno); rs= ps.executeQuery(); if (rs.next()){ String dname= rs.getString("dname"); String loc=rs.getString("loc"); out.print(" 部门名称:"+dname+"<br />"); out.print(" 部门位置:"+loc+"<br />"); } } catch (SQLException throwables) { throwables.printStackTrace(); }finally { DButil.close(conn,ps,rs); } out.print(" <input type='button' value='后退' οnclick='window.history.back()'>"); out.print(" </body>"); out.print("</html>"); } private void doEdit(HttpServletRequest request, HttpServletResponse response) throws IOException { //获取部门编号 String deptno = request.getParameter("deptno"); //获取根路径 String contextPath = request.getContextPath(); response.setContentType("text/html"); PrintWriter out = response.getWriter(); Connection conn=null; PreparedStatement ps=null; ResultSet rs=null; out.print(" <!DOCTYPE html>"); out.print("<html>"); out.print(" <head>"); out.print(" <meta charset='utf-8'>"); out.print(" <title>修改部门</title>"); out.print(" </head>"); out.print(" <body>"); out.print(" <h1>修改部门</h1>"); out.print(" <hr>"); out.print(" <form action='"+contextPath+"/dept/modify' method='post'>"); out.print(" 部门编号<input type='text'' name='deptno' value='"+deptno+"'><br>"); try { conn= DButil.getConnection(); String sql="select deptno,dname,loc from dept where deptno=?"; ps=conn.prepareStatement(sql); ps.setString(1,deptno); rs=ps.executeQuery(); if (rs.next()){ String dname=rs.getString("dname"); String loc=rs.getString("loc"); out.print(" 部门名称<input type='text'' name='dname'' value='"+dname+"'><br>"); out.print(" 部门位置<input type='text' name='loc' value='"+loc+"'><br>"); } } catch (SQLException throwables) { throwables.printStackTrace(); }finally { DButil.close(conn,ps,rs); } out.print(" <input type='submit'' value='保存'>"); out.print(" </form>"); out.print(" </body>"); out.print("</html>"); } private void doSave(HttpServletRequest request, HttpServletResponse response) throws IOException { //获取部门信息 //注意乱码问题(tomcat10不会出现) 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; ResultSet rs=null; int count=0; try { conn=DButil.getConnection(); String sql="INSERT INTO dept (deptno, dname, loc) VALUES ('"+deptno+"', '"+dname+"', '"+loc+"')"; ps=conn.prepareStatement(sql); count=ps.executeUpdate(); } catch (SQLException throwables) { throwables.printStackTrace(); }finally { DButil.close(conn,ps,rs); } if (count==1){ //保存成功跳转到列表页面 //转发是一次请求,之前是post请求,后面也是post请求,转发的下一个servlet对象只有doget方法,所以会报405错误 //解决这个错误的暂时的方法是在list对象中写一个dopost方法,该方法调用doget方法 response.sendRedirect(request.getContextPath()+"/dept/list"); }else { //保存失败跳转到错误页面 } } private void doList(HttpServletRequest request, HttpServletResponse response) throws IOException { //获取应用的根路径 String contextPath = request.getContextPath(); response.setContentType("text/html"); PrintWriter out= response.getWriter(); out.print(" <!DOCTYPE html>"); out.print("<html>"); out.print(" <head>"); out.print(" <meta charset='utf-8'>"); out.print(" <title>部门列表</title>"); out.print(" <script type='text/javascript'>"); out.print(" function del(dno){"); out.print(" if (window.confirm('亲,删了就不能恢复了哦')){"); out.print(" document.location.href='/ServletProject/dept/delete?deptno='+dno"); out.print(" }"); out.print(" }"); out.print(" </script>"); out.print(" </head>"); out.print(" <body>"); out.print(" <h1 align='center'>部门列表</h1>"); out.print(" <hr>"); out.print(" <table border='1px' align='center' width='50%'>"); out.print(" <tr>"); out.print(" <th>序号</th>"); out.print(" <th>部门编号</th>"); out.print(" <th>部门名称</th>"); out.print(" <th>操作</th>"); out.print(" </tr>"); //连接数据库,查询所有的部门 Connection conn=null; PreparedStatement ps=null; ResultSet rs=null; try { conn=DButil.getConnection(); String sql="select deptno,dname,loc from dept"; ps=conn.prepareStatement(sql); rs= ps.executeQuery(); int i=0; //获取到的数据库数据 while (rs.next()){ String deptno=rs.getString("deptno"); String dname=rs.getString("dname"); String loc=rs.getString("loc"); out.print(" <tr>"); out.print(" <td>"+(++i)+"</td>"); out.print(" <td>"+deptno+"</td>"); out.print(" <td>"+dname+"</td>"); out.print(" <td>"); out.print(" <a href='javascript:void(0)' οnclick='del("+deptno+")'>删除</a>"); out.print(" <a href='"+contextPath+"/dept/edit?deptno="+deptno+"'>修改</a>"); out.print(" <a href='"+contextPath+"/dept/detail?deptno="+deptno+"'>详情</a>"); out.print(" </td>"); out.print(" </tr>"); } } catch (SQLException throwables) { throwables.printStackTrace(); }finally { //释放资源 DButil.close(conn,ps,rs); } out.print(" </table>"); out.print(" <hr>"); out.print(" <a href='"+contextPath+"/add.html'>新增部门</a>"); out.print(" </body>"); out.print("</html>"); } private void doDel(HttpServletRequest request, HttpServletResponse response) throws IOException{ String deptno=request.getParameter("deptno"); response.setContentType("text/html"); PrintWriter out = response.getWriter(); int count=0; Connection conn=null; PreparedStatement ps=null; try { conn=DButil.getConnection(); //开启事务 conn.setAutoCommit(false); String sql ="delete from dept where deptno=?"; ps=conn.prepareStatement(sql); ps.setString(1,deptno); //返回值是影响了数据库几行数据的结果 count=ps.executeUpdate(); //事务提交 conn.commit(); } catch (SQLException throwables) { //遇到异常回滚 if (conn!=null){ try { conn.rollback(); } catch (SQLException e) { e.printStackTrace(); } } }finally { DButil.close(conn,ps,null); } if (count==1){ //删除成功,回到列表页面 response.sendRedirect(request.getContextPath()+"/dept/list"); }else { //删除失败 } } }
什么是会话:
在Java的servlet规范中,session对应的类名:HttpSession()
session机制属于B/S结构的一部分:如果使用php语言开发web项目也有这个机制
session对象最主要的作用是:保存会话状态(用户登陆成功了,这是一种登陆成功的状态,你怎么把登陆成功的状态一直抱持,使用session对象可以保留会话状态)
为什么要session对象来保存会话状态?
打开一个浏览器发送请求,分配一个session对象,在同一浏览器下再次发送请求,同样时这一个session对象,直至浏览器关闭,重新打开,或者打开其他的浏览器发送请求。
为什么不使用request对象保存会话状态?为什么不使用ServletContext对象保存会话状态?
session对象的实现原理:
HttpSession session = request.getSession();
这段代码很神奇,为什么每个人访问的都是自己的session?
session对象什么时候销毁:
session对象怎么获取:
session的实现原理:
//在web.xml文件中设置session超时时间
<session-config>
<session-timeout>20</session-timeout>
</session-config>
Cookie禁用了,session还能找到吗?
总结一下目前我们所了解的域对象:
request请求域(HttpServletRequest)<session(HttpSession)<application域(ServletContext)
他们三个域都有一下三个公共方法:setAttribute,getAttribute,removeAttribute,向域当中绑定数据及管理数据
session掌握之后,怎么解决项目中的登录问题,怎么让登录起作用?
登录成功后,将用户的登录信息存储到session当中。也就是说session中如果有用户的信息就代表用户登录成功了。
注意:在jsp中会默认创建一个session,所以在获取session对象时只判断是否存在session对象是不能判断登录成功,如果想访问jsp不自动生成session,则可以添加这样一条语句:
<%--访问jsp的时候不生成session对象--%>
<%@page session="false" %>
package action; import jakarta.servlet.ServletException; import jakarta.servlet.annotation.WebServlet; import jakarta.servlet.http.HttpServlet; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpSession; import utils.DButil; import java.io.IOException; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; @WebServlet("/dept/login") public class UserServlet extends HttpServlet { @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //验证用户名和密码是否正确 //获取用户名和密码 String username = request.getParameter("username"); String password = request.getParameter("password"); //链接数据库验证 Connection conn=null; PreparedStatement ps=null; ResultSet rs=null; int count=0; try { conn=DButil.getConnection(); String sql="select * from users where username=? and password=?"; ps=conn.prepareStatement(sql); ps.setString(1,username); ps.setString(2,password); rs=ps.executeQuery(); if (rs.next()){ count=1; } } catch (SQLException throwables) { throwables.printStackTrace(); }finally { DButil.close(conn,ps,rs); } if (count==1){ //登陆成功 //获取session对象 HttpSession session = request.getSession(); session.setAttribute("username",username); response.sendRedirect(request.getContextPath()+"/dept/list"); }else { response.setContentType("text/html"); System.out.println("登陆失败"); } } }
package action; import bean.Dept; import jakarta.servlet.ServletException; import jakarta.servlet.annotation.WebServlet; import jakarta.servlet.http.HttpServlet; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpSession; import utils.DButil; import java.io.IOException; import java.io.PrintWriter; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; @WebServlet({"/dept/list","/dept/save","/dept/edit","/dept/detail","/dept/delete","/dept/modify"}) public class DeptServlet extends HttpServlet { @Override protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //获取session,不需要新建,只是获取当前session HttpSession session = request.getSession(false); if (session != null && session.getAttribute("username") != null) { //获取Servlet Path String servletPath = request.getServletPath(); if ("/dept/list".equals(servletPath)) { doList(request, response); }/*else if ("/dept/save".equals(servletPath)){ doSave(request,response); }else if ("/dept/edit".equals(servletPath)){ doEdit(request,response); }else if ("/dept/detail".equals(servletPath)){ doDetail(request,response); }else if ("/dept/delete".equals(servletPath)){ doDel(request,response); }else if ("/dept/modify".equals(servletPath)){ doModify(request,response); }*/ } } private void doList(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { //获取应用的根路径 String contextPath = request.getContextPath(); //设置一个存放部门信息的集合 List<Dept> depts=new ArrayList(); //连接数据库,查询所有的部门 Connection conn=null; PreparedStatement ps=null; ResultSet rs=null; try { conn=DButil.getConnection(); String sql="select deptno,dname,loc from dept"; ps=conn.prepareStatement(sql); rs= ps.executeQuery(); int i=0; //获取到的数据库数据 while (rs.next()){ String deptno=rs.getString("deptno"); String dname=rs.getString("dname"); String loc=rs.getString("loc"); //将以上零散的数据封装成Java对象,并装入集合再通过请求域提交到jsp文件 Dept dept=new Dept(); dept.setDeptno(deptno); dept.setDname(dname); dept.setLoc(loc); depts.add(dept); } } catch (SQLException throwables) { throwables.printStackTrace(); }finally { //释放资源 DButil.close(conn,ps,rs); } //将集合放入请求域 request.setAttribute("deptList",depts); //转发(不能重定向,因为重定向是不同的请求,请求域存放的信息不能传给其他使用) request.getRequestDispatcher("/list.jsp").forward(request,response); } private void doModify(HttpServletRequest request, HttpServletResponse response) throws IOException { request.setCharacterEncoding("UTF-8"); response.setContentType("text/html"); PrintWriter out = response.getWriter(); //获取修改表单的数据 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.getConnection(); 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 throwables) { throwables.printStackTrace(); }finally { DButil.close(conn,ps,null); } if (count==1){ //更新成功,返回list页面 response.sendRedirect(request.getContextPath()+"/dept/list"); } } private void doDetail(HttpServletRequest request, HttpServletResponse response) throws IOException { //获取请求中url的部门编号 String deptno=request.getParameter("deptno"); response.setContentType("text/html"); PrintWriter out = response.getWriter(); out.print(" <!DOCTYPE html>"); out.print("<html>"); out.print(" <head>"); out.print(" <meta charset='utf-8'>"); out.print(" <title>部门详情</title>"); out.print(" </head>"); out.print(" <body>"); out.print(" <h1>部门详情</h1>"); out.print(" <hr>"); out.print(" 部门编号:"+deptno+" <br />"); //连接数据库,根据部门编号查询信息 Connection conn=null; PreparedStatement ps=null; ResultSet rs=null; try { conn= DButil.getConnection(); String sql="select deptno,dname,loc from dept where deptno=?"; ps=conn.prepareStatement(sql); ps.setString(1,deptno); rs= ps.executeQuery(); if (rs.next()){ String dname= rs.getString("dname"); String loc=rs.getString("loc"); out.print(" 部门名称:"+dname+"<br />"); out.print(" 部门位置:"+loc+"<br />"); } } catch (SQLException throwables) { throwables.printStackTrace(); }finally { DButil.close(conn,ps,rs); } out.print(" <input type='button' value='后退' οnclick='window.history.back()'>"); out.print(" </body>"); out.print("</html>"); } private void doEdit(HttpServletRequest request, HttpServletResponse response) throws IOException { //获取部门编号 String deptno = request.getParameter("deptno"); //获取根路径 String contextPath = request.getContextPath(); response.setContentType("text/html"); PrintWriter out = response.getWriter(); Connection conn=null; PreparedStatement ps=null; ResultSet rs=null; out.print(" <!DOCTYPE html>"); out.print("<html>"); out.print(" <head>"); out.print(" <meta charset='utf-8'>"); out.print(" <title>修改部门</title>"); out.print(" </head>"); out.print(" <body>"); out.print(" <h1>修改部门</h1>"); out.print(" <hr>"); out.print(" <form action='"+contextPath+"/dept/modify' method='post'>"); out.print(" 部门编号<input type='text'' name='deptno' value='"+deptno+"'><br>"); try { conn= DButil.getConnection(); String sql="select deptno,dname,loc from dept where deptno=?"; ps=conn.prepareStatement(sql); ps.setString(1,deptno); rs=ps.executeQuery(); if (rs.next()){ String dname=rs.getString("dname"); String loc=rs.getString("loc"); out.print(" 部门名称<input type='text'' name='dname'' value='"+dname+"'><br>"); out.print(" 部门位置<input type='text' name='loc' value='"+loc+"'><br>"); } } catch (SQLException throwables) { throwables.printStackTrace(); }finally { DButil.close(conn,ps,rs); } out.print(" <input type='submit'' value='保存'>"); out.print(" </form>"); out.print(" </body>"); out.print("</html>"); } private void doSave(HttpServletRequest request, HttpServletResponse response) throws IOException { //获取部门信息 //注意乱码问题(tomcat10不会出现) 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; ResultSet rs=null; int count=0; try { conn=DButil.getConnection(); String sql="INSERT INTO dept (deptno, dname, loc) VALUES ('"+deptno+"', '"+dname+"', '"+loc+"')"; ps=conn.prepareStatement(sql); count=ps.executeUpdate(); } catch (SQLException throwables) { throwables.printStackTrace(); }finally { DButil.close(conn,ps,rs); } if (count==1){ //保存成功跳转到列表页面 //转发是一次请求,之前是post请求,后面也是post请求,转发的下一个servlet对象只有doget方法,所以会报405错误 //解决这个错误的暂时的方法是在list对象中写一个dopost方法,该方法调用doget方法 response.sendRedirect(request.getContextPath()+"/dept/list"); }else { //保存失败跳转到错误页面 } } private void doDel(HttpServletRequest request, HttpServletResponse response) throws IOException{ String deptno=request.getParameter("deptno"); response.setContentType("text/html"); PrintWriter out = response.getWriter(); int count=0; Connection conn=null; PreparedStatement ps=null; try { conn=DButil.getConnection(); //开启事务 conn.setAutoCommit(false); String sql ="delete from dept where deptno=?"; ps=conn.prepareStatement(sql); ps.setString(1,deptno); //返回值是影响了数据库几行数据的结果 count=ps.executeUpdate(); //事务提交 conn.commit(); } catch (SQLException throwables) { //遇到异常回滚 if (conn!=null){ try { conn.rollback(); } catch (SQLException e) { e.printStackTrace(); } } }finally { DButil.close(conn,ps,null); } if (count==1){ //删除成功,回到列表页面 response.sendRedirect(request.getContextPath()+"/dept/list"); }else { //删除失败 } } }
<%@ page import="java.util.List" %> <%@ page import="bean.Dept" %> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>部门列表</title> </head> <body> <h1>欢迎<%=session.getAttribute("username")%></h1> <h1 align="center">部门列表</h1> <hr> <table border="1px" align="center" width="50%"> <tr> <th>序号</th> <th>部门编号</th> <th>部门名称</th> <th>操作</th> </tr> <% //从request取集合 List<Dept> deptList = (List) request.getAttribute("deptList"); int i=0; for (Dept dept:deptList){ %> <tr> <td><%=++i%></td> <td><%=dept.getDeptno()%>></td> <td><%=dept.getDname()%>></td> <td> <a href="">删除</a> <a href="<%=request.getContextPath()%>/edit.jsp">修改</a> <a href="<%=request.getContextPath()%>/detail.jsp">详情</a> </td> </tr> <% } %> </table> <hr> <a href="<%=request.getContextPath()%>/add.jsp">新增部门</a> </body> </html>
项目增加一个安全退出(手动销毁session对象)
private void doLOginout(HttpServletRequest request, HttpServletResponse response) throws IOException {
//获取session对象,销毁session
HttpSession session = request.getSession();
if (session!=null){
//手动销session对象
session.invalidate();
//跳转到登陆页面
response.sendRedirect(request.getContextPath());
session的实现原理中,每一个session对象都会关联一个sessionId,例如:
cookie怎么生成?保存在什么地方?有什么用?什么时候发送cookie?发送哪些cookie?
cookie的经典案例:
cookie和session机制都不属于Java的机制,实际上是HTTP协议的一部分。
HTTP协议中规定:然后一个cookie都是由name和value组成的,name和value都是字符串类型。
在Java的servlet中,对cookie提供了哪些支持呢?
关于cookie的path,cookie关联的路径:(只要路径正确,浏览器就会自动发送cookie给服务器)
假设现在发送的请求路径是“localhost:8080/Servlet_cookie/servletcookie”生成的路径,如果cookie没有设置path,默认的path是什么?
手动设置cookie的path
cookie.setPath("/Servlet-cookie");//表示只要是这个Servlet-cookie项目的请求路径,都会提交cookie给浏览器
浏览器发送cookie给服务器,服务器的Java程序怎么接收?
Cookie[] cookies=request.getCookies();
使用Cookie实现十天免登录功能:
Cookie使用方法:
//创建cookie对象存储用户账号密码 Cookie cookie1 = new Cookie("username", username); Cookie cookie2 = new Cookie("password", password); //设置cookie有效期10天 cookie1.setMaxAge(60*60*24*10); cookie2.setMaxAge(60*60*24*10); //设置cookie的path cookie1.setPath(request.getContextPath()); cookie2.setPath(request.getContextPath()); //响应cookie给浏览器 response.addCookie(cookie1); response.addCookie(cookie2); //获取cookie Cookie[] cookies = request.getCookies(); String username=null; String password=null; if (cookies!=null){ for (Cookie cookie : cookies) { String name = cookie.getName(); if ("username".equals(name)){ username = cookie.getValue(); }else if ("password".equals(name)){ password = cookie.getValue(); } } }
jsp的底层原理:
JSP实际上就是一个Servlet
jsp文件第一次访问比较慢,为什么?
jsp的基础语法
在jsp文件中直接编写文字,都会被翻译到哪里?
jsp的page指令,解决响应时的中文乱码问题:
通过page指令来设置响应的内容类型,在内容类型的最后面添加:charset=UTF-8
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
怎么在jsp中编写Java程序:
<%Java语句; %>
//该符号中语句写在service方法里的Java代码
<%System.out.println("hello jsp");%>
在这个符号当中编写的被视为Java程序,被翻译到Servlet类的service方法内部。
在这个符号里写代码,就相当于在Servlet类的service方法里写代码,所以该符号里的代码要遵守方法里代码的书写规范。
jsp中的专业注释:<%–jsp专业注释,不会被翻译到Java源代码中–%>
在同一个jsp当中可以写多个<%%>
<%!Java语句;%> //该符号中语句写在service方法外的Java代码 <%! //成员变量 private String name="hetao"; //静态代码块 static { System.out.println("静态方法执行"); } //方法 public static void m1(){ System.out.println("m1方法执行了"); } %>
<%! %>这个语法基本上不建议用,因为在service方法外写静态变量和实例变量,都会存在线程安全问题,jsp就是servlet,servlet是单例的,多线程并发的环境下,这个静态变量和实例变量一旦有修改操作,必然会存在线程安全问题。
jsp的输出语句:怎么把一个Java变量输出到浏览器?
在<%%>符号里写out.print(“输出的变量”)
直接写在<%= %>符号里
<%-- Created by IntelliJ IDEA. User: 26332 Date: 2023/7/5 Time: 15:40 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <body> <% int a=1; out.print(a); %> <%=a%> </body> </html>
JSP基础语法总结:
JSP中直接编写普通字符串
<% %>
*翻译到service方法体内部,里面是一条条Java语句。
<%= %>
<%= %>
<%@ page contentType=“text/html;charset=UTF-8” language=“java” %>
使用Servlet处理业务,收集数据。
使用JSP展示数据。
将之前原型中的HTML文件全部修改为jsp文件,然后再jsp文件头部添加page指令(指定contextType防止中文乱码,将所有的jsp直接拷贝到web目录下)
完成所有的页面正常跳转。
在Servlet中连接数据库,查询所有的部门,遍历结果集。
遍历所有结果集的过程中,取出部门编号、部门号、位置等信息,封装成Java对象。
将Java对象存放到List集合。
将List集合存储到request域当中。
转发到jsp。
Servlet代码:
@WebServlet({"/dept/list","/dept/save","/dept/edit","/dept/detail","/dept/delete","/dept/modify"}) 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); } private void doList(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { //获取应用的根路径 String contextPath = request.getContextPath(); //设置一个存放部门信息的集合 List<Dept> depts=new ArrayList(); //连接数据库,查询所有的部门 Connection conn=null; PreparedStatement ps=null; ResultSet rs=null; try { conn=DButil.getConnection(); String sql="select deptno,dname,loc from dept"; ps=conn.prepareStatement(sql); rs= ps.executeQuery(); int i=0; //获取到的数据库数据 while (rs.next()){ String deptno=rs.getString("deptno"); String dname=rs.getString("dname"); String loc=rs.getString("loc"); //将以上零散的数据封装成Java对象,并装入集合再通过请求域提交到jsp文件 Dept dept=new Dept(); dept.setDeptno(deptno); dept.setDname(dname); dept.setLoc(loc); depts.add(dept); } } catch (SQLException throwables) { throwables.printStackTrace(); }finally { //释放资源 DButil.close(conn,ps,rs); } //将集合放入请求域 request.setAttribute("deptList",depts); //转发(不能重定向,因为重定向是不同的请求,请求域存放的信息不能传给其他使用) request.getRequestDispatcher("/list.jsp").forward(request,response); }
在jsp中:
从request域当中取出List集合。
遍历List集合,取出每个部门对象,动态生成tr
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>欢迎使用OA系统</title>
</head>
<body>
<a href="<%=request.getContextPath()%>/dept/list">查看部门列表</a>
</body>
</html>
<%@ page import="java.util.List" %> <%@ page import="bean.Dept" %> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>部门列表</title> </head> <body> <h1 align="center">部门列表</h1> <hr> <table border="1px" align="center" width="50%"> <tr> <th>序号</th> <th>部门编号</th> <th>部门名称</th> <th>操作</th> </tr> <% //从request取集合 List<Dept> deptList = (List) request.getAttribute("deptList"); int i=0; for (Dept dept:deptList){ %> <tr> <td><%=++i%></td> <td><%=dept.getDeptno()%>></td> <td><%=dept.getDname()%>></td> <td> <a href="">删除</a> <a href="<%=request.getContextPath()%>/edit.jsp">修改</a> <a href="<%=request.getContextPath()%>/detail.jsp">详情</a> </td> </tr> <% } %> </table> <hr> <a href="<%=request.getContextPath()%>/add.jsp">新增部门</a> </body> </html>
jsp文件的拓展名必须是XXX.jsp吗?
jsp文件的拓展名是可以配置的
在CATALINA_HOME/conf/web.xml,在这个文件当中配置jsp文件的拓展名。
<servlet-mapping>
<servlet-name>jsp</servlet-name>
<url-pattern>*.jsp</url-pattern>
<url-pattern>*.jspx</url-pattern>
</servlet-mapping>
xxx.jsp文件对Tomcat来说就是普通文档,web容器都会将该文件翻译成Java程序,真正执行时,和jsp文件没关系。
当前的项目存在的问题:需要一个登录功能
实现登录功能步骤:
jsp代码 <%@ page contentType="text/html;charset=UTF-8" language="java" %> <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>欢迎使用OA系统</title> </head> <body> <%--<a href="<%=request.getContextPath()%>/dept/list">查看部门列表</a>--%> <h1>用户登录</h1><hr> <form action="<%=request.getContextPath()%>/dept/login" method="post"> username:<input type="text" name="username"><br> password:<input type="password" name="password"><br> <input type="submit" value="登录"> </form> </body> </html>
Servlet代码 package action; import jakarta.servlet.ServletException; import jakarta.servlet.annotation.WebServlet; import jakarta.servlet.http.HttpServlet; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import utils.DButil; import java.io.IOException; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; @WebServlet("/dept/login") public class UserServlet extends HttpServlet { @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //验证用户名和密码是否正确 //获取用户名和密码 String username = request.getParameter("username"); String password = request.getParameter("password"); //链接数据库验证 Connection conn=null; PreparedStatement ps=null; ResultSet rs=null; int count=0; try { conn=DButil.getConnection(); String sql="select * from users where username=? and password=?"; ps=conn.prepareStatement(sql); ps.setString(1,username); ps.setString(2,password); rs=ps.executeQuery(); if (rs.next()){ count=1; } } catch (SQLException throwables) { throwables.printStackTrace(); }finally { DButil.close(conn,ps,rs); } if (count==1){ response.sendRedirect(request.getContextPath()+"/dept/list"); }else { response.setContentType("text/html"); System.out.println("登陆失败"); } } }
指令的作用:指导JSP翻译引擎如何翻译JSP文件
指令包括哪些?
指令的使用语法是什么?
关于page当中都有哪些常用的指令:
//是否启用JSP内置对象session,false表示不启用 <%@page session="false" %> //设置响应的内容类型和响应时的字符集 <%@page contentType="text/html;" pageEncoding="UTF-8" %> //导包 <%@page import="com" %> //当前页面出错就跳转到这个页面,errorPage这个属性用来指定出错之后的跳转位置 <%@page errorPage="2.jsp" %> //跳转到出错页面后,无异常信息,程序员不知道要怎么做,则使用下面的标签和九大内置对象之一,把错误信息打印到控制台 <%@page isErrorPage="true" %> <% exception.printStackTrace(); %>
jakarta.servlet.jsp.PageContext pageContext 页面作用域
jakarta.servlet.http.HttpServletRequest request 请求作用域
jakarta.servlet.http.HttpSession session 会话作用域
jakarta.servlet.ServletContext application 应用作用域
pageContext<request<session<application
以上四个域都有setAttribute、getAttribute、removeAttribute方法。
以上作用域使用原则:尽可能使用小的域
java.lang.Throwable exception
jakarta.servlet.ServletConfig config
java.lang.Object page (其实时this,当前servlet对象)
jakarta.servlet.jsp.JspWriter out (负责输出)
jakarta.servlet.http.HttpServletResponse response (负责响应)
EL表达式是干什么用的?
EL表达式出现在JSP中只要是:
EL表达式很好用,基本的语法格式:
${表达式}
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
//向request作用域存储username为hetao
request.setAttribute("username","hetao");
%>
<%=request.getAttribute("username")%>
<%--使用EL表达式--%>
${username}
EL表达式的使用:
<%@ page import="action.User" %> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <% //创建User对象 User user = new User(); user.setUsername("hetao"); user.setPassword("20021008"); user.setAge(20); //将User对象存储到request域当中(将对象存储到某个域当中,一定要存,因为EL表达式只能从某个范围中取数据) //数据必须存储到四大范围之一 request.setAttribute("userObj",user); %> <%--使用EL表达式,从request域当中,取出User对象,并将其输出到浏览器--%> <%--1、EL表达式会自动从某个范围取出数据。2、将其转换成字符串。3、将其输出到浏览器--%> ${userObj} //输出结果:User{username='hetao', password='20021008', age=20} <br> <%--输出user对象的username属性--%> ${userObj.username} //输出结果:hetao <br> ${userObj.email} //输出结果:hetao //看下面的User类中的getEmail方法 ${"userObj"}和${userObj}的区别: 第一个总结输出字符串userObj,后面的输出User{username='hetao', password='20021008', age=20}
package action; import jakarta.servlet.annotation.WebServlet; public class User { private String username; private String password; private int age; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "User{" + "username='" + username + '\'' + ", password='" + password + '\'' + ", age=" + age + '}'; } public String getEmail(){ return "hetao"; } }
总结:EL表达式中,这个语法实际上就是调用底层的getxxx()方法,如果没有对应的get方法,浏览器就会报500错误。如果同时多个域都有相同名字的变量,EL表达式优先从小域取。
${userObj.username}相当于${userObj["username"]}
加入一个名称为abc.a的要输出,第一种方式输出为空白,第二种方式可以正常输出
版权声明:本文为CSDN博主「代码怎么撕」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/m0_57151612/article/details/123693754
什么是JSTL标签库
使用JSTL标签库的步骤
第一步:引入JSTL标签库对应的jar包
第二步:在JSP中引入需要的标签库(使用taglib指令引入标签库)
JSTL提供了多种标签,你要引入哪个标签???(重点掌握核心标签库)
<%--引入标签库,这里引入的是JSTL的核心标签库--%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
这就是核心标签库
prefix="" 这里随便起一个名字就行了,核心标签库,大家默认的叫做c
url是对应jar包里的东西
第三步:在需要标签的位置使用即可(表面是标签,实际上是Java程序)
JSTL标签的原理
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
以上uri 后面的路径实际上指向了一个xx.tld文件。
tld文件实际上是一个xml配置文件。
在tld文件中描述了“标签”和java类之间的关系。
以上核心标签库对应的tld文件是c.tld文件。
在jakarta.servlet.jsp.jstl-2.0.0.jar里面META-INF目录下,有一个c.tld文件。
源码解析:配置文件tld解析
<tag> <description>对该标签的描述 </description> <name>catch</name> 标签的名字 <tag-class>org.apache.taglibs.standard.tag.common.core.CatchTag</tag-class>标签对应的java类。 <body-content>JSP</body-content>标签体当中可以出现的内容,如果是JSP,就表示标签体重可以出现符合JSP所有语法的代码。例如EL表达式。 <attribute> <description>对这个属性的描述 </description> <name>var</name> 属性名 <required>false</required> false 表示该属性不是必须的。true表示该属性是必须的。 <rtexprvalue>false</rtexprvalue>这个描述说明了该属性是否支持EL表达式。false表示不支持。true表示支持EL表达式。 </attribute> </tag> <c:catch 属性名=“”> JSP... </c:catch>
总结JSTL标签的格式就是:
<库名:标签名 标签中包含的属性名=“”>
其他代码(JSP什么的)
</库名:标签名>
JSTL中的核心标签库core当中有哪些常用的标签呢?
<%--核心库的if标签 test属性是必须的,test属性支持EL表达式 test属性只能是Boolean类型 if标签还有var属性,不是必须的 if标签还有scope属性,用来指定var的存储域,var是保存test属性的值,也不是必须的(四个域) --%> <c:if test="${empty param.username}"> <h1>用户名不能为空</h1> </c:if> <c:if test="${not empty param.username}"> <h1>欢迎您${param.username}</h1> </c:if> <%--存储到request域--%> <c:if test="${not empty param.username}" var="v" scope="request"> <h1>欢迎您${param.username}</h1> </c:if> <%--通过EL表达式将request域当中的v取出--%> ${v}
1. <%-- forEach标签: var用来指定循环中的变量 begin开始 end结束 step步长 底层实际会将i存储到pageContext域当中 --%> <c:forEach var="i" begin="1" end="10" step="1"> ${i}<br> </c:forEach> 2. <%-- forEach标签: 取集合元素 --%> <% List<User> users=new ArrayList<>(); User user=new User(); user.setAge(20); user.setUsername("hetao"); user.setPassword("20021008"); User user1=new User(); user1.setAge(20); user1.setUsername("hetao"); user1.setPassword("20021008"); User user2=new User(); user2.setAge(20); user2.setUsername("hetao"); user2.setPassword("20021008"); users.add(user); users.add(user1); users.add(user2); request.setAttribute("users",users); %> <%--var="s"这个s代表的是集合中的每个User对象--%> <c:forEach items="${users}" var="s"> user:${s.username},password=${s.password},age=${s.age}<br> </c:forEach> 3. <%--varStatus这个属性表示var的状态对象,这里是一个Java对象,这个Java对象代表了var的状态 varStatus=”名字随意“ varStatus这个状态对象有count属性,可以直接使用 --%> <c:forEach items="${users}" var="s" varStatus="userStatus"> <%--主要用于编号,从1递增--%> 编号:${userStatus.count}, user:${s.username},password=${s.password},age=${s.age}<br> </c:forEach>
<%--
相当于if else
--%>
<c:choose>
<c:when test="${param.age<18}">青少年</c:when>
<c:when test="${param.age<35}">青年</c:when>
<c:when test="${param.age<55}">中年</c:when>
<c:otherwise>老年</c:otherwise>
</c:choose>
拓展:HTML头部的标签,可以用来设置根路径
当前的项目有什么缺陷?
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sjuMoGDt-1688717410092)(C:\Users\26332\AppData\Roaming\Typora\typora-user-images\image-20230707111134150.png)]
Filter是什么,有什么用,执行原理是什么?
一个过滤器怎么写呢?
注意:
package action; import jakarta.servlet.ServletException; import jakarta.servlet.annotation.WebServlet; import jakarta.servlet.http.HttpServlet; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; @WebServlet("/a.do") public class Aservlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("Aservlet的doget方法执行..."); } }
package action; import jakarta.servlet.ServletException; import jakarta.servlet.annotation.WebServlet; import jakarta.servlet.http.HttpServlet; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; @WebServlet("/b.do") public class BServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("Bservlet的doget方法执行..."); } }
//过滤器 package action; import jakarta.servlet.*; import jakarta.servlet.annotation.WebFilter; import java.io.IOException; @WebFilter("*.do") public class Filter1 implements Filter { public Filter1() { System.out.println("构造方法执行"); } @Override public void init(FilterConfig filterConfig) throws ServletException { System.out.println("init。。。"); } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { System.out.println("doFilter开始执行。。。"); //执行下一个过滤器,如果下面没有过滤器,则执行目标Servlet chain.doFilter(request,response); //如果执行完Servlet,就会在执行下面这条语句 System.out.println("doFilter方法执行结束"); } @Override public void destroy() { System.out.println("dostroy。。。"); } }
Filter优先级高于Servlet
什么是Listener
监听器有什么用?
Servlet规范中提供了哪些监听器?(监听器里的方法调用根据域,例如Context,服务器启动执行一个方法,服务器关闭执行一个方法。request一次请求就执行一次)
实现一个监听的步骤:(以ServletContextListener为例:)
第一步:编写一个类实现ServletContextListener接口。并且实现里面的方法
import jakarta.servlet.ServletContextEvent;
import jakarta.servlet.ServletContextListener;
public class MyServletContextListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
}
}
第二步:在web.xml文件中对MyServletContextListener进行配置:
<listener>
<listener-class>MyServletContextListener</listener-class>
</listener>
也可以使用注解:
import jakarta.servlet.ServletContextEvent; import jakarta.servlet.ServletContextListener; import jakarta.servlet.annotation.WebListener; @WebListener public class MyServletContextListener implements ServletContextListener { @Override public void contextInitialized(ServletContextEvent sce) { } @Override public void contextDestroyed(ServletContextEvent sce) { } }
注意:所有监听器中的方法都是不需要javaweb程序员调用,由服务器自动调用。什么时候调用?
做网站用户在线人数功能:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。