流程
JSP/Servlet
Tomcat
文件目录
---bin 启动、关闭的脚本文件
---conf 配置
|---server.xml 核心文件 可修改端口、主机名称等 默认8080
---lib 依赖的jar包
---logs 日志
---webapps 发存放的网站
默认端口
tomcat:8080
mysql:3306
http:80
https:443
网站
文件结构
---webapps Tomcat服务器的web目录
-ROOT
-xxxx 网站的目录名
|-WEB-INF
| |-class Java程序
| |-lib web应用所依赖的jar包
| |-web.xml 网站配置文件
|-index.html 默认首页
|-static
| |-css
| | |-style.css
| |-js
| |-img
|-...
Http
Http请求
Request URL
Request Method:GET
Status Code:200 OK
Remote Address:14.215.177.39:443
Http响应
Cache-Control:private 缓存控制
Connection:Keep-Alive 连接
Content-Encoding:gzip 编码
Content-Type:text/html 类型
响应体
Accept
Accept-Encoding
Accept-Language
Cache-Control
Connection
HOST
Refresh 定时刷新
Location 网页重定位
状态码
200
4xx: 资源不存在 4040
3xx:请求重定向
5xx: 服务器代码错误 500 502(网关错误)
Header
Accept
Accept-Encoding
Accept-Language
Cache-Control
Connection 请求结束后是否保持连接
...
Maven
环境配置
M2_HOME 目录\bin
MAVEN_HOME 目录
镜像配置
<mirror>
<id>nexus-aliyun</id>
<mirrorOf>central</mirrorOf>
<name>Nexus aliyun</name>
<url>http://maven.aliyun.com/nexus/content/groups/public</url>
</mirror>
本地仓库
<localRepository>D:\environment\Maven\apache-maven-3.8.3\maven-repo</localRepository>
IDEA中使用Maven
- 新建Maven项目 (选用模板)
- 注意 仓库和配置文件
- IDEA中查看 仓库和配置
- 等待项目初始化
- 这里就Ok了
创建普通Maven项目
- 新建Maven 不选用模板
- 同上
在IDEA中标记源码功能
在IDEA中配置tomcat
pom文件
pom.xml是Maven的核心配置文件
由于Maven约定大于配置,自己写的配置会有导不出的问题出现
解决方法:在pom中添加resources节点
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<excludes>
<exclude>**/*.properties</exclude>
<exclude>**/*.xml</exclude>
</excludes>
<filtering>false</filtering>
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
</build>
web.xml
用tomcat里的web.xml配置即可
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee
https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd"
version="5.0"
metadata-complete="true">
</web-app>
Servlet
继承HttpServlet 或 GenericServlet
前者是后者的继承
HelloServlet
- 构建一个普通的Maven项目,删除src目录,之后要建项目就可以在该目录下建module,这个空项目就是Maven的主项目
- Maven父子项目的关系
父项目中有
<modules>
<module>servlet-01</module>
</modules>
子项目中有
<parent>
<artifactId>xxxx</artifactId>
<groupId>com.kuang</groupId>
<version>1.0sSNAPSHOT</>
</parent>
相当于son extents parent
- Maven环境优化
- 修改web.xml为最新的
- 将maven的结构搭建完整(java和recourses包)
- 编写一个servlet程序
- 建一个普通类
- 继承HttpServlet、
- 重写自己需要的方法
- doGet
- doPost
- doDelete
- .........................
- 编写Servlet的映射
- 运行
Bug
原因:Tomcat10之后包名不再是"javax.servlet”,则是改为"jakarta.servlet"
解决办法:
第一种解决办法:Tomcat版本改为10以下的版本
第二种解决办法:“javax.servlet”改为"jakarta.servlet”
<dependency>
<groupId>jakarta.servlet.jsp</groupId>
<artifactId>jakarta.servlet.jsp-api</artifactId>
<version>3.0.0</version>
</dependency>
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
<version>5.0.0</version>
</dependency>
最后修改导入的包名
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
servlet原理
Mapping映射
url pattern 不是后缀行一定要加/
<servlet>
<servlet-name>Hello,world</servlet-name>
<servlet-class>com.learn.yys.Hello</servlet-class>
</servlet>
- 一个servlet对应一个映射路径
<servlet-mapping>
<servlet-name>Hello,world</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
- 一个servlet对应多个映射路径
<servlet-mapping>
<servlet-name>Hello,world</servlet-name>
<url-pattern>/hello1</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>Hello,world</servlet-name>
<url-pattern>/hellow2</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>Hello,world</servlet-name>
<url-pattern>/hello13</url-pattern>
</servlet-mapping>
- 一个servlet可以指用映射路径
<servlet-mapping>
<servlet-name>Hello,world</servlet-name>
<url-pattern>/hello/*</url-pattern>
</servlet-mapping>
-
默认请求路径
相当于index.html的地位 让Hello的Java成了index.html
<servlet-mapping>
<servlet-name>Hello,world</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
- 指定 后缀 等
<servlet-mapping>
<servlet-name>Hello,world</servlet-name>
<url-pattern>*.yys</url-pattern> //默认访问以.yys结尾的路径 注意*前不能加项目映射路径
// hello/sdf.yys 的访问也是默认走这个路径
</servlet-mapping>
- 优先级
指定大于默认
可以用来写404等
package com.learn.yys;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
public class ErrorServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setCharacterEncoding("utf-8");
resp.setContentType("text/html");
PrintWriter writer = resp.getWriter();
writer.write("<h1>404 error</h1>");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doPost(req, resp);
}
}
<servlet>
<servlet-name>404</servlet-name>
<servlet-class>com.learn.yys.ErrorServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>404</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
ServletContext
web容器再启动的时候,会为每个web程序都创建一个对应的servletContext对象,它代表了当前的web应用
作用:
- 共享数据
在这个Servlet中保存的数据,可以在另一个servlet中拿到
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext servletContext = this.getServletContext();
String name = "yys";
servletContext.setAttribute("name",name);
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext servletContext = this.getServletContext();
String name = (String) servletContext.getAttribute("name");
resp.getWriter().println(name);
}
- 获取初始化参数
<context-param>
<param-name>database</param-name>
<param-value>jdbc:mysql//localhost:3306/mybatis</param-value>
</context-param>
<servlet>
<servlet-name>getParam</servlet-name>
<servlet-class>GetParam</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>getParam</servlet-name>
<url-pattern>/get_param</url-pattern>
</servlet-mapping>
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext servletContext = this.getServletContext();
String database = servletContext.getInitParameter("database");
resp.getWriter().println(database);
}
- 请求转发
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext servletContext = this.getServletContext();
// RequestDispatcher requestDispatcher = servletContext.getRequestDispatcher("/get_param");//转发请求路径
// requestDispatcher.forward(req,resp);//调用forward实现转发
servletContext.getRequestDispatcher("/get_param").forward(req,resp);
}
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>Dispatcher</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/dispatcher</url-pattern>
</servlet-mapping>
- 读取资源文件
java包和recourses包的内容打包后都在classes目录下
称之为classpath
这里会有资源导出的问题 在java包内的properties可能导不出
需要在pom里添加配置
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
InputStream inputStream = this.getServletContext().getResourceAsStream("/WEB-INF/classes/db.properties");
Properties properties = new Properties();
properties.load(inputStream);
String name = properties.getProperty("name");
String password = properties.getProperty("password");
resp.getWriter().println(name+":"+password);
}
HttpServletResponse
负责向浏览器发送数据的方法
public ServletOutputStream getOutputStream() throws IOException;
public PrintWriter getWriter() throws IOException;
负责向浏览器发送响应头的方法
各种set和add
常见应用
-
向浏览器输出信息
-
下载文件
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //1. 获取文件路径 String realPath = "E:\\code\\JavaWeb\\MyJavaWeb\\lesson2\\target\\lesson2-1.0-SNAPSHOT\\WEB-INF\\classes\\db.properties"; System.out.println("下载文件的路径:"+realPath); //2. 下载的文件名 String fileName = realPath.substring(realPath.lastIndexOf("//") + 1); //3. 设置让浏览器支持下载 中文文件名URLEncoder resp.setHeader("Content-Disposition","attachment;filename="+ URLEncoder.encode(fileName,"UTF-8")); //4. 获取下载文件的输入流 FileInputStream fileInputStream = new FileInputStream(realPath); //5. 创建缓冲区 int len = 0; byte[] buffer = new byte[1024]; //6. 获取OutputStream对象 ServletOutputStream outputStream = resp.getOutputStream(); //7. 将FileOutputStream流写入buffer缓冲区,使用OutputStream将缓冲区中数据输出到客户端 while ((len = fileInputStream.read(buffer))>0){ outputStream.write(buffer,0,len); } outputStream.close(); fileInputStream.close(); }
验证码
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//浏览器3秒刷新一次
resp.setHeader("refresh","3");
//在内存中创建图片
BufferedImage bufferedImage = new BufferedImage(80, 20, BufferedImage.TYPE_INT_RGB);
//得到图片
Graphics2D graphics2D = (Graphics2D)bufferedImage.getGraphics();//笔
//设置图片背景颜色
graphics2D.setColor(Color.WHITE);
graphics2D.fillRect(0,0,80,20);
//给图片写数据
graphics2D.setColor(Color.BLACK);
graphics2D.setFont(new Font(null,Font.BOLD,20));
graphics2D.drawString(makeNum(),0,20);
//告诉浏览器 请求用图片方式打开
resp.setContentType("image/jpg");
//网站存在缓存,让浏览器不缓存
resp.setDateHeader("expires",-1);
resp.setHeader("Cache-Control","no-cache");
resp.setHeader("Pragma","no-cache");
//把图片给浏览器
ImageIO.write(bufferedImage,"jpg",resp.getOutputStream());
}
private String makeNum()
{
Random random = new Random();
String num = random.nextInt(9999999)+"";
StringBuffer sb = new StringBuffer();
for (int i = 0;i<7-num.length();i++)
sb.append("0");
num = sb.append(num).toString();
return num;
}
重定向
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.sendRedirect("/lesson2_war/image");
}
注意完整的url
HttpServletRequest
- 获取前端传递的参数
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
resp.setCharacterEncoding("utf-8");
PrintWriter writer = resp.getWriter();
String username = req.getParameter("username");
String pwd = req.getParameter("password");
writer.println(username+":"+pwd);
writer.println("-------------------");
Map<String, String[]> parameterMap = req.getParameterMap();
for (Map.Entry<String, String[]> stringEntry : parameterMap.entrySet()) {
writer.println(stringEntry.getKey()+":"+ Arrays.toString(stringEntry.getValue()));
}
Enumeration<String> parameterNames = req.getParameterNames();
while (parameterNames.hasMoreElements())
writer.println(parameterNames.nextElement());
writer.println("-------------------");
String[] hobbies = req.getParameterValues("hobbies");
writer.println(Arrays.toString(hobbies));
}
- 请求转发
req.getRequestDispatcher("/success.jsp").forward(req,resp); /代表当前项目目录
Cookie
服务端给客户端一个信件,客户端下次访问服务端带上信件即可
客户端技术(响应,请求)
Cookie类的各种方法
注意中文字符问题 URLEncoder
Session
服务端登记来过,下次来时服务端匹配客户端
服务端技术,保存会话信息
- 服务器会给每个用户(浏览器)创建一个session对象
- 一个session独占一个浏览器,只要浏览器没关,session就存在
Session类的各种方法
手动注销
session.invalidate();
自动注销在xml中设置
<session-config>
<session-timeout>15</session-timeout>//这里是min不是s
</session-config>