33.JavaWeb基础

系统架构

 

系统架构简单点就是指所研发的系统分类,通常划分为B/S架构和C/S架构。

B/S架构:Browser(浏览器)/service(服务器),通常指的是在PC端运行的程序,例如:民宿后台管理系统、在线教育信息管理系统、网吧计费系统等等

优点:安全性高(所有的数据运算都在服务器执行)、不需要频繁更新

缺点:操作有局限性、运行效率低(所有的数据运算都在服务器执行)

C/S架构:Client(客户端)/Service(服务器),通常指的是在移动端运行的项目,例如:QQ、微信、探探、王者荣耀、今日头条、抖音等

优点:便捷携带、运行效率高

缺点:频繁下载更新、安全性能低

JavaWeb走的是B/S架构的方向,因此项目都需要在网页中进行浏览、操作,就需要有服务器的支持,因为在网页中发送的请求需要通过指定的协议进行处理。

Http1.0版本支持短连接,连接一次使用完立马断开,想要在使用就再连接,例如:发一条信息就断开连接,再发就需要重新连接。

Http1.1版本支持长连接,连接一次,可以多次使用,例如:连接成功后,可以一直发送信息;

 
Tomcat

通常一个Tomcat服务器可以支持200个并发访问,较优秀的可以支持500个并发访问。

Tomcat目录结构

启动Tomcat服务:在bin目录中找到startup.bat,双击运行

验证服务启动的方式,在浏览器的地址栏中输入:localhost:8080 或 http://127.0.0.1:8080,如果能打开Tomcat的官网,就代表服务启动成功了。

常见问题:

1、Tomcat未启动

2、窗口闪退

端口被占用,例如:已经开启了8080端口,然后又尝试去开启8080的端口服务

3、启动时闪退

闪退的原因:在环境变量中没有配置JAVA_HOME的变量

Eclipse配置Tomcat

Eclipse中本身自带了Tomcat,如果想要使用本机自己的Tomcat就需要进行设置

将Eclipse中运行的项目部署到指定的Tomcat的目录中:

Eclipse创建WEB项目

注意事项:web项目在开发的阶段中,可能会出现页面缓存的问题,原因有两点:

1、浏览器本身的缓存

方案:使用ctrl+f5进行刷新,强制刷新,或者在网页调试模式下,点network下的disabled cache

2、项目部署没有成功

方案:找到项目的部署目录,将对应的已部署的项目删掉,在开发工具中删除Tomcat重新创建一个

当在web项目中修改了xml文件或java代码的时候,项目需要重启(没有部署热部署插件时),如果修改的是jsp或html页面则不需要重启,只需要在浏览器中刷新即可。

JSP页面介绍

jsp页面其实就是html页面,但是呢,在页面中设置了浏览器的解析规则,让java代码也可以进行编译,同时能够在html页面中进行使用。

定义小脚本及方法:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
 hello jsp!!!
 <hr>
 你好,jsp!!!
 
 <!-- 小脚本:用于写java代码的 -->
 <%-- <% 
 	int x = 5, y = 6,max=0;
 	if(x>y){
 		max = x;
 		System.out.println(x);
 	}else{
 		max = y;
 		System.out.println(y);
 	}
 %> --%>
 <hr>
 最大值是:<%=maxMethod(7,2) %>
 <hr>
 <%!
 	public int maxMethod(int x,int y){
		 if(x>y){
			 return x;
		 }else{
		 	return y;
		 }
	 }
 %>
</body>
</html>

jsp的注释在页面审查元素模式下是不显示,前端的注释是可以看见的

编号 描述
404 页面资源找不到,通常是地址有问题
500 内部错误,通常是java代码出问题了
200 请求成功
网页无法显示 Tomcat未启动
JSP中的内置对象

内置对象:不需要手动去创建,可以直接进行使用的

out 用于页面输出
request 请求,通常用于form表单或地址栏中的数据请求
response 响应,对所有发送的请求给出响应结果
session 一次会话
application 全局对象(上下文对象)
pageContext 当前页对象
config 服务器配置对象
page  
Exception 异常

request对象

getParamter(String key) 根据key获取请求中的值
setCharacterEncoding() 设置请求字符编码
getRequestDispatch 请求转发
setAttribute(String key,Object val) 设置参数
getAttribute(String key) 获取参数

request是JSP的内置对象之一,称为请求,通过request对象可以获取到表单或者通过request进行传递的数据,request在进行页面的跳转时,第一页面中地址栏中的地址是不变的,第二请求转发只是一次请求,第三请求转发的过程中是可以携带数据的。

注意:在jsp页面中,每个页面都有自己的内置对象,通过请求转发,将上一个页面中的request和response对象传递到了下一个页面中。

编码的解决方案:

1、针对get请求,uname = new String(uname.getBytes("ISO8859-1"),"utf-8");

2、针对POST请求,request.setCharacterEncoding("utf-8");

3、在Tomcat的配置文件中设置请求编码

response对象

方法 描述
response.sendRedirect(String url) 跳转,重定向

 

response重定向,简单来讲就是重新发送一次请求,请求的效果就是跳转

response的特点,第一是地址栏中的地址会发生改变,第二是response不能携带参数,第三是多次请求

面试题:重定向和请求转发的区别/forward和sendRedirect的区别

多次重定向问题:

if("admin".equals(uname) && "admin".equals(password)){
	response.sendRedirect("success.jsp");
}else{
	response.sendRedirect("fail.jsp");
}
response.sendRedirect("login.jsp");
session对象

称为一次会话,当浏览器关闭后或session的生命周期结束后,这次会话就结束了

session通常是用于数据的存储,该数据是在服务器上进行存储的,是安全的。

session内置对象的方法:

setAttribute(String key,Object val) 设置值
getAttribute(String key) 获取值
setMaxInactiveInterval() 设置session的生命周期
getId() 获取session的唯一表示
removeAttribute(String key) 清除指定的key值

cookie对象(不是内置对象)

cookie是用于做本地的数据存储,往往是在浏览器中做相关的数据存储,但是呢,该存储方式是将数据存储到了本机的电脑上,因此,数据是不安全的,另一方面来讲,因为数据是在本地存储的,所以在进行数据的读取及运算时相对服务器来讲效率高很多。

常见的使用场景:记住账户、浏览记录、观看记录等等

//设置cookie
<%
	request.setCharacterEncoding("utf-8");
	//获取账户名
	String account = request.getParameter("uname");
	//使用cookie将用户名存储到本地
	Cookie cookie = new Cookie("account",account);
	//设置cookie的存活周期
	cookie.setMaxAge(3);
	//存储cookie
	response.addCookie(cookie);
	response.sendRedirect("login.jsp");
%>
//获取cookie
<%
		String account = "";
		//获取cookie值
		Cookie[] cookies = request.getCookies();
		if(cookies != null){
			//遍历cookie
			for(Cookie cookie : cookies){
				String key = cookie.getName();
				String val = cookie.getValue();
				if("account".equals(key)){
					account = val;
				}
			}
		}
	%>

关于cookie的生命周期:

setMaxAge():

值为负数:代表cookie的生命周期和session一样,当浏览器关闭时,cookie就结束了

值为0:代表让cookie立马失效

值为正数:代表cookie的存活周期,单位秒

目前的主流浏览器所支持的cookie的存储数量:50个,据说Chrome无限制(有点瞎),早期浏览器只支持20个

cookie存取时的字符编码问题:

编码:URLEncode.encode(String val,String enc); 参数一:要进行编码的值,参数二:编码格式

解码:URLDecode.decode(String val,String enc);参数一:要解码的值,参数二:解码对应的格式

application对象

application是Javaweb项目中的全局对象,通常用于给项目中设置一些全局属性等

应用场景:访问人数的统计

<%
		//计数器 初始值为0
		Integer count = 0;
		//思路:用户访问页面,计数器+1(在上一次的数量基础上进行+1操作)
		Object obj = application.getAttribute("count");
		/* //如果object为空,代表是第一次访问
		if(obj == null){
			count++;
			//第一次访问,设置访问数量为1
			application.setAttribute("count",count);
		}else{
			count = (Integer)obj;
			count++;
			application.setAttribute("count", count);
		} */
		if(obj != null){
			count = (Integer)obj;
		}
		count++;
		//第一次访问,设置访问数量为1
		application.setAttribute("count",count);
	%>
	访问量:<%=count %>
四大作用域
pageContext 只在当前页生效
request 在一次请求中生效
session 在一次会话中生效
application 在整个项目中生效
<%
		//验证方式:分别给不同的对象设置不同的参数,在另一个页面中验证是否能够获取对应的参数
		pageContext.setAttribute("pageContext", "pageContext");
		request.setAttribute("request", "request");
		session.setAttribute("session", "session");
		application.setAttribute("application","application");
		
		request.getRequestDispatcher("next.jsp").forward(request, response);
	%>
	<h3>当前页</h3>
	<a href="./next.jsp">go next page</a>
	<hr>
	pageContext:<%=pageContext.getAttribute("pageContext") %><br>
	request:<%=request.getAttribute("request") %><br>
	session:<%=session.getAttribute("session") %><br>
	application:<%=application.getAttribute("application") %>
JSP中操作数据库
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page import="java.util.*,beans.Emp,java.sql.*" %>
<%
	//思路:连接数据库,将获取到的数据存储起来,然后在数据列表页中进行获取渲染
	request.setCharacterEncoding("utf-8");
	

	//定义集合用于接收数据
	List<Emp> list = new ArrayList<Emp>();
	//1、注册驱动
	Class.forName("com.mysql.jdbc.Driver");
	//2、获取连接对象
	Connection conn = DriverManager.getConnection("jdbc:mysql:///hongzehu","root","root");
	//3、定义SQL,预编译
	String sql = "select * from emp";
	PreparedStatement ps = conn.prepareStatement(sql);
	//4、执行SQL拿到结果集
	ResultSet rs = ps.executeQuery();
	//5、遍历结果集,将结果集存储到集合中
	while(rs.next()){
		int eno = rs.getInt(1);
		String ename = rs.getString(2);
		String sex = rs.getString(3);
		String phone = rs.getString(4);
		String address = rs.getString(5);
		Emp emp = new Emp(eno,ename,sex,phone,address);
		//将对象添加到集合中
		list.add(emp);
	}
	//将数据存储到域中
	session.setAttribute("list", list);
	//6、关闭数据库连接对象
	rs.close();
	ps.close();
	conn.close();
	
	//回跳到list页面
	response.sendRedirect("list.jsp");
%>

//列表展示
<%
		//获取存储的集合数据
		Object obj = session.getAttribute("list");
		if(obj == null){
			response.sendRedirect("control.jsp");
			return;
		}
		List<Emp> list = (List<Emp>)obj;
	%>
	<table border="1" cellpadding="0" cellspacing="0" width="50%" align="center">
		<tr>
			<th>员工编号</th>
			<th>员工姓名</th>
			<th>员工性别</th>
			<th>联系方式</th>
			<th>家庭住址</th>
		</tr>
	
	<%
		for(Emp emp : list){
	%>
	
		<tr>
			<td><%=emp.getEno() %></td>
			<td><%=emp.getEname() %></td>
			<td><%=emp.getSex() %></td>
			<td><%=emp.getPhone() %></td>
			<td><%=emp.getAddress() %></td>
		</tr>
	<%
		}
	%>
	</table>
三层架构介绍

数据层:连接数据库,返回数据,所有该项目可能会用到的连接到数据的功能(可能会用到的功能) dao

业务层:根据用户的请求,去数据层找数据,返回给控制层(一定会用到的功能) service

控制层:接收请求、将请求交给业务层,再根据业务层返回的数据进行逻辑控制(跳转) controller

JSTL和EL表达式

原生的jsp中嵌套java代码的写法,使得整个jsp页面看着比较混乱,牵扯到有逻辑判断的时候,大多数情况都需要进行拼接,拼接是比较麻烦的且容易出现错误,所以就有了jstl标签库和el表达式。

el表达式:通过一种特定的书写格式,能够简化小脚本中的代码量,要求:要变量的变量一定是在某个作用域中。

<%
    Object obj = session.getAttribute("namekey");
    String name = (String)obj;
    out.println("name="+name);

    Object empObj = session.getAttribute("empkey");
    Emp emp = (Emp)empObj;
    String ename = emp.getEname();
    String sex = emp.getSex();
    out.println(ename+"--"+sex);
%>

<hr>
name:${namekey }
<!-- 该语法底层其实还是通过调用getter的方法来实现 -->
ename:${empkey.ename },
sex:${empkey.sex }

如果每个作用域中都有一个相同的key值时,到底获取的是哪一个?

回答:一定是从域中进行查找,如果多个域中都有,那么按照从小到大的顺序进行获取

<%
    //pageContext.setAttribute("key", "pageContextVal");
    //session.setAttribute("key", "sessionVal");
    application.setAttribute("key", "applicationVal");
    request.setAttribute("key", "requestVal");
%>
key-->${key }

el表达式中的运算符

字段 描述
eq == 判断是否相等
gt > 大于
lt < 小于
empty 判断是否为null
not empty  

 

缺点:el表达式是不能做逻辑运算的,如果需要做逻辑运算,那就需要使用jstl标签库

JSTL标签库

需要导入两个jar包:jstl.jar(标签库的jar)、standard(标签库的语言规范jar).jar

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
可选:当需要对内容进行格式化时加入以下头样式文件
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
并且需要导入相对应的jar包,实例如下:

下面分别对这些标签进行说明:

1. <c:set> 用于将变量存取于 JSP 范围中或 JavaBean 属性中。下面的例子中假设已经有 Person.java 这个类文件
 <c:set value="张三" var="name1" scope="session"></c:set>
<c:set var="name2" scope="session">李四</c:set>
<c:set value="赵五" target="${person}" property="name"></c:set>
<c:set target="${person}" property="age">19</c:set>
<li>从session中得到的值:${sessionScope.name1}</li>
<li>从session中得到的值:${sessionScope.name2}</li>
<li>从Bean中获取对象person的name值:<c:out value="${person.name}"></c:out></li>
<li>从Bean中获取对象person的age值:<c:out value="${person.age}"></c:out></li>

2. <c:out> 用来显示数据对象(字符串、表达式)的内容或结果

例如:

<c:out value="要显示的数据对象" default="默认值"></c:out>

3.<c:remove> 主要用来从指定的 jsp 范围内移除指定的变量。使用类似,下面只给出语法:

<c:remove var="变量名" ></c:remove>

4.<c:catch> 用来处理 JSP 页面中产生的异常,并存储异常信息

<c:catch var="name1">

      容易产生异常的代码

</c:catch>

如果抛异常,则异常信息保存在变量 name1 中。

5.<c:if>条件判断

<c:if test="${person.name == '张三'}" var="name1">
c:out value="name1的值:${name1}"></c:out>
</c:if

6. <c:choose> <c:when> <c:otherwise> 三个标签通常嵌套使用,第一个标签在最外层,最后一个标签在嵌套中只能使用一次。

使用相当于JAVA中的switch-case。例:

c:set var="score">85</c:set>
<c:choose>
<c:when test="${score>=90}">
你的成绩为优秀!
</c:when>
<c:when test="${score>=70&&score<90}">
您的成绩为良好!
</c:when>
<c:when test="${score>60&&score<70}">
您的成绩为及格
</c:when>
<c:otherwise>
不及格
</c:otherwise>
</c:choose>

7.<c:forEach>遍历

语法:<c:forEach var="name" items="Collection" varStatus="statusName" begin="begin" end="end" step="step"></c:forEach>

该标签根据循环条件遍历集合 Collection 中的元素。 var 用于存储从集合中取出的元素;items 指定要遍历的集合;varStatus 用于存放集合中元素的信息。varStatus 一共有4种状态属性,下面例子中说明:

①,指定开始结束值,每一次前进的步数step。

<c:forEach var="i" begin="0" end="10" step="1">
<p>${i}</p>
</c:forEach>

②,直接遍历,相当于JAVA中的foreach,使用比较频繁

<c:forEach var="str" items="${strs}">
<p>${str}</p>
</c:forEach>

③,综合使用

<c:forEach var="zhangsan" items="${a}" begin="3" end="4" step="1" varStatus="s">
<c:out value="${zhangsan}" />的四种属性:<br>
所在位置,即索引:<c:out value="${s.index}" /><br>
总共已迭代的次数:<c:out value="${s.count}" /><br>
是否为第一个位置:<c:out value="${s.first}" /><br>
是否为最后一个位置:<c:out value="${s.last}" /><br>
</c:forEach>

8.<c:forTokens> 用于浏览字符串,并根据指定的字符串截取字符串
语法:<c:forTokens items="stringOfTokens" delims="delimiters" [var="name" begin="begin" end="end" step="len" varStatus="statusName"]></c:forTokens>

 9.URL 操作标签

(1)<c:import> 把其他静态或动态文件包含到 JSP 页面。与<jsp:include>的区别是后者只能包含同一个web应用中的文件,前者可以包含其他web应用中的文件,甚至是网络上的资源。

语法:<c:import url="url" [context="context"] [value="value"] [scope="..."] [charEncoding="encoding"]></c:import>

        <c:import url="url"  varReader="name" [context="context"][charEncoding="encoding"]></c:import>

 看个例子:

(2)<c:redirect> 该标签用来实现请求的重定向。例如,对用户输入的用户名和密码进行验证,不成功则重定向到登录页面。或者实现Web应用不同模块之间的衔接

语法:<c:redirect url="url" [context="context"]/>

  或:<c:redirect url="url" [context="context"]>

            <c:param name="name1" value="value1">

       </c:redirect>

看个例子:

<c:redirect url="http://127.0.0.1:8080">
4 <c:param name="uname">lihui</c:param>
5 <c:param name="password">11111</c:param>
6 </c:redirect>

(3)<c:url> 用于动态生成一个 String 类型的URL,可以同上个标签共同使用,也可以使用HTML的<a>标签实验超链接。

语法:<c:url value="value" [var="name"] [scope="..."] [context="context"]>

            <c:param name="name1" value="value1">

       </c:url>

或:<c:url value="value" [var="name"] [scope="..."] [context="context"]/>

看个例子:

<c:url value="http://127.0.0.1:8080" var="url" scope="session">
9 </c:url>


10.格式化的使用:

<!-- 格式化日期 -->
<fmt:formatDate value="${date}" pattern="yyyy年MM月dd日 HH:mm:ss"/>
<!-- 格式化数字 -->
<fmt:formatNumber value="56.7436789" pattern="#.##"></fmt:formatNumber>


已有 0 条评论

    欢迎您,新朋友,感谢参与互动!