JavaWeb 我的学习笔记
一、动态网页开发
1.动态网页
动态网页介绍
动态网页是指能在服务器端运行、使用程序语言设计的交互式网页。它们会根据某种条件(如时间、用户输入、数据库内容等)的变化,返回不同的网页内容。这种变化不是由静态的HTML代码直接实现的,而是依赖于服务器端的程序逻辑和数据库交互。
例如: 日常浏览器的搜索页面,根据不同的操作,返回不同的页面
动态网页相对于静态网页来说,页面代码虽然没有变,但是显示的内容却是可以随着时间、环境或者数据库操作的结果而发生改变的。
2.系统架构
C/S架构
Client/Server(客户端/服务器)
C/S架构的特点: 需要安装特定的客户端软件。
优点:
- 速度快:软件中的大部分数据都是集成到客户端软件当中,很少量的数据从服务器端传送过来,所以C/S结构的系统速度快
- 体验好:速度又快,界面又炫酷,体验好
- 界面炫酷:专门的语言去实现界面,更加灵活
- 服务器压力小:因为大量的数据都是集成在客户端软件当中,所以服务器只需要传送很少的数据量,当然服务器压力小。
- 安全性高:因为大量的数据都是集成在客户端软件当中,所以服务器虽然只有一个,就算服务器那边地震了,火灾了,服务器受损,问题也不大,因为大量的数据都在多个客户端上有缓存,有存储,所以从这个方面说,C/S结构的系统比较安全。
缺点:
升级维护比较差劲,升级维护比较麻烦,成本高,每个客户端软件都需要升级,有一些软件不是那么容易安装的。
B/S架构
B/S(Browser/Server,浏览器/服务器)
实际上B/S结构的系统还是一个C/S,只不过这C比较特殊,这个Client是一个固定不变浏览器软件。
优点:
- 升级维护方便,成本比较低(只需要升级服务器端即可。)
- 不需要安装特定的客户端软件,用户操作及其方便。只需要浏览器,输入网址即可
缺点:
- 速度慢:不是因为宽带低的原因,是因为所有的数据都是在服务器上,用户发送的每应该请求都是需要服务器全身心的响应数据,所有B/S结构的系统在网络中传送的数据量比较大。
- 体验差:界面不是那么炫酷
- 不安全:所有数据都在服务器上,只要服务器挂了,最终数据全部丢失。
开发B/S结构的系统,其实就是开发网站,其实就是开发一个Web系统
B/S与C/S的比较
名称 | B/S架构 | C/S架构 |
---|---|---|
软件安装 | 浏览器 | 需要专门的客户端 |
升级维护 | 客户端维护方便 | 客户端需要单独维护升级 |
平台相关 | 与操作系统平台关系不大 | 对客户端操作系统一般有限制 |
性能安全 | 在响应速度上和安全成本上需要花费更多的设计成本 | 能充分发挥客户端处理能力,客户端响应更快 |
3.URL通信三要素
- IP地址:电子设备(计算机)在网络中的唯一标识。
- 端口:应用程序在计算机中的唯一标识。 0~65536
- 传输协议:规定了数据传输的规则,如http, ftp等
4.Tomcat服务器
1.Tomcat简介
服务器介绍:
服务器:安装了服务器软件的计算机
服务器软件:接收用户的请求,处理请求,做出响应
在web服务器软件中,可以部署web项目,让用户通过浏览器来访问这些项目
Tomcat就是web服务器的一种
2. Tomcat的目录结构:
官方下载地址:https://tomcat.apache.org/
3. Tomcat基本使用
- 进入到Tomcat的目录中bin目录中 进入cmd 输入startup.bat
- Tomcat服务器的启动文件在bin目录中:startup.bat 就是Tomcat的启动文件。
- Tomcat服务器的停止文件也在bin目录中:shutdown.bat 就是Tomcat的停止文件
- 启动Tomcat服务器之后, 能够正常访问 http://localhost:8080
问题分析解决
- 启动一闪而过
原因: 没有配置环境变量。
解决办法: 配置上JAVA_HOME环境变量 - 报错: Address already in use : JVM_Bind
原因: 端口被占用
解决办法: 找到使用该端口的进程 结束进程
正确启动关闭tomcat
4.IDEA集成Tomcat
创建Tomcat
配置Tomcat
tomcat各项功能介绍
二、Servlet
1.Servlet简介
运行在服务器端的小程序
-
- Servlet就是一个接口,定义了java类被浏览器访问到(tomcat识别到)的规则。
- Servlet就javaweb三大组件之一,三大组件分别是
Servlet程序
Filter过滤器
Listener监听器
Servlet是在服务器端运行的Java程序,可以接收客户端请求并做出响应
Servlet可以动态生成HTML内容对客户端进行响应
Servlet与JSP都可以动态生成HTML内容
2.Servlet快速入门
入门样例
1.创建javaWEB项目
2.导入依赖
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
</dependency>
3.定义一个类,实现Servlet接口,在service方法里,输出内容
public class ServletTest1 implements Servlet {
@Override
public void init(ServletConfig servletConfig) throws ServletException {
}
@Override
public ServletConfig getServletConfig() {
return null;
}
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("Hello Servlet");
}
@Override
public String getServletInfo() {
return null;
}
@Override
public void destroy() {
}
4.配置web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app
version="4.0"
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:javaee="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xml="http://www.w3.org/XML/1998/namespace"
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">
<display-name>Archetype Created Web Application</display-name>
<!--配置Servlet-->
<!--servlet标签给tomcat配置Servlet程序-->
<servlet>
<!--servlet-name标签Servlet程序起一个别名(一般用于类名)-->
<servlet-name>ServletTest1</servlet-name>
<!--servlet-class是Servlet程序的全类名-->
<servlet-class>com.chq.ServletTest1</servlet-class>
</servlet>
<!--servlet-mapping标签给Servlet程序配置访问地址-->
<servlet-mapping>
<!--servlet-name标签的作用是告诉服务器,
我们当前配置的地址给那个Servlet程序使用-->
<servlet-name>ServletTest1</servlet-name>
<!--url-pattern标签配置访问地址
/ 斜杠在服务器解析的时候,表示地址为:http://ip:port/工程路劲
/hello表示地址为:http://ip:port/工程路劲/hello -->
<url-pattern>/hello</url-pattern>
</servlet-mapping>
</web-app>
5.配置启动Tomcat 在浏览器中访问 http://localhost:8080/ServletTest1/hello
6.观察控制台 打印出Hello Servlet
执行原理
- 当服务器接受到客户端浏览器的请求后,会解析请求URL路劲,获取访问的Servlet的资源路劲
- 查找web.xml文件,是否有对应的
<url-pattern>
标签内容 - 如果有,则在找到对应的
<servlet-class>
全类名 - tomcat会将字节码文件加载到内存,并且创建其对象
- 调用方法
执行过程
浏览器——>Tomcat服务器——>我们的应用——>应用中的web.xml——>Servlet类——>响应浏览器
3.Servlet的体系结构
GenericServlet——抽象类:将Servlet接口中其他方法做了默认空实现,只将service()方法作为抽象,将来定义servlet类时,可以继承GenericServlet,实现service()方法即可
public class ServletTest2 extends GenericServlet{
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("Hello GenericServlet");
}
}
HttpServlet——抽象类:对http协议的一种封装,简化操作
- 定义类继承HttpServlet
- 复写doGet/doPost方法
public class ServletTest3 extends HttpServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("get请求");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("post请求");
}
}
注意:
- 继承了HttpServlet,需要重写里面的doGet和doPost方法来接收get方式和post方式的请求。
- 为了实现代码的可重用性,我们只需要在doGet或者doPost方法中一个里面提供具体功能即可,而另外的那个方法只需要调用提供了功能的方法,不实现功能浏览器会报405错误
4.servlet的十大方法
方法名 | 说明 |
---|---|
init(HTTPServletConfig config) | 被servlet容器调用与指明一个servlet被放进服务中,当Servlet第一次被请求的时候Servlet容器会调用这个方法,在后续的请求中不会被再次调用 |
destroy() | 被servletcontainer调用以告知一个servlet它被剔除服务,当销毁Servlet的时候,该方法被调用 |
service(HttpServletRequest request,HttpServletResponse response) | 被servlet容器调用以允许servlet响应一个请求,每当请求Servlet的时候多会调用一次。 |
doGet(httpServletRequest request,HttpServletResponse response) | 被server调用处理客户端的GET请求。 |
doPost(HttpServletRequest request,HttpServletResponse response) | 被server调用处理客户端的POST请求。 |
doPut(HttpServletRequest request,HttpServletResponse response) | 被server调用处理客户端的DELETE请求。 |
doDelete(HttpServletRequest request,HttpServletResponse response) | 被server调用处理客户端的DELETE请求。 |
getServletInfo() | 返回有关Servlet的信息,例如作者、版本、版权。 |
getServletConfig() | 被server调用处理客户端的Head请求. |
doHead(HttpServletRequest request,HttpServletResponse response): | 被server调用处理客户端的Head请求. |
5.Servlet生命周期
服务器启动时,会在web.xml文件中找到servlet文件的配置并创建servlet的实例
- init()|第一次访问servlet的时候调用,全过程仅执行一次(初始化);
- service()|每一次访问servlet的时候调用(处理请求和响应);
- destroy()| 清理或销毁,服务器关闭。
6.在web.xml中配置servlet
1.servlet的名字,包装
<servlet>
<!--为servlet取的名字-->
<servlet-name>ServletTest1</servlet-name>
<!--指明为哪一个servlet类起个名字,名字要写全限定名;-->
<servlet-class>com.chq.ServletTest1</servlet-class>
</servlet>
<!--serlvet一般情况是有用户第 一次访问的时候才初始化,
如果需要应用程序一启动就初始化,需要配置load-on-startup-->
<servlet>
<servlet-name>ServletTest1</servlet-name>
<servlet-class>com.chq.ServletTest1</servlet-class>
<!--当值为0或者大于0时,表示容器在应用启动时就加载这个servlet,正数的值越小,启动该servlet的优先级越高-->
<load-on-startup>1</load-on-startup>
</servlet>
2.映射、访问的地址(url)
<!--用于映射一个已注册的servlet的一个对外访问路径-->
<servlet-mapping>
<!--与上面的servlet名字要完全一样,指明为哪一个servlet类配置对外访问路径-->
<servlet-name>ServletTest1</servlet-name>
<!--运行时地址栏显示的文件名,指明对外访问资源路径-->
<url-pattern>/hello</url-pattern>
</servlet-mapping>
同一个Servlet可以被映射到多个URL上,即多个 <servlet-mapping>
的<servlet-name>
的值,可以是同一个Servlet
3.配置默认首页: <welcome-file-list>
4.session有效期的设置
<session-config>
<session-timeout>300</session-timeout>
</session-config>
5.servlet全局参数的配置
<context-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</vontext-param>
6.servlet的注解方式。
通过web.xml方式配置servlet是web3.0版本以前常用的方式,那么在3.0版本后,使用注解的方式代替配置文件。
支持注解配置,可以不需要web.xml了
servlet注解方式
注解: @WebServlet(value=“/myServlet1”,name = “MyServlet”)
参数名称 | 说明 |
---|---|
String name() default ”“ | 名字 |
String[] value() default {} | 获取参数值 |
String[] urlPatterns() default {} | 访问路径 |
int loadOnStartup() default -1 | 启动时机 |
WebInitParam[] initParams() default {} | 初始化参数 |
loadOnStartup | servlet初始化时机,默认是第一次访问servlet的时候初始化 这个时候loadOnStartup值为-1. |
@WebServlet("/test2")
public class ServletTest2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("get方式于注解测试");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("post方法注解测试");
}
}
//控制台打印:get方式于注解测试
控制台出现中文乱码:
在VM options上加上-Dfile.encoding=utf-8
Servlet的映射方式
- 具体名称的方式。访问的资源路径必须和映射配置完全相同。(常用) 如上述例子
- / 开头 + 通配符的方式。只要符合目录结构即可,不用考虑结尾是什么
- 通配符 + 固定格式结尾的方式。只要符合固定结尾格式即可,不用考虑前面的路径
//只要请求符合这个目录结构/ServletTest/, 后面无论是什么都能匹配到这个
@WebServlet("/ServletTest/*")
//匹配所有, 任何请求都能匹配到这个
@WebServlet("/*")
//匹配所有以.cxk结尾的请求
@WebServlet("*.cxk")
Servlet的多路径映射
我们可以给一个 Servlet 配置多个访问映射,从而可以让不同的请求路径来访问相同的Servlet。
//@WebServlet里面可以写多个路径, 使用{}包裹,用逗号分隔
@WebServlet({
"/test3","/test4","/test5"})
三 Request(请求)
1.Request继承体系
2.Request的功能
- 获取请求行(getContextPath、getServletPath、getRequestURI,getQueryString) 包含HTTP方法、请求URL和HTTP版本。
- 获取请求头(getHeader) 包含多个键值对,用于传递额外的信息给服务器。
- 获取请求体(getReader / getInputStream) 用于POST、PUT等包含数据的请求方法,包含要发送给服务器的数据。
3.请求消息数据
请求行
关于请求方式:HTTP协议有7种请求方式,常用的有两种:
- GET:请求参数在请求行中(url中);请求的url有长度限制;不太安全
- POST:请求参数在请求体中;请求的url没有长度限制;相对安全
- 请求方式 请求url 请求协议/版本
请求头
- 键值对。是客户端浏览器告诉服务器的信息。
- 关于几个重要的请求头键/值:
User-Agent:浏览器告诉服务器"我是哪个版本的浏览器"。这样服务器才能"对症下药",解决浏览器兼容性问题
Referer:告诉服务器"我的请求的来源"。这被用于 防盗链 和 统计工作。
请求空行: 就是个空行。分割了 请求头 和 请求体
请求体: POST方式有请求体,GET方式没有。流的形式获取。
4.Request获取请求数据
- 请求行
方法 | 描述 |
---|---|
String getMethod() | 获取请求方式:GET |
String getContextPath() | 获取虚拟目录 (重要) |
String getServletPath() | 获取Servlet路劲 |
String getQueryString() | 获取get方式请求参数 |
String getRequestURI() | 获取请求URI (重要) |
StringBuffer getRequestURL() | 获取get方式请求参数,获取请求URL |
String getProtocol() | 获取协议版本:HTTP/1.1 |
String getRemoteAddr() | 获取客户机的IP地址 |
样例:
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse resp){
// 1. String getMethod()获取请求方式
String method = request.getMethod();
System.out.println("method = " + method);
//2. String getContextPath()获取虚拟目录
String contextPath = request.getContextPath();
System.out.println("contextPath = " + contextPath);
//3. String getServletPath()获取Servlet路劲
String servletPath = request.getServletPath();
System.out.println("servletPath = " + servletPath);
//4. String getQueryString()获取get方式请求参数
String queryString = request.getQueryString();
System.out.println("queryString = " + queryString);
//5. String getRequestURL()获取请求URL
String requestURI = request.getRequestURI();
System.out.println("requestURI = " + requestURI);
//6. StringBuffer getRequestURL()获取get方式请求参数
StringBuffer requestURL = request.getRequestURL();
System.out.println("requestURL = " + requestURL);
//7. String getProtocol()获取协议版本
String protocol = request.getProtocol();
System.out.println("protocol = " + protocol);
//8. String getRemoteAddr()获取客户机的IP地址
String remoteAddr = request.getRemoteAddr();
System.out.println(