Servlet注解,简化配置
-
作用
- 每次新增Servlet时,都需要在web.xml文件配置(注册Servlet)。如果大的项目,web.xml文件的内容会很庞大。所以可以通过Servlet注解进行简化,同时也提高了开发效率。
- Servlet3.0以后版本就推出了注解式开发
- 注解式开发的优点
- 开发效率高,不需要编写大量的配置信息,
- web.xml文件体积变小
- 注意
- 有些需要变化的信息,还是需要配置到web.xml文件中,一般采用 注解 + 配置文件 的开发模式。
- 一些不会经常修改的配置建议使用 注解
- 注解式开发的优点
-
写法
package com.bz.oa.web.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; import java.io.PrintWriter; // @WebServlet(name="a", urlPatterns = {"/a"}) // urlPatterns只有一个时可以简写,如下 // @WebServlet(name="a", urlPatterns = "/a") // urlPatterns和value 相同,可以简写,如下 // @WebServlet(name="a", value = "/a") // 注解中只有value属性时可以省略属性名,如下 @WebServlet("/a") public class AServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=UTF-8"); PrintWriter out = response.getWriter(); String servletName = getServletName(); out.println("<h1>servlet name = " + servletName + "</h1>"); String contextPath = request.getContextPath(); out.println("<h1>contextPath = " + contextPath + "</h1>"); } }
- 在类的上方添加注解:@WebServlet
使用模板方法设计模式优化OA项目
- 概念
- 类爆炸:类太多
- 如何解决类爆炸问题?
- 以前的设计是一个请求一个Servlet类,1000个请求对应1000个Servlet类,导致类爆炸。
- 优化思路
- 一个 请求对应一个方法,一个业务对应一个Servlet类
- 以oa系统为例,处理部门相关业务的对应一个DeptServlet,处理用户相关业务的对应一个UserServlet……
- 一个 请求对应一个方法,一个业务对应一个Servlet类
分析使用纯粹Servlet开发Web应用的缺陷 - JSP技术入场
- 在Servlet当中编写HTML、CSS、JS等前端代码。存在什么问题?
- java程序中编写前端代码,编写难度大,麻烦;而且代码不美观
- java程序中编写前端代码,显然程序的耦合度非常高
- java程序中编写前端代码,维护成本高(非常难维护)
JSP技术
本质
- 底层中Tomcat会把jsp文件翻译生成对应的java文件,然后再编译生成class文件
- 访问index.jsp,实际上执行的是index_jsp.class文件中的方法
- jsp实际上就是一个Servlet
- jsp的生命周期与Servlet的生命周期一样
- jsp和Servlet都是单例(假单例)的。
JSP和Servlet有什么区别?
- 职责不同
- Servlet的职责是:收集数据
- JSP的职责是:展示数据
第一次访问jsp比较慢的原因
- 第一次访问jsp时,jsp文件会翻译成java文件,然后还需要编译生成class文件
jsp错误调试方法
- 需要找到jsp翻译后的java文件,检查java代码。
注意
-
JSP文件的扩展名可以不为xxx.jsp。可以在CATALINA_HOME(tomcat)/conf/web.xml文件的中进行配置
<servlet-mapping> <servlet-name>jsp</servlet-name> <url-pattern>*.jsp</url-pattern> <url-pattern>*.jspx</url-pattern> </servlet-mapping>
jsp语法
基础语法
-
在jsp文件直接编写代码,都会自动翻译到对应的java文件中的server方法的out.write(“翻译到这里”);中。
-
JSP的page指令,解决响应时的中文乱码问题
<!--响应的内容类型为text/html;采用的字符集为:UTF-8--> <%@ page contentType="text/html;charset=UTF-8" language="java" %>
-
JSP中如何编写java程序,会自动翻译到对应的java文件中的server方法中。
<% java语句; %>
-
JSP专业注释,不会被翻译到Java源代码中
<%-- JSP注释内容 --%>
-
声明,会自动翻译到对应的java文件中的server方法之外(很少用)
<%! java代码; %>
-
如何在浏览器上输出java变量
<% int num = 10; %> <% out.write("num = " + num); %> <%-- 或 --%> <%=num %>
基本语法总结
- <%page %>
- page指令,通过contentType属性用来设置响应的内容类型,字符集编码
- JSP直接编写普通字符串
- 翻译到service方法的out.write(“这里”);
- <%%>
- 翻译到service方法之中,是java语句
- <%! %>
- 翻译到service方法之外
- <%= %>
- 翻译到service方法的out.print(这里);
什么是javabean?
- Javabean翻译为:咖啡豆。
- 整个java程序中有很多bean存在,由很多bean组成。
- 实际上javabean可以理解为符合某种规范的java类,例如:
- 有无参数构造方法
- 属性私有化
- 对外提供公开的set和get方法
- 实现java.io.Serializable接口
- 重写toString()
- 重写hasCode() + equals()
- ……
- javabean其实就是java中的实体类,负责数据的封装
- 由于javabean符合javabean规范,具有更强的通用性
Servlet注解 + 模板方法设计模式 + JSP技术 优化OA系统
-
目录结构
src |----com.bz.oa |----bean |----Dept.java |----utils |----DBUtil |----web.action |----DeptServlet |----resources |----jdbc.properties web |----WEB-INF |----lib |-----mysql jdbc驱动包 |----web.xml |----addDept.jsp |----deptList.jsp |----detail.jsp |----editDept.jsp |----error.jsp |----index.jsp
-
addDept.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>新增部门</title> </head> <body> <h1>新增部门</h1> <hr/> <form action="<%=request.getContextPath()%>/dept/add" method="post"> 部门编号<input type="number" name="deptno" /><br/> 部门名称<input type="text" name="dname" /><br/> 部门位置<input type="text" name="address" /><br/> <input type="submit" value="保存" /> </form> </body> </html>
-
deptList.jsp
<%@ page import="com.bz.oa.bean.Dept" %> <%@ page import="java.util.List" %> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <meta charset='utf-8' /> <title>部门列表</title> </head> <body> <script type="text/javascript"> function del(deptno) { if (window.confirm('删除后无法 恢复,是否确定删除?')) { document.location.href = "<%=request.getContextPath()%>/dept/delete?deptno=" + deptno; } } </script> <h1>部门列表</h1> <br/> <table border="1" align="center" width="50%"> <tr> <th>部门编号</th> <th>部门名称</th> <th>操作</th> </tr> <% List<Dept> depts = (List<Dept>)request.getAttribute("deptList"); for(Dept dept : depts) { %> <tr> <td><%=dept.getDeptno()%></td> <td><%=dept.getDname()%></td> <td> <a href="javascript:void(0);" onClick="del(<%=dept.getDeptno()%>)">删除</a> <a href="<%=request.getContextPath()%>/dept/detail?deptno=<%=dept.getDeptno()%>&isEdit=1">编辑</a> <a href="<%=request.getContextPath()%>/dept/detail?deptno=<%=dept.getDeptno()%>&isEdit=0">详情</a> </td> </tr> <% } %> </table> <hr/> <a href="<%=request.getContextPath()%>/addDept.jsp">新增部门</a> </body> </html>
-
detail.jsp
<%@ page import="com.bz.oa.bean.Dept" %> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <meta charset="utf-8" /> <title>部门详情</title> </head> <body> <% Dept dept = (Dept) request.getAttribute("deptDetail"); String isEdit = request.getParameter("isEdit"); // 0:详情 1:修改 if (isEdit.equals("1")) { %> <h1>修改部门</h1> <hr/> <form action="<%=request.getContextPath()%>/dept/update" method="post"> 部门编号<input type="number" name="deptno" value="<%=dept.getDeptno()%>" readonly /> <br/> 部门名称<input type="text" name="dname" value="<%=dept.getDname()%>" /> <br/> 部门位置<input type="text" name="address" value="<%=dept.getAddress()%>" /> <br/> <input type="submit" value="保存" /> </form> <% } else { %> <h1>部门详情</h1> <hr/> <p>部门编号:<%=dept.getDeptno()%></p> <p>部门名称:<%=dept.getDname()%></p> <p>部门地址:<%=dept.getAddress()%></p> <input type="button" value="返回" onClick="window.history.back()" /> <% } %> </body> </html>
-
editDept.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <meta charset="UTF-8"> <title>部门编辑</title> </head> <body> <h1>修改部门</h1> <hr/> <form action="<%=request.getContextPath()%>/deptList.jsp" method="post"> 部门编号<input type="number" name="deptno" value="deptno" readonly /> <br/> 部门名称<input type="text" name="dname" value="dname" /> <br/> 部门位置<input type="text" name="address" value="address" /> <br/> <input type="submit" value="保存" /> </form> </body> </html>
-
error.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>error</title> </head> <body> <h1>操作失败</h1> <a href="<%=request.getContextPath()%>/dept/list">返回</a> </body> </html>
-
index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>欢迎使用oa系统</title> </head> <body> <a href="<%=request.getContextPath()%>/dept/list">查看部门列表</a> </body> </html>
-
jdbc.properties
driver=com.mysql.cj.jdbc.Driver url=jdbc:mysql://ip地址:3306/bztest user=root pwd=root
-
Dept.java
package com.bz.oa.bean; import java.util.Objects; /** * 一个普通的Java类,这个Java类可以封装零散的数据,代表了一个部门对象 */ public class Dept { private String deptno; private String dname; private String address; public Dept() { } public Dept(String deptno, String dname, String address) { this.deptno = deptno; this.dname = dname; this.address = address; } 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 getAddress() { return address; } public void setAddress(String address) { this.address = address; } @Override public String toString() { return "Dept{" + "deptno='" + deptno + '\'' + ", dname='" + dname + '\'' + ", address='" + address + '\'' + '}'; } @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(address, dept.address); } @Override public int hashCode() { return Objects.hash(deptno, dname, address); } }
-
DBUtil.java
package com.bz.oa.utils; import java.sql.*; import java.util.ResourceBundle; /** * JDBC工具类 */ public class DBUtil { // 静态变量,在类加载时执行 // 并且是有顺序的,自上而下的顺序 // 注意:这里的resources目录是在src下的 private static ResourceBundle bundle = ResourceBundle.getBundle("resources.jdbc"); private static String driver = bundle.getString("driver"); private static String url = bundle.getString("url"); private static String user = bundle.getString("user"); private static String pwd = bundle.getString("pwd"); static { try { // 注册驱动 Class.forName(driver); } catch (ClassNotFoundException e) { e.printStackTrace(); } } /** * 获取数据库连接对象 * @return connection 数据库连接对象 * @throws SQLException */ public static Connection getConnection() throws SQLException { return DriverManager.getConnection(url, user, pwd); } /** * 释放资源 * @param conn 数据库连接对象 * @param stat 数据库操作对象 * @param res 结果集对象 */ public static void close(Connection conn, Statement stat, ResultSet res) { if (res != null) { try { res.close(); } catch (SQLException e) { e.printStackTrace(); } } if (stat != null) { try { stat.close(); } catch (SQLException e) { e.printStackTrace(); } } if (conn != null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } }
-
DeptServlet.java
package com.bz.oa.web.action; import com.bz.oa.bean.Dept; import com.bz.oa.utils.DBUtil; 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; 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/detail", "/dept/add", "/dept/delete", "/dept/update"}) public class DeptServlet extends HttpServlet { @Override protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String servletPath = request.getServletPath(); if("/dept/list".equals(servletPath)) { doList(request, response); } else if("/dept/detail".equals(servletPath)) { doDetail(request, response); } else if("/dept/add".equals(servletPath)) { doSave(request, response); } else if("/dept/delete".equals(servletPath)) { doDel(request, response); } else if("/dept/update".equals(servletPath)) { doUpdate(request, response); } } /** * 修改部门信息 * @param request * @param response * @throws ServletException * @throws IOException */ private void doUpdate(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{ String deptno = request.getParameter("deptno"); String dname = request.getParameter("dname"); String address = request.getParameter("address"); Connection conn = null; PreparedStatement ps = null; int count = 0; try { conn = DBUtil.getConnection(); String sql = "update t_dept set dname=?, address=? where deptno = ?"; ps = conn.prepareStatement(sql); ps.setString(1, dname); ps.setString(2, address); ps.setString(3, deptno); count = ps.executeUpdate(); } catch (SQLException e) { e.printStackTrace(); } finally { DBUtil.close(conn, ps, null); } String contextPath = request.getContextPath(); if(count > 0) { // 修改成功 response.sendRedirect(contextPath + "/dept/list"); } else { // 修改失败 response.sendRedirect(contextPath + "/error.jsp"); } } /** * 连接数据库,查询所有的部门信息,将部门信息收集好,然后跳转到JSP做页面展示 * @param request * @param response * @throws ServletException * @throws IOException */ private void doList(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 准备一个容器,用来专门存储部门 List<Dept> depts = new ArrayList<>(); Connection conn = null; PreparedStatement ps = null; ResultSet rs = null; try { conn = DBUtil.getConnection(); String sql = "select deptno, dname, address from t_dept"; ps = conn.prepareStatement(sql); rs = ps.executeQuery(); while(rs.next()) { String deptno = rs.getString("deptno"); String dname = rs.getString("dname"); String address = rs.getString("address"); System.out.println(deptno + ", " + dname + ", " + address); // 将以上零散的数据封装成java对象 Dept dept = new Dept(deptno, dname, address); // 将部门对象放到集合中 depts.add(dept); } // 将部门对象集合放到请求域中 request.setAttribute("deptList", depts); // 转发(不用重定向) request.getRequestDispatcher("/deptList.jsp").forward(request, response); } catch (SQLException e) { e.printStackTrace(); } finally { DBUtil.close(conn, ps, rs); } } /** * 获取部门详情 * @param request * @param response * @throws ServletException * @throws IOException */ private void doDetail(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String deptno = request.getParameter("deptno"); String isEdit = request.getParameter("isEdit"); // 0:详情 1:修改 Connection conn = null; PreparedStatement ps = null; ResultSet rs = null; Dept dept = new Dept(); try { conn = DBUtil.getConnection(); String sql = "select dname, address from t_dept where deptno = ?"; ps = conn.prepareStatement(sql); ps.setString(1, deptno); rs = ps.executeQuery(); if(rs.next()) { dept.setDeptno(deptno); dept.setDname(rs.getString("dname")); dept.setAddress(rs.getString("address")); } } catch (SQLException e) { e.printStackTrace(); } finally { DBUtil.close(conn, ps, rs); } request.setAttribute("isEdit", isEdit); request.setAttribute("deptDetail", dept); // 转发到jsp页面 request.getRequestDispatcher("/detail.jsp").forward(request, response); } /** * 添加部门 * @param request * @param response * @throws ServletException * @throws IOException */ private void doSave(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("UTF-8"); String deptno = request.getParameter("deptno"); String dname = request.getParameter("dname"); String address = request.getParameter("address"); Connection conn = null; PreparedStatement ps = null; int count = 0; try { conn = DBUtil.getConnection(); // 开启事务 conn.setAutoCommit(false); String sql = "insert into t_dept (deptno, dname, address) values (?, ?, ?)"; ps = conn.prepareStatement(sql); ps.setString(1, deptno); ps.setString(2, dname); ps.setString(3, address); count = ps.executeUpdate(); // 提交事务 conn.commit(); } catch (SQLException e) { if(conn != null) { // 回滚事务 try { conn.rollback(); } catch (SQLException ex) { ex.printStackTrace(); } } e.printStackTrace(); } finally { DBUtil.close(conn, ps, null); } if (count > 0) { // 新增成功 response.sendRedirect(request.getContextPath() + "/dept/list"); } else { // 新增失败 response.sendRedirect(request.getContextPath() + "/error.jsp"); } } /** * 删除部门 * @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.getConnection(); // 开启事务 conn.setAutoCommit(false); String sql = "delete from t_dept where deptno = ?"; ps = conn.prepareStatement(sql); ps.setString(1, deptno); count = ps.executeUpdate(); // 提交事务 conn.commit(); } catch (SQLException e) { if (conn != null) { // 回滚事务 try { conn.rollback(); } catch (SQLException ex) { ex.printStackTrace(); } } e.printStackTrace(); } finally { DBUtil.close(conn, ps, null); } if (count > 0) { // 删除成功 response.sendRedirect(request.getContextPath() + "/dept/list"); } else { // 删除失败 response.sendRedirect(request.getContextPath() + "/error.jsp"); } } }
index.jsp修改为登录页,实现登录操作
-
新增t_user表
drop table if exists t_user; create table t_user ( id int primary key auto_increment, username varchar(255), password varchar(255) ); insert into t_user (username, password) values ('bz', '123'); commit; select * from t_user;
-
index.jsp调整
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>欢迎使用oa系统</title> </head> <body> <form action="<%=request.getContextPath()%>/user/login" method="post"> <h1>用户登录</h1> <hr> 用户名:<input type="text" name="username" /><br/> 密码:<input type="password" name="password"/><br/> <input type="submit" value="登录"> </form> <a href="<%=request.getContextPath()%>/dept/list">查看部门列表</a> </body> </html>
-
UserServlet.java
package com.bz.oa.web.action; import com.bz.oa.utils.DBUtil; 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 javax.xml.transform.Result; import java.io.IOException; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; @WebServlet("/user/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 res = null; boolean success = false; try { conn = DBUtil.getConnection(); String sql = "select * from t_user where username=? and password=?"; ps = conn.prepareStatement(sql); ps.setString(1, username); ps.setString(2, password); res = ps.executeQuery(); if(res.next()) { success = true; } } catch (SQLException e) { e.printStackTrace(); } finally { DBUtil.close(conn, ps, res); } String contextPath = request.getContextPath(); if(success) { // 登录成功 response.sendRedirect(contextPath + "/dept/list"); } else { // 登录失败 response.sendRedirect(contextPath); } } }
存在问题
- 在浏览器地址栏直接输入地址,可以跳过登录环节,进行数据的增删改查操作,这是一个很大的安全漏洞。可以 通过会话(session)机制
会话(session)机制
什么是会话?
- 用户打开浏览器,进行一系列操作,最后关闭浏览器。这整个过程叫做:一次会话
- 一次会话对应n次请求
- 超时时间默认是30分钟
作用
- 保存会话状态
为什么需要session对象来保存会话状态呢?
- 因为HTTP协议是一种无状态协议
- 什么是无状态:请求的时候,B和S是连接的,但是请求结束后,连接就断了。(减轻服务器压力)
实现原理
- 在web服务器中有一个类似map集合的session列表,这个map集合的key存储的是sessionid,这个map集合的value存储的是对应的session对象
- 用户发送第一次请求时:服务器会创建一个新的session对象,同时给session对象生成一个id,然后web服务器会将session的id发送给浏览器,浏览器会将这个id保存到缓存中,所以关闭浏览器后,浏览器中的缓冲就被释放了,所以sessionid就不存在了
- 用户第二次发送请求时,会自动将浏览器缓存中的sessionid自动发送给服务器,服务器获取到sessionid后,再从session列表中查找对应的session对象
工作原理
- 用户打开浏览器,第一次请求时,服务器生成session对象,同时生成sessionid,并将sessionid响应给浏览器
- 用户第二次请求时,自动将浏览器内存中的sessionid发送给服务器,服务器根据id查找session对象
- 用户关闭浏览器时,内存释放,cookie消失,sessionid消失,会话等同于结束
Cookie禁用的含义
- 服务器把生成的sessionid响应给浏览器,但是浏览器拒收了,浏览器不缓冲sessionid。所以每次请求都重新生成session对象
Cookie禁用了,如何实现session机制
-
需要使用URL重写机制,在URL后追加“;sessionid=第一次响应的sessionid值”
http://xxxx;sessionid=xxxxxxxxxxxxxxxxx
-
URL重写机制会导致开发成本加大,原因:每个请求后都需要加sessionid。所以目前的方案是如果不允许cookie,就建议别使用该系统。
session的销毁方式
- 超时销毁
- 手动销毁
session的配置
-
第一种:在web.xml文件配置
<!-- session的超时时长是30分钟 --> <session-config> <session-timeout>30</session-timeout> </session-config>
案例
-
第一次请求:服务器生成session对象,并响应给浏览器,浏览器以Cookie形式保存
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1BrX1N0r-1658934971915)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20220727214129522.png)]
-
第二次请求:浏览器从Cookie取sessionid,发送请求时一并发送给服务器,服务器根据拿到的sessionid查询session列表中的数据
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zujuMqwt-1658934971918)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20220727214211792.png)]
在java的Servlet规范中,session对应的类名:HttpSession(jakarta.servlet.http.HttpSession)
session机制属于B/S结构的一部分
// 从服务器中获取session对象,如果获取不到,就新建session对象
HttpSession session = request.getSession();
// 从服务器中获取session对象,如果获取不到,返回null
HttpSession session = request.getSession(false);
Cookie
cookie保存的位置?
- jakarta.servlet.http.Cookie
- cookie最终保存在浏览器客户端上,可以保存在运行内存中,也可以保存在硬盘文件中(永久保存)
cookie有啥用?
- cookie和session机制其实都是为了保存会话状态
- cookie是将会话的状态保存在浏览器客户端上,session是将会话状态保存在服务器上
cookie机制和session机制不属于java的机制,都是HTTP协议。
只要是web开发,不管哪种语言,cookie和session都是需要的。
HTTP协议规定:
- 任何一个cookie都是由name和value组成的,name和value都是字符串
- 当浏览器发送请求时,会自动携带该path下cookie数据给服务器
cookie有效时间
默认不设置有效时间
- 默认保存浏览器的运行内存中,浏览器关闭则cookie失效
- 只要设置cookie的有效时间大于0,这个cookie一定会存储到硬盘文件当中。
- cookie有效时间等于0,cookie会被删除
- cookie有效时间小于0,cookie不会被存储到硬盘文件中,但是会被存储到浏览器运行内存中(跟不调用setMaxAge方法一样)。
如何设置有效时间
Cookie cookie = new Cookie(k, v);
// 单位:秒
// 设置cookie在一小时之后失效
cookie.setMaxAge(60 * 60);
// 手动设置cookie的path
cookie.setPath("/webServlet");
关于cookie的path
假如当前发送请求路径为:http://localhost:8080/webServlet/aaa/bbb生成cookie
-
默认情况
- 如果cookie没有设置path,默认的path为:http://localhost:8080/webServlet/aaa 以及它的子路径
- 也就是说,以后只要浏览器的请求路径是 http://localhost:8080/webServlet/aaa 这个路径以及这个路径下的子路径,cookie都会被发送到服务器。
-
手动设置cookie的path
- cookie.setPath(“/webServlet”);表示只要是这个webServlet项目的请求路径,都会提交这个cookie给服务器。
浏览器发送cookie给服务器,服务器的java程序如何接收?
// 如果浏览器没有提交cookie,这个方法返回值为null,并不是返回一个长度为0的数组
Cookie[] cookies = request.getCookies();
if(cookies != null) {
for(Cookie cookie : cookies) {
String name = cookie.getName();
String value = cookie.getValue();
System.out.println(name + " = " + value);
}
}
EL表达式
-
EL表达式有什么用?
- Expression Language(表达式语言)
- EL表达式可以代替JSP中的java代码,让JSP文件中的程序看起来更加整洁,美观
- EL表达式可以算是JSP语法的一部分,EL表达式归属于JSP
-
EL表达式出现在JSP中主要是:
- 从某个作用域中取数据,然后将其转换成字符串,最后将其输出到浏览器
-
EL表达式的三大功效:
- 第一功效:从某个作用域中取数据
- 四个域
- pageContext
- request
- session
- application
- 四个域
- 第二功效:将取出的数据转换成字符串
- 如果是一个java对象,也会自动调用java对象的toString方法将其转换成字符串
- 第三功效:将字符串输出到浏览器
- 第一功效:从某个作用域中取数据
-
EL表达式的基本语法:
${表达式}