JavaWeb的一些重点
Maven
此处将在后面出专门的案例和配置(五一)
Tomcat
此处将在后面出专门的案例和配置(五一)
Http
HTTP协议:Hyper Text Transfer Protocol(超文本传输协议),是用于从万维网(World Wide Web)服务器传输超文本到本地浏览器的传送协议。
HTTP是一个基于TCP/IP通信协议来传递数据(HTML 文件, 图片文件, 查询结果等)。
-
HTTP协议工作于客户端-服务端架构上。浏览器作为HTTP客户端通过URL向HTTP服务端即WEB服务器发送所有请求。
-
Web服务器有:Apache服务器,IIS服务器(Internet Information Services)等。
-
Web服务器根据接收到的请求后,向客户端发送响应信息。
-
HTTP默认端口号为80,但是你也可以改为8080或者其他端口。
以下图表展示了HTTP协议通信流程:
HTTP三点注意事项:
- HTTP是无连接:无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。
- HTTP是媒体独立的:这意味着,只要客户端和服务器知道如何处理的数据内容,任何类型的数据都可以通过HTTP发送。客户端以及服务器指定使用适合的MIME-type内容类型。
- HTTP是无状态:HTTP协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快。
客户端请求消息
客户端发送一个HTTP请求到服务器的请求消息包括以下格式:请求行(request line)、请求头部(header)、空行和请求数据四个部分组成。
服务器响应消息
HTTP响应也由四个部分组成,分别是:状态行、消息报头、空行和响应正文。
HTTP状态码
下面是常见的HTTP状态码:
- 200 - 请求成功
- 301 - 资源(网页等)被永久转移到其它URL
- 404 - 请求的资源(网页等)不存在
- 500 - 内部服务器错误
分类 | 分类描述 |
---|---|
1** | 信息,服务器收到请求,需要请求者继续执行操作 |
2** | 成功,操作被成功接收并处理 |
3** | 重定向,需要进一步的操作以完成请求 |
4** | 客户端错误,请求包含语法错误或无法完成请求 |
5** | 服务器错误,服务器在处理请求的过程中发生了错误 |
HTTP content-type
常用
Content-Type: text/html; charset=utf-8
Servlet
JSP语法(淘汰)
其实原理也是在Servlet中写java代码
Cookie、Session
Cookie
Cookie是客户端技术,程序把每个用户的数据以cookie的形式写给用户各自的浏览器。当用户使用浏览器再去访问服务器中的web资源时,就会带着各自的数据去。这样,web资源处理的就是用户各自的数据了。
(百度百科)Cookie,有时也用其复数形式 Cookies。类型为“小型文本文件”,是某些网站为了辨别用户身份,进行Session跟踪而储存在用户本地终端上的数据(通常经过加密),由用户客户端计算机暂时或永久保存的信息 [1] 。
Java提供的操作Cookie的API
Java中的javax.servlet.http.Cookie类用于创建一个Cookie
Cookie类的主要方法 | |||
---|---|---|---|
No. | 方法 | 类型 | 描述 |
1 | [Cookie](https://www.cnblogs.com/xdp-gacl/p/3803033.html#Cookie(java.lang.String, java.lang.String))(String name, String value) | 构造方法 | 实例化Cookie对象,传入cooke名称和cookie的值 |
2 | public String getName() | 普通方法 | 取得Cookie的名字 |
3 | public String getValue() | 普通方法 | 取得Cookie的值 |
4 | public void setValue(String newValue) | 普通方法 | 设置Cookie的值 |
5 | public void setMaxAge(int expiry) | 普通方法 | 设置Cookie的最大保存时间,即cookie的有效期,当服务器给浏览器回送一个cookie时,如果在服务器端没有调用setMaxAge方法设置cookie的有效期,那么cookie的有效期只在一次会话过程中有效,用户开一个浏览器,点击多个超链接,访问服务器多个web资源,然后关闭浏览器,整个过程称之为一次会话,当用户关闭浏览器,会话就结束了,此时cookie就会失效,如果在服务器端使用setMaxAge方法设置了cookie的有效期,比如设置了30分钟,那么当服务器把cookie发送给浏览器时,此时cookie就会在客户端的硬盘上存储30分钟,在30分钟内,即使浏览器关了,cookie依然存在,在30分钟内,打开浏览器访问服务器时,浏览器都会把cookie一起带上,这样就可以在服务器端获取到客户端浏览器传递过来的cookie里面的信息了,这就是cookie设置maxAge和不设置maxAge的区别,不设置maxAge,那么cookie就只在一次会话中有效,一旦用户关闭了浏览器,那么cookie就没有了,那么浏览器是怎么做到这一点的呢,我们启动一个浏览器,就相当于启动一个应用程序,而服务器回送的cookie首先是存在浏览器的缓存中的,当浏览器关闭时,浏览器的缓存自然就没有了,所以存储在缓存中的cookie自然就被清掉了,而如果设置了cookie的有效期,那么浏览器在关闭时,就会把缓存中的cookie写到硬盘上存储起来,这样cookie就能够一直存在了。 |
6 | public int getMaxAge() | 普通方法 | 获取Cookies的有效期 |
7 | public void setPath(String uri) | 普通方法 | 设置cookie的有效路径,比如把cookie的有效路径设置为"/xdp",那么浏览器访问"xdp"目录下的web资源时,都会带上cookie,再比如把cookie的有效路径设置为"/xdp/gacl",那么浏览器只有在访问"xdp"目录下的"gacl"这个目录里面的web资源时才会带上cookie一起访问,而当访问"xdp"目录下的web资源时,浏览器是不带cookie的 |
8 | public String getPath() | 普通方法 | 获取cookie的有效路径 |
9 | public void setDomain(String pattern) | 普通方法 | 设置cookie的有效域 |
10 | public String getDomain() | 普通方法 | 获取cookie的有效域 |
response接口也中定义了一个addCookie方法,它用于在其响应头中增加一个相应的Set-Cookie头字段。 同样,request接口中也定义了一个getCookies方法,它用于获取客户端提交的Cookie。
package com.xgm.cookie;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.Date;
/*
* 存入并读取name和写入时间
* */
@WebServlet(name = "CookieServlet01",urlPatterns = "/CookieServlet01")
public class CookieServlet01 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setCharacterEncoding("utf-8");
request.setCharacterEncoding("utf-8");
Cookie[] cookies = request.getCookies();
PrintWriter out = response.getWriter();
if (cookies!=null){
for (int i = 0; i < cookies.length; i++) {
Cookie cookie = cookies[i];
//打印cookie中的name的value
if (cookie.getName().equals("name")){
//解码 URLDecoder.decode()
System.out.println(URLDecoder.decode(cookie.getValue(),"utf-8"));
out.println(URLDecoder.decode(cookie.getValue(),"utf-8"));
}
//打印cookie中的时间value
if (cookie.getName().equals("lastTime")){
System.out.println(cookie.getValue().getClass().getSimpleName());
//必须先把时间戳转换成long类型
long l = Long.parseLong(cookie.getValue());
/* public Date(long date) {
fastTime = date;
}*/
Date date = new Date(l);
System.out.println(date);
out.println(date.toLocaleString());
}
}
}else {
System.out.println("null");
out.println("null");
}
//最好用 URLEncoder.encode() 设置编码格式
Cookie name = new Cookie("name", URLEncoder.encode("xuguanming","utf-8"));
Cookie lastTime = new Cookie("lastTime", System.currentTimeMillis()+"");
//设置coolie存在时间,s为单位
name.setMaxAge(30);
lastTime.setMaxAge(30);
response.addCookie(name);
response.addCookie(lastTime);
}
}
Session
- Session对象存储特定用户会话所需的属性及配置信息。这样,当用户在应用程序的Web页之间跳转时,存储在Session对象中的变量将不会丢失,而是在整个用户会话中一直存在下去。
- Session 对象最常见的一个用法就是存储用户的首选项。
- Session是服务器端技术,利用这个技术,服务器在运行时可以为每一个用户的浏览器创建一个其独享的session对象,由于session为用户浏览器独享,所以用户在访问服务器的web资源时,可以把各自的数据放在各自的session中,当用户再去访问服务器中的其它web资源时,其它web资源再从用户各自的session中取出数据为用户服务。
简单理解就是一个当你打开浏览器就会自动创建的对象,可以存储大量的用户信息,一个用户对应一个Session对象
HttpSession
-
HttpSession:在服务器端保持 HTTP 状态信息的方案,和其对应的是Cookie 。
-
产生HttpSession对象的过程:
当程序需要为某个客户端的请求创建一个session时,服务器首先检查这个客户端的请求里是否包含了一个session标识(即Session ID),如果已经包含一个Session ID则说明以前已经为此客户创建过session,服务器就按照Session ID把这个session检索出来使用(如果检索不到,可能会新建一个,这种情况可能出现在服务端已经删除了该用户对应的session对象,但用户人为地在请求的URL后面附加上一个JSESSION的参数)。如果客户请求不包含Session ID,则为此客户创建一个session并且生成一个与此session相关联的Session ID,这个Session ID将在本次响应中返回给客户端保存。
-
使用Cookie来跟踪Session:
session通过Session ID来区分不同的客户, session是以cookie或URL重写为基础的,默认使用cookie来实现,系统会创造一个名为JSESSIONID的输出cookie,这称之为session cookie,以区别persistent cookies(也就是我们通常所说的cookie),session cookie是存储于浏览器内存中的,并不是写到硬盘上的。
HttpSession的生命周期
创建一个HttpSession对象:
- 一个常见的错误是以为session在有客户端访问时就被创建(若第一次访问某Web应用的一个JSP页面,且该页面的page指定的Session属性为false,此时就不会产生Session对象)。
- 某server端程序(如Servlet)调用HttpServletRequest.getSession(true) 或者 HttpServletRequest.getSession()这样的语句时才会被创建。
- 若第一次访问某Web应用的一个JSP页面,且该页面的page指定的Session属性为true,则服务器会自动为该页面分配一个HttpSession对象。
package com.xgm.session;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import java.io.IOException;
/*
查看Session ID
*并存name进入session ,也可以存对象
* */
@WebServlet(name = "SessionDemo01",urlPatterns = "/SessionDemo01")
public class SessionDemo01 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setCharacterEncoding("utf-8");
response.setHeader("content-type","text/html;charset=utf-8");
HttpSession session = request.getSession();
session.setAttribute("name","许冠铭");
String id = session.getId();
System.out.println(id);
if (session.isNew()){
response.getWriter().write("session创建成功,ID:"+id);
}
else {
response.getWriter().write("session已经存在了,ID:"+id);
}
/*
* session创建的时候做了什么事情
Cookie cookie = new Cookie("JSESSIONID", id);
response.addCookie(cookie);
* */
}
}
package com.xgm.session;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
/*
* 取session中的name
* */
@WebServlet(name = "SessionDemo02",urlPatterns = "/SessionDemo02")
public class SessionDemo02 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setCharacterEncoding("utf-8");
response.setHeader("content-type","text/html;charset=utf-8");
HttpSession session = request.getSession();
String name = (String) session.getAttribute("name");
System.out.println(name);
}
}
销毁HttpSession对象:
- 程序调用HttpSession.invalidate()
- 距离上一次收到客户端发送的session id时间间隔超过了session的最大有效时间
- 服务器进程被停止
package com.xgm.session;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
/*
* 销毁HttpSession对象
* */
@WebServlet(name = "SessionDemo03",urlPatterns = "/SessionDemo03")
public class SessionDemo03 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setCharacterEncoding("utf-8");
response.setHeader("content-type","text/html;charset=utf-8");
HttpSession session = request.getSession();
session.getAttribute("name");
//注销
session.invalidate();
}
}
注意:关闭浏览器只会使存储在客户端浏览器内存中的session cookie失效,不会使服务器端的session对象
失效。
HttpSession的相关API
- 获取Session对象:request.getSession()、request.getSession(boolean create)
- 属性相关的:setAttribute、getAttribute、removeAttribute
- 使HttpSession失效:HttpSession.invalidate()
- 设置最大时效:settMaxInactiveInterval()
Session使用的具体例子-购物车
原文链接:https://blog.csdn.net/qq_37308779/article/details/82048800
cookie 和session 的区别
-
cookie数据存放在客户的浏览器上,session数据放在服务器上。
-
cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗
考虑到安全应当使用session。 -
session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能
考虑到减轻服务器性能方面,应当使用COOKIE。 -
单个cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个cookie。
-
所以个人建议:
-
将登陆信息等重要信息存放为SESSION
-
其他信息如果需要保留,可以放在COOKIE中
-
JavaBean
MVC模式
MVC模式是软件工程中常见的一种软件架构模式,该模式把软件系统(项目)分为三个基本部分:模型(Model)、视图(View)和控制器(Controller)。
- 视图(View):负责界面的显示,以及与用户的交互功能,例如表单、网页等。
- 控制器(Controller):可以理解为一个分发器,用来决定对于视图发来的请求,需要用哪一个模型来处理,以及处理完后需要跳回到哪一个视图。即用来连接视图和模型。
- 模型(Model):模型持有所有的数据、状态和程序逻辑。模型接受视图数据的请求,并返回最终的处理结果。
在MVC模式中,视图View可以用JSP/HTML/CSS实现,模型Model可以用JavaBean实现,而控制器Control就可以用Servlet来实现。
MVC模式的流程如下:浏览器通过视图向控制器发出请求,控制器接收到请求之后通过选择模型进行处理,处理完请求以后再转发到视图,进行视图界面的渲染并做出最终响应。
三层架构
“三层”是指表示层(USL,User Show Layer)、业务逻辑层(BLL,Business Logic Layer)、数据访问层(DAL,Data Access Layer,三层中使用的数据,是通过实体类(封装数据的JavaBean)来传递的。实体类一般放在entity包下。
1.数据访问层(DAL)
数据访问层也称为持久层,位于三层中的最下层,用于对数据进行处理。该层中的方法一般都是**“原子性”的,即每个方法都不可再分。比如,可以在DAL层中实现数据的增删改查操作,而增、删、改、查四个操作是非常基本的功能,都是不能再拆分的。**
在程序中,DAL一般写在dao包中,包里面的类名也是以“Dao”结尾,如StudentDao.java、DepartmentDao.java、NewsDao.java等;换句话说,在程序中,DAL是由dao包中的多个“类名Dao.java”组成。每个“类名Dao.java”类,就包含着对该“类名”的所有对象的数据操作,如StudentDao.java中包含对Student对象的增、删、改、查等数据操作,DepartmentDao.java中包含对Department对象的增、删、改、查等数据操作。
2.业务逻辑层(BLL)
位于三层中的中间层(DAL与USL中间),起到了数据交换中承上启下的作用,用于对业务逻辑的封装。BLL的设计对于一个支持可扩展的架构尤为关键,因为它扮演了两个不同的角色。对于DAL而言,它是调用者;对于USL而言,它是被调用者。依赖与被依赖的关系都纠结在BLL上。
使用上,就是对DAL中的方法进行“组装”。比如,该层也可以实现对Student对象的增删改查,但与DAL不同的是,BLL中的增、删、改、查不再是 “原子性”的功能,而是包含了一定的业务逻辑。比如该层中的“删”不再像DAL中那样仅仅实现“删”,而是在“删”之前要进行业务逻辑的判断:先查找该学生是否存在(即先执行DAL层的“查”),如果存在才会真正地“删”(再执行DAL层的“删”),如果该学生不存在则应该提示错误信息。即BLL中的“删”,应该是“带逻辑的删”(即先“查”后“删”),也就是对DAL中的“查”和“删”两个方法进行了“组装”。
在程序中,BLL一般写在service包(或biz包)中,包里面的类名也是以“Service(或Biz)”结尾,如StudentService.java、DepartmentService.java、NewsService等。换句话说,在程序中,BLL是由service包中的多个“类名Service.java”组成。每个“类名Service.java”类,就包含着对该“类名”的对象的业务操作,如StudentService.java中包含对Student对象的“带逻辑的删”、“带逻辑的增”等业务逻辑操作,DepartmentService.java中包含对所有Department对象的“带逻辑的删”、“带逻辑的增”等业务逻辑操作。
3.表示层(USL)
位于三层中的最上层,用于显示数据和接收用户输入的数据,为用户提供一种交互式操作的界面。USL又分为“USL前台代码”和“USL后台代码”,其中“USL前台代码”是指用户能直接访问到的界面,一般是程序的外观(如html文件、JSP文件等),类似于MVC模式中的“视图”;“USL后台代码”是指用来调用业务逻辑层的JAVA代码(如Servlet),类似于MVC模式中的“控制器”。表示层前台代码一般放在WebContent目录下,而表示层后台代码目前放在servlet包下。
MVC模式与三层架构的关系
MVC模式和三层架构,是分别从两个不同的角度去设计的,但目的都是“解耦,分层,代码复用等”。
Filter(过滤器)
实现Filter接口
在web客户端和servlet之间添加一层过滤器来实现对请求的过滤。
应用场景
- 自动登录
- 统一设置编码格式
- 访问权限控制
- 敏感字符过滤等
过滤器:
CharacterEncodingFilter
package com.xgm.filter;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
/*
* 实现Filter接口
* */
@WebFilter(filterName = "CharacterEncodingFilter",urlPatterns = "/sb1/*")
public class CharacterEncodingFilter implements Filter {
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("filter初始化");
}
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
servletRequest.setCharacterEncoding("utf-8");
servletResponse.setCharacterEncoding("utf-8");
servletResponse.setContentType("text/html;charset=UTF-8");
//让请求继续运行,固定格式,不写则会在治理被拦截停止
filterChain.doFilter(servletRequest,servletResponse);
}
public void destroy() {
System.out.println("filter被销毁");
}
}
servlet
ShowServlet
package com.xgm.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet(name = "ShowServlet",urlPatterns = "/sb1/ShowServlet")
public class ShowServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.getWriter().write("你是煞笔");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
具体操作可学习:https://blog.csdn.net/yuzhiqiang_1993/article/details/81288912
监听器(少用)
实现监听器的接口:
HttpSessionListener
等等很多的监听器接口
jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
<h1>当前有<span><%=this.getServletConfig().getServletContext().getAttribute("name")%></span> 人在线</h1>
<%=application.getAttribute("name")%>
</body>
</html>
监听器
Listener
package com.xgm.listen;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
/*
* 浏览网站session监听器
* */
public class Listener implements HttpSessionListener {
//一旦创建了Session就会触发这个事件
public void sessionCreated(HttpSessionEvent se) {
ServletContext cxt = se.getSession().getServletContext();
Integer name = (Integer) cxt.getAttribute("name");
if (name==null){
name = new Integer(1);
}else {
int count = name.intValue();
name = new Integer(count+1);
}
cxt.setAttribute("name",name);
}
public void sessionDestroyed(HttpSessionEvent se) {
ServletContext cxt = se.getSession().getServletContext();
Integer name = (Integer) cxt.getAttribute("name");
if (name==null){
name = new Integer(0);
}else {
int count = name.intValue();
name = new Integer(count-1);
}
cxt.setAttribute("name",name);
}
}
xml配置
<!-- 注册监听器-->
<listener>
<listener-class>com.xgm.listen.Listener</listener-class>
</listener>
1、监听三大作用域创建和销毁的监听器
ServletContextListener | 监听ServletContext域的创建销毁 |
HttpSessionListener | 监听Session域的创建销毁 |
ServletRequestListener | 监听request域的创建销毁 |
2、监听三大作用域中属性变化的监听器(创建、更新、销毁)
ServletContextAttributeListener | 监听ServletContext域中属性的变化 |
HttpSessionAttributeListener | 监听Session域中属性的变化 |
ServletRequestAttributeListener | 监听request域中属性的变化 |
3、监听JavaBean在Session域中状态变化的监听器
HttpSessionBindingListener | 监听javabean在session域中添加和销毁事件 |
HttpSessionActivationListener | 让javabean自己感知到自己随着session被钝化和活化。 |