1、Http
1.1 什么是Http
http的意思是超文本传输协议(Hyper Text Transfer Protocol,HTTP)是一个简单的请求-响应协议,它通常运行在TCP之上。
它指定了客户端可能发送给服务器什么样的消息以及得到什么样的响应。请求和响应消息的头以ASCII形式给出;而消息内容则具有一个类似MIME的格式。这个简单模型是早期Web成功的有功之臣,因为它使开发和部署非常地直截了当。
Http:
文本:html,字符串
超文本:图片、音乐、视频、定位、地图……
默认端口号:80
Https: 安全的
默认端口号:443
1.2 两个时代
-
http1.0
HTTP/1.0:客户端可以与web服务器连接后,只能获得一个web资源
-
http2.0
HTTP/1.1:客户端可以与web服务器连接后,能获得多个web资源
1.3 Http请求
客户端—发送请求—服务器
百度请求:
Request URL: https://www.baidu.com/ //请求 URL
Request Method: GET //请求方法get
Status Code: 200 OK //状态代码: 200
Remote Address: 180.101.49.11:443 //远程地址
Accept: text/html
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6 //语言
Cache-Control: max-age=0
Connection: keep-alive
请求行:
请求行的请求方式:GET/POST
消息头:
Accept: 告诉浏览器,它所支持的数据类型
Accept-Encoding: 支持哪种编码格式 GBK UTF-8 GB2312 ISO8859-1
Accept-Language: 告诉浏览器,它的语言环境
Cache-Control: 缓存控制
Connection: 告诉浏览器请求完成是断开还是保持连接
HOST: 主机
1.4 Http响应
服务器—响应—客户端
百度响应:
Cache-Control: private //缓存控制
Connection: keep-alive //连接
Content-Encoding: gzip //编码
Content-Type: text/html;charset=utf-8 //类型
响应体:
Accept: 告诉浏览器,它所支持的数据类型
Accept-Encoding: 支持哪种编码格式 GBK UTF-8 GB2312 ISO8859-1
Accept-Language: 告诉浏览器,它的语言环境
Cache-Control: 缓存控制
Connection: 告诉浏览器请求完成是断开还是保持连接
HOST: 主机
Refresh: 告诉客户端多久刷新
Location: 让网页重新定位
响应状态:
200:请求响应成功
3xx:请求重定向–重新到我给的新位置去
404:找不到资源
5xx:服务器代码错误 -----502网关错误
2、Maven
自动导入和配置jar包
Maven的核心思想:约定大于配置
有约束,不要去违反
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<!-- 配置的GAV -->
<groupId>org.example</groupId>
<artifactId>JavaWeb</artifactId>
<!-- 项目的打包方式
jar: java应用
war: javaweb应用
-->
<packaging>war</packaging>
<version>1.0-SNAPSHOT</version>
<name>JavaWeb Maven Webapp</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<!-- 具体依赖的jar包配置文件 -->
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<finalName>JavaWeb</finalName>
</build>
</project>
3、Servlet
3.1 Servlet 简介
servlet是Java Servlet的简称,称为小服务程序或服务连接器,用Java编写的服务器端程序,主要功能在于交互式地浏览和修改数据,生成动态Web内容。
Servlet可以响应任何类型的请求,但绝大多数情况下Servlet只用来扩展基于HTTP协议的Web服务器。
开发步骤:
1、编写一个类,实现servlet接口
2、把开发好的Java类部署到web服务器中
把实现了servlet接口的Java程序叫做servlet
Servlet接口在Sun公司有两个默认的实现类:HttpServlet,GenericServlet;
3.2 Maven项目
maven 父子项目:子项目可以用父项目的 jar 包(类似继承关系)
主项目pom.xml
<parent>
<artifactId>ServletTest</artifactId>
<groupId>org.example</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
子项目pom.xml
<modules>
<module>Servlet-01</module>
</modules>
3.3 HelloServlet
编写 servlet 映射:web.xml
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>Archetype Created Web Application</display-name>
<!-- 一个servlet对应一个类-->
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>com.servlet.HelloServlet</servlet-class>
</servlet>
<!-- servlet的请求路径-->
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>hello</url-pattern>
</servlet-mapping>
</web-app>
主类 HelloServlet:
package com.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
PrintWriter writer = resp.getWriter(); //获得响应流
writer.println("Hello,Servlet");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp); //和get处理方式一样,可以直接调用
}
}
3.4 ServletContext
3.4.1 共享数据:
在这个 Servlet 中保存的数据,可以在另一个 Servlet 中拿到;
放置类:
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class ContextTest extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext context = this.getServletContext();
String username = "zhiqi";
context.setAttribute("username",username);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
读取类:
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class GetServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext context = this.getServletContext();
String username = (String) context.getAttribute("username");
resp.setContentType("text/html");
resp.setCharacterEncoding("utf-8");
resp.getWriter().print("名字"+username);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req,resp);
}
}
web.xml
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>ContextTest</servlet-class>
</servlet>
<!-- servlet的请求路径-->
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>get</servlet-name>
<servlet-class>GetServlet</servlet-class>
</servlet>
<!-- servlet的请求路径-->
<servlet-mapping>
<servlet-name>get</servlet-name>
<url-pattern>/get</url-pattern>
</servlet-mapping>
3.4.2 获取初始化参数
<!-- 配置web初始化应用的参数-->
<context-param>
<param-name>url</param-name>
<param-value>jdbc:mysql://localhost:3306/mybatis</param-value>
</context-param>
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext context = this.getServletContext();
String url = context.getInitParameter("url");
resp.getWriter().print(url);
}
3.4.3 请求转发
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext context = this.getServletContext();
RequestDispatcher requestDispatcher = context.getRequestDispatcher("/Init"); //转发请求路径
requestDispatcher.forward(req,resp); //调用forward实现请求转发
}
3.4.4 读取资源文件
Properties:
在java目录下新建properties
在resources目录下新建properties
都被打包到了同一个路径下:classes ---- 类路径
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext context = this.getServletContext();
InputStream in = context.getResourceAsStream("/WEB-INF/classes/db.properties");
Properties properties = new Properties();
properties.load(in);
String username = properties.getProperty("username");
String password = properties.getProperty("password");
resp.getWriter().print(username+":"+password);
}
3.5 HttpServletResponse
web服务器接收到客户端 http 请求,针对这个请求,分别创建一个代表请求的HttpServletRequest 对象,代表响应的一个HttpServletResponse;
- 如果要获取客户端请求过来的参数:找HttpServletRequest
- 如果要获取客户端请求过来的参数:找HttpServletResponse
3.5.1 负责向浏览器发送数据的方法
public ServletOutputStream getOutputStream() throws IOException;
public PrintWriter getWriter() throws IOException; //写中文用
3.5.2 下载文件
文件路径一定要写对,找了半天bug!气吐血……
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.FileInputStream;
import java.io.IOException;
public class FileServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String path = "D:\\ANewStart\\ServletTest\\response\\target\\classes\\lan.jpg";
System.out.println("地址"+path);
String filename = path.substring(path.lastIndexOf("\\") + 1); //截取\后面的文件名
resp.setHeader("Content-Disposition", "attachment;filename=" + filename);
//获取下载文件的输入流
FileInputStream in = new FileInputStream(path);
//创建缓冲区
int len = 0;
byte[] buffer = new byte[1024];
//获取OutputStream输出对象
ServletOutputStream out = resp.getOutputStream();
//循环将输入流读入到缓冲区当中,(len=in.read(buffer))>0就表示in里面还有数据
while ((len=in.read(buffer))>0){
// 使用FileOutputStream输出流将缓冲区的数据写入到指定的目录
out.write(buffer,0,len);
}
in.close();
out.close();
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
3.5.3 生成3s刷新的验证码图片
import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;
public class ImageServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//设置浏览器3s刷新一次
resp.setHeader("refresh","3");
//在内存中创建一张图片
BufferedImage image = new BufferedImage(80, 20, BufferedImage.TYPE_INT_RGB);
//得到图片 g 看作一支笔
Graphics2D g = (Graphics2D) image.getGraphics();
//设置图片的背景颜色 填充
g.setColor(Color.white);
g.fillRect(0,0,80,20);
//给图片写数据
g.setColor(Color.BLUE);
g.setFont(new Font(null,Font.BOLD,20));
g.drawString(makeNum(),0,20);
//告诉浏览器图片打开方式
resp.setContentType("image/jpeg");
//网站存在缓存,不让浏览器缓存
resp.setDateHeader("expires",-1);
resp.setHeader("Cache-Control","no-cache");
resp.setHeader("Pragma","no-cache");
//把图片写给浏览器 --- jpg 格式化名字
ImageIO.write(image,"jpg",resp.getOutputStream());
}
//创建随机字符串
private String makeNum(){
Random random = new Random();
String s = random.nextInt(9999999)+""; //随机生成字符串---加""变字符串
StringBuffer sb = new StringBuffer();
for (int i = 0; i < 7-s.length(); i++) {
sb.append("0"); //保证每次都是七位数
}
s = sb.toString()+s;
return s;
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
3.5.4 重定向
重定向和转发的区别:
相同点:页面都会实现跳转
不同点:请求转发的时候,url不会产生变化;重定向的时候,url地址栏会发生变化(/img 和 /resp/img 的区别)
/*
resp.setHeader("Location","/resp/img");
resp.setStatus(302);//302代表重定向
*/
resp.sendRedirect("/resp/img");
index.jsp
<html>
<body>
<h2>Hello World!</h2>
<%--这里提交的路径,需要寻找到项目的路径
pageContext.request.contextPath 代表当前项目
--%>
<form action="${pageContext.request.contextPath}/login" method="get">
用户名:<input type="text" name="username"><br>
密码:<input type="password" name="password"><br>
<input type="submit">
</form>
</body>
</html>
RequestTest:
public class RequestTest extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//处理请求
String username = req.getParameter("username");
String password = req.getParameter("password");
System.out.println(username+":"+password);
resp.sendRedirect("/resp/success.jsp");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
web.xml----由于web版本过低,导致路径不对一直404,踩坑大神又双叒叕踩坑了……
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
</web-app>
3.6 HttpServletRequest
3.6.1 获取前端传递的参数
返回字符串和字符串数组
3.6.2 请求转发
public class RequestTest extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//防止中文乱码
req.setCharacterEncoding("utf-8");
resp.setCharacterEncoding("utf-8");
String username = req.getParameter("username");
String password = req.getParameter("password");
String[] hobbies = req.getParameterValues("hobby");
System.out.println(username);
System.out.println(password);
System.out.println(Arrays.toString(hobbies));
//通过请求转发 /代表当前的web应用
req.getRequestDispatcher("/success.jsp").forward(req,resp);
}
}
4、Cookie
保存会话的两种技术
cookie:客户端技术(响应、请求)
session:服务器技术,利用这个技术可以保存用户的会话信息,存储信息和数据
得到一个cookie:
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//解决中文乱码
req.setCharacterEncoding("utf-8");
resp.setCharacterEncoding("utf-8");
PrintWriter out = resp.getWriter();
//服务器端从客户端获取cookie,返回数组可能代表存在多个
Cookie[] cookies = req.getCookies();
if (cookies != null){
out.write("你上次访问的时间是");
for (int i = 0; i < cookies.length; i++) {
Cookie cookie = cookies[i];
if(cookie.getName().equals("time")){ //获得cookie的键
//获取cookie的值,解析成字符串
long l = Long.parseLong(cookie.getValue());
Date date = new Date(l);
out.write(date.toLocaleString());
}
}
}else {
out.write("这是您第一次访问本站");
}
Cookie cookie = new Cookie("time", System.currentTimeMillis()+"");
cookie.setMaxAge(24*60*60); //设置cookie有效期为1天
resp.addCookie(cookie); //响应给客户端一个cookie
}
删除cookie:
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//创建的cookie和要删除的一样
Cookie cookie = new Cookie("time", System.currentTimeMillis()+"");
//设置有效期为0 相当于覆盖掉之前的cookie
cookie.setMaxAge(0);
resp.addCookie(cookie);
}
编码和解码:防止中文乱码
URLEncoder.encode("","UTF-8"); //解码
URLDecoder.decode(cookie.getValue(),"UTF-8"); //解码
5、session
- 服务器会给每一个用户创建一个session对象;
- 一个session独占一个浏览器,只要浏览器没有关闭,这个session就存在;
- 用户登录之后,整个网站它都可以访问!保存用户信息,保存购物车信息
session 的 ID 放在 cookie中:
//session创建的时候做了什么
Cookie cookie = new Cookie("JSESSIONID",id);
resp.addCookie(cookie);
获取session 的 ID:
public class SessionDemo1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("UTF-8");
resp.setCharacterEncoding("UTF-8");
resp.setContentType("text/html;charset=utf-8");
//得到session
HttpSession session = req.getSession();
session.setAttribute("name",new Person("zhqi",20));
String id = session.getId();
//判断session是不是新创建
if(session.isNew()){
resp.getWriter().write("session创建成功"+id);
}else {
resp.getWriter().write("session已经在服务器中存在了"+id);
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req,resp);
}
}
注销session:
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//得到session
HttpSession session = req.getSession();
session.removeAttribute("name");
//手动注销session
session.invalidate();
}
session和cookie的区别:
- cookie是把用户的数据写给用户的浏览器,浏览器保存(可以保存多个)
- session把用户的数据写到用户独占session中,服务器端保存(保存重要的信息,减少服务器资源的浪费)
- session对象由服务创建
6、JSP
6.1 什么是JSP
java server pages:java服务器端页面,和servlet 一样,用于动态web技术
jsp 和 html 区别:
写法相似;
HTML只会给用户提供动态数据,JSP页面中可以嵌入JAVA代码,为用户提供动态数据
6.2 JSP原理
浏览器向服务器发送请求,不管访问什么资源,其实都是在访问servlet
jsp最终也会被转换成为一个Java类
JSP本质上就是一个servlet
//初始化
public void _jspInit() {
}
//销毁
public void _jspDestroy() {
}
//JSPService
public void _jspService(HttpServletRequest request, HttpServletResponse response)
1、判断请求
2、内置一些对象
final javax.servlet.jsp.PageContext pageContext; //页面上下文
final javax.servlet.ServletContext application; //applicationContext
final javax.servlet.ServletConfig config; //config
javax.servlet.jsp.JspWriter out = null; //out
final java.lang.Object page = this; //page:当前页
3、输出页面前增加的代码
response.setContentType("text/html; charset=UTF-8"); //设置响应的页面类型
pageContext = _jspxFactory.getPageContext(this, request, response,
null, false, 8192, true);
_jspx_page_context = pageContext;
application = pageContext.getServletContext();
config = pageContext.getServletConfig();
out = pageContext.getOut();
_jspx_out = out;
4、以上的这些对象可以在jsp页面中直接使用
在jsp页面中:
Java 代码会原封不动的输出;
html 代码会被转换成 out.write("\r\n"); 这样的格式输出到前端。
6.3 JSP基本语法
JSP表达式
<%-- JSP表达式 <%= 变量或者表达式%>写Java代码
作用:用来将程序输出到客户端
--%>
<%= new java.util.Date()%>
JSP脚本片段
<%--JSP脚本片段--%>
<%
int sum=0;
for (int i = 0; i < 100; i++) {
sum+=i;
}
out.println("<h1>"+sum+"</h1>");
%>
脚本片段再实现
<%
int x = 10;
out.println(x);
%>
<p>这是一个JSP文档</p>
<%
out.println(x); //上面定义的下面也可以用
%>
<%--在代码里嵌入html元素--%>
<%
for (int i = 0; i < 5; i++) {
%>
<h3>hello world <%=i%> </h3>
<%
}
%>
JSP声明
会被编译到JSP生成java的类中(方法外面),其他的会被生成到_jspService方法中
<%! %>
JSP导包
<%@page import="java.util.Date" %>
跳转错误页面
<%@ page errorPage="error/500.jsp" %>
web.xml错误页面配置
<error-page>
<error-code>500</error-code>
<location>/error/500.jsp</location>
</error-page>
jsp指令-include
<%-- 将两个页面二合一 --%>
<%@include file="header.jsp"%>
<h1>网页主体</h1>
<%@include file="footer.jsp"%>
<%-- jsp标签 拼接页面,本质还是三个--%>
<jsp:include page="header.jsp"/>
<h1>网页主体</h1>
<jsp:include page="footer.jsp"/>
6.4 九大内置对象
setattribute–设置属性,保存数据
- pageContext
- Request
- Response
- Session
- Application
- Config
- out
- page
- exception
request:客户端向服务器发送请求,产生的数据,用户看完了就没用了,比如新闻;
session:客户端向服务器发送请求,产生的数据,用户看完了一会还有用,比如购物车;
application:客户端向服务器发送请求,产生的数据,一个用户用完了,其他用户还可能使用,比如聊天数据;
<%@ page contentType="text/html;charset=UTF-8" language="java"isELIgnored="true" %>
<html>
<head>
<title>pageContext</title>
</head>
<body>
<%
pageContext.setAttribute("name1","1号"); //保存的数据只在一个页面中有效
request.setAttribute("name2","2号"); //保存的数据只在一次请求中有效,请求转发会携带这个数据
session.setAttribute("name3","3号"); //保存的数据只在一次页面中有效,从打开浏览器到关闭浏览器
application.setAttribute("name4","4号"); //保存的数据只在服务器中有效,从打开服务器到关闭服务器
%>
<%
//从pageContext取出,我们通过寻找的方式来
//从底层到高层(作用域):page->request->session->application
String n1= (String) pageContext.findAttribute("name1");
String n2= (String) pageContext.findAttribute("name2");
String n3= (String) pageContext.findAttribute("name3");
String n4= (String) pageContext.findAttribute("name4");
String name5= (String) pageContext.findAttribute("name5"); //不存在
%>
<h1>取出的值:</h1>
<h3>${name1}</h3> <%--EL表达式取的是setAttribute中的name1--%>
<h3>${name2}</h3>
<h3>${name3}</h3>
<h3>${name4}</h3>
<h3>${name5}</h3> <%--不显示--%>
<h3><%=name5%></h3> <%--显示null--%>
<h3><%=n1%></h3> <%--<%=n1%>取的是string的--%>
<h3><%=n2%></h3>
<h3><%=n3%></h3>
<h3><%=n4%></h3>
</body>
</html>