绝对路径
<a href="localhost:8080/system/pages/hello.html">跳转</a>
相对路径问题
/
表示从根目录(域名+ip)出发
./
表示从当前位置出发
../
表示跳向上一层
如有index页面所在路径为
localhost:8080/system/pages/index.html
<a href="/hello.html">跳转</a>
这种方式,从根目录(localhost:8080)出发,会跳转到localhost:8080/hello.html
<a href="./hello.html">跳转</a>
这种方式,从当前位置(localhost:8080/system/pages)出发,会跳转到localhost:8080/system/pages/hello.html
<a href="../hello.html">跳转</a>
这种方式,从当前位置跳向上一层,会跳转到localhost:8080/system/hello.html
在jsp页面中,可以使用**${pageContex.request.contextPath}**表示页面上下文路径。
如项目默认上下文访问路径为localhost:8080/system
<a href="${pageContex.request.contextPath}/pages/hello.html">跳转</a>
以上路径相当于/system/pages/hello.html,即从根目录出发localhost:8080/system/pages/hello.html
如果在jsp页面中无法识别${},在<%@ page%>中加入isELIgnored="false"
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
四大作用域对象
作用域:共享数据的区域
pageContext
当前页面对象。共享数据区域范围为当前页面。
如果不在同一个页面,数据无法读取。
request
请求对象。共享数据区域范围为一次请求。
如果跳转中途使用了重定向,数据无法读取。
session
会话对象。会话是用户访问服务器时的某个时间段。
共享数据区域范围在这个时间段内,默认30分钟。
如果在指定时间内没有操作或销毁会话时,数据无法读取。
application
项目对象。共享数据区域范围为整个项目。
作用域范围
application > session > request > pageContext
以上四个作用域对象,都有这几个方法
//将某个对象obj保存到作用域中,命名为str
作用域对象.setAttribute(String str,Object obj);
//从某个作用域中获取保存的某个对象
Object obj = 作用域对象.getAttribute(String str);
//从某个作用域中移除某个保存的对象
作用域对象.removeAttribute(String str);
作用域对象的使用
在JSP页面中
作用域对象也称为内置对象,直接通过对应的单词使用
p1.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%
//在jsp中使用pageContext页面上下文对象,跳转到p2时不能使用
pageContext.setAttribute("str","保存在pageContext作用域中的字符串");
//在jsp中使用request请求对象,请求转发到p2时可以使用,重定向到p2时不能使用
request.setAttribute("str","保存在request中的字符串");
//在jsp中使用session会话对象,在默认的30分钟内,没有销毁,哪种跳转都能在p2中使用
session.setAttribute("str","保存在session中的字符串");
//在jsp中使用application应用程序对象,整个项目中任何页面都能使用
application.setAttribute("str","保存在application中的字符串");
//以上四个作用域对象,也是jsp中的内置对象,无需定义
//销毁会话
//session.invalidate();
//使用请求转发跳转到p2.jsp
//request.getRequestDispatcher("p2.jsp").forward(request,response);
//使用重定向跳转到p2.jsp
response.sendRedirect("p2.jsp");
%>
<h1><%=pageContext.getAttribute("str")%></h1>
</body>
</html>
p2.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h3><%=pageContext.getAttribute("str")%></h3>
<h3><%=request.getAttribute("str")%></h3>
<h3><%=session.getAttribute("str")%></h3>
<h3><%=application.getAttribute("str")%></h3>
</body>
</html>
在servlet中使用
pageContext
servlet本身就是一个java类,在类中定义成员变量,就能在当前类中使用。
所以在servlet中不会使用pageContext对象
request
使用doGet/doPost/service方法中的HttpServletRequest参数req
session
//在servlet中使用session,需要通过请求对象request调用getSession()方法
HttpSession session= req.getSession();
application
//通过getServletContext()方法获取的ServletContext类型对象,就是当前项目对象
ServletContext application = getServletContext();
总结
在jsp页面中使用pageContext保存的数据,只能共享于当前页面
通常在servlet中查询后的数据保存在request中,使用请求转发跳转到其他页面,在对应的页面中数据数据
通常在登录后,将登录的用户保存在session中,无论用哪种方式跳转,都能从session中获取当时登录的用户。
在application中保存一些共享于整个项目中的数据
购物车
添加商品时,如果不存在,直接添加,如果存在,修改数量。
采用HashMap作为核心容器。将商品作为键,将购买数量作为值。
使用Hash相关集合,需要重写实体类中的hashcode和equals方法。
实现过程
1.BookInfo和BookType类重写equals和hashcode方法,选择所有属性
2.创建购物车类Cart类
package com.hqyj.bookShop.util;
import com.hqyj.bookShop.entity.BookInfo;
import java.util.HashMap;
/*
* 购物车
* 使用HashMap作为购物车容器
* 添加商品方法
* 移除商品方法
* 查看购物车
* 清空购物车
*
* */
public class Cart {
/*
* 商品作为键,购买数量作为值
* */
private HashMap<BookInfo, Integer> hm;
/*
* 创建购物车对象时,初始化HashMap
* */
public Cart() {
hm = new HashMap<>();
}
/*
* 添加到购物车
* */
public void addToCart(BookInfo bi, int buyNum) {
//判断键是否存在
if (hm.containsKey(bi)) {//如果存在,修改数量
//获取现有数量
Integer oldNum = hm.get(bi);
//覆盖原本的值
hm.put(bi,oldNum+buyNum);
}else{//如果不存在,直接添加
hm.put(bi,buyNum);
}
}
/*
* 获取购物车
* */
public HashMap<BookInfo, Integer> getCart() {
return hm;
}
/*
移除商品
*/
/*
清空购物车
*/
}
3.在登录成功后,创建购物车Cart对象,将其保存到session中
case "login":
//获取登录信息
String phone = req.getParameter("phone");
String password = req.getParameter("password");
//调用登录
Customer login = dao.login(phone, password);
if (login != null) {
//登录成功后,创建购物车对象
Cart cart = new Cart();
//将购物车保存到session中
session.setAttribute("cart",cart);
//将登录成功的对象,保存到session中
session.setAttribute("customer", login);
//使用重定向跳转到查询所有图书的servlet
resp.sendRedirect("./bookInfo?op=search");
} else {
System.out.println("登录失败");
}
break;
4.在图书详情页中,创建添加商品到购物车的表单
<%--提交到图书servlet--%>
<form action="./bookInfo">
<%--op、图书编号、购买数量--%>
<input type="hidden" name="op" value="addToCart">
<input type="hidden" name="id" value="<%=bi.getBookId()%>">
<input type="number" name="buyNum" value="1" min="1" max="<%=bi.getBookNum()%>" ><br>
<input type="submit" value="添加到购物车">
</form>
5.在图书servlet中添加新op判断,获取要购买的数据
case "addToCart":
//图书编号
String buyId = req.getParameter("id");
//调用查询
BookInfo byId = biDao.findById(Integer.parseInt(buyId));
//获取购买数量
int buyNum = Integer.parseInt(req.getParameter("buyNum"));
//从session中获取购物车
Cart cart = (Cart) req.getSession().getAttribute("cart");
//调用添加
cart.addToCart(byId, buyNum);
//跳转购物车页面
resp.sendRedirect("./pages/cart.jsp");
break;
6.购物车页面
<%@ page import="com.hqyj.bookShop.util.Cart" %>
<%@ page import="com.hqyj.bookShop.entity.BookInfo" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<style>
* {
margin: 0;
padding: 0;
}
body {
background-color: #f5f5f5;
}
.wrap {
width: 900px;
height: 660px;
margin: 100px auto;
background-color: #fff;
}
a {
text-decoration: none;
color: deepskyblue;
}
.wrap table {
width: 100%;
border: 1px solid skyblue;
border-collapse: collapse;
}
.wrap table th, td {
width: 120px;
height: 20px;
border: 1px solid skyblue;
}
</style>
</head>
<body>
<%--防止在未登录的情况下访问该页面--%>
<%--
如果登录成功,session中保存登录的对象customer,
如果没有登录或者退出,customer对象就会消失。
所以判断customer对象是否存在,决定是否显示该页面
--%>
<%
//如果从session中无法获取customer对象,跳转到登录页面
if (session.getAttribute("customer") == null) {
response.sendRedirect("login.html");
return;
}
//获取session中的购物车对象
Cart cart = (Cart) session.getAttribute("cart");
%>
<jsp:include page="top.jsp"></jsp:include>
<div class="wrap">
<table>
<tr>
<th>图书编号</th>
<th>图书名称</th>
<th>图书作者</th>
<th>图书单价</th>
<th>购买数量</th>
<th>小计</th>
</tr>
<%
double sumPrice = 0;
for (BookInfo bookInfo : cart.getCart().keySet()) {
sumPrice += cart.getCart().get(bookInfo) * bookInfo.getBookPrice();
%>
<tr>
<td><%=bookInfo.getBookId()%>
</td>
<td><%=bookInfo.getBookName()%>
</td>
<td><%=bookInfo.getBookAuthor()%>
</td>
<td><%=bookInfo.getBookPrice()%>
</td>
<td><%=cart.getCart().get(bookInfo)%>
</td>
<td><%=cart.getCart().get(bookInfo) * bookInfo.getBookPrice()%>
</td>
</tr>
<%}%>
<tr>
<td colspan="5">总计</td>
<td><%=sumPrice%>
</td>
</tr>
</table>
</div>
</body>
</html>
Web项目开发模式
Model1
JSP+JavaBean模式。
JSP负责渲染数据和处理页面。
JavaBean是一个满足以下条件的类
被public修饰
其中的属性进行封装
用private修饰属性
提供get/set方法
有无参数的构造方法
这种模式,不适合复杂项目的开发。
jsp既要显示内容,又要处理数据,后期维护扩展不方便。
Model2(MVC)
MVC模式:模型-视图-控制器模式。
M:Model模型 用于封装数据处理数据,对应业务逻辑类、数据访问类、实体类
V:View视图 用于渲染数据,对应页面(jsp或html)
C:Controller控制器 用户调度用户请求,对应servlet
这种模式适合复杂项目的开发。
每个模块各司其职,耦合性低。
对于后期维护和扩展较为方便。
WEB阶段核心内容
B/S模式的访问流程
用户通过浏览器发送请求,访问服务器上的某个部署的项目,经过该项目的MVC,得到响应。
框架部分会使用SpringMVC替换现有的Servlet实现MVC的流程。
页面提交数据的方式
通过表单提交,可以设置get/post
<form action="地址" method="get/post">
<input type="text" name="参数" >
<input type="submit">
</form>
通过超链接提交,属于get提交
<a href="地址?参数=值&参数=值">xxx</a>
通过ajax提交,可以设置get/post
先导入Jquery
$.ajax({
//请求地址
url:'',
//提交数据
data:{
"参数名":值,
"参数名":值
},
//提交方式
type:"get/post",
//成功回调
success:function(res){
//res为控制层的返回值
},
//失败回调
error:function(){}
});
路径
/
表示根目录,即域名:端口号,如localhost:8080
./
表示当前目录,如在localhost:8080/Web03/page.html页面中访问./index.html,相当于localhost:8080/Web03/index.html
../
表示向上一层目录,如在localhost:8080/Web03/page.html页面中访问../index.html,相当于localhost:8080/index.html
使用EL的${pageContext.request.contextPath}表示当前项目的上下文路径,
如localhost:8080/Web03/pages/index.html中使用${pageContext.request.contextPath}/hello.html,
相当于localhost:8080/Web03/hello.html
servlet依赖
如果要使用servlet、filter、listener、request、response都需要该依赖
<!--servlet-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
</dependency>
web.xml中的相关配置
servlet
<!-- 声明servlet -->
<servlet>
<servlet-name>自定义servlet名</servlet-name>
<servlet-class>servlet全限定名</servlet-class>
<!-- servlet初始化参数 -->
<init-param>
<param-name>参数名</param-name>
<param-value>参数值</param-value>
</init-param>
</servlet>
<!-- 配置servlet请求映射 -->
<servlet-mapping>
<servlet-name>自定义servlet名</servlet-name>
<url-patten>/映射名</url-patten>
</servlet-mapping>
filter
<!-- 声明filter -->
<filter>
<filter-name>自定义filter名</filter-name>
<filter-class>filter全限定名</filter-class>
</filter>
<!-- 配置filter请求映射 -->
<filter-mapping>
<filter-name>自定义filter名</filter-name>
<!--过滤器通常用于解决中文乱码,要过滤所有请求-->
<url-patten>/*</url-patten>
</filter-mapping>
listener
<listener>
<listener-class>监听器的全限定名</listener-class>
</listener>
session
<!--设置全局session配置-->
<session-config>
<session-timeout>session有效时长,单位为分钟</session-timeout>
</session-config>
全局参数
<!--设置全局参数-->
<context-param>
<param-name>参数名</param-name>
<param-value>参数值</param-value>
</context-param>
数据访问层(Dao)
现在使用JDBC实现查询,框架部分会使用MyBatis、MyBatisPlus或JPA,简化该层的写法。
跳转
请求转发forward
保存在request中的数据会一直存在
request.getRequestDispatcher("目的路径").forward(request,response);
重定向redirect
保存在request中的数据会丢失(不是同一个请求)
response.sendRedirect("目的路径");
JSP
由控制层保存数据到作用域中,跳转到Jsp中展示数据。
作用域对象
pageContext request session application
内置对象
request response page pageContext session application out config exception
EL
Expression Language 表达式语言
是为了使JSP写起来更加简便,替换JSP中的<%=%>,简化了JSP页面中输出数据的操作。
主要输出保存在某个作用域中的数据。
特点
如果通过"某个作用域对象.setAttribute("cus",customer)"方法保存的对象,
在JSP页面中如果用表达式,使用<%=cus%>,如果用EL,使用**${cus}**输出。
会依次从pageContext-->reqeust-->session-->application中获取指定对象,
如果一旦从某个作用域中获取到了指定对象,就不再判断后续作用域。
也可以输出指定作用域中的对象。
只能输出保存在作用域中的对象
减少代码(省去了获取对象、转换的过程)
免去非空判断
如果某个要输出的对象不存在,不会输出null,而是输出空字符串""。
表达式语言。替换jsp中的输出<%=%>部分。
从作用域中获取对象,通过.或[]获取属性,该属性必须存在且有get方法
{对象名.属性名}或{指定作用域.对象名["属性名"]}
从请求中获取参数,表单的name或?后的数据
${param.参数名}
逻辑判断、计算
非空判断 ${empty 对象}
计算 ${xx + yy}
获取当前项目上下文路径
${pageContext.request.contextPath}
JSTL
<!--jstl标签库-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
先导入依赖,在jsp页面中引入标签库
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
判断
<c:if test="条件">
html内容
</c:if>
遍历
<c:forEach items="要遍历的集合" var="遍历出的对象">
html内容
</c:if>
Session
通常用session保存登录时的用户信息,实现在各个页面中共享信息或防止未登录的情况下访问。
使用session时,会创建一个JSESSIONID,保存在cookie中,在浏览器开启状态下,该JSESSIONID默认会有30分钟的有效期,
如果在30分钟内没有对session进行操作或关闭浏览器,该cookie就会销毁,对应的session就会失效。