# Javaweb学习 **Repository Path**: hongxiaohan/javaweb_learning ## Basic Information - **Project Name**: Javaweb学习 - **Description**: Javaweb学习 - **Primary Language**: Java - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 0 - **Created**: 2020-08-20 - **Last Updated**: 2024-12-22 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # JavaWeb # 1、基础概念 ## 1.1、前言 web开发: - web---》指网页开发的意思、指可以在网络上任何网站上获取他们服务器响应回来的资源。www.baidu.com - 静态web - html css - 提供的数据是静态的、始终不会改变 - 动态web - 淘宝、百度。。。。。。 - 提供的数据是动态的、每个人访问的内容都有所不同、不同时间看到不同内容。 - 技术栈:Servlet/JSP、ASP、PHP 在java中、动态web资源开发的技术统称为JavaWeb; ## 1.2、web应用程序 web应用程序:可以提高给浏览器访问的程序。 - a.html、b.html。。。。。多个web资源、这些web资源可以被外界访问。对外界提供服务。 - 能访问到任何一个页面或者资源、都存在世界的任何一个角落的计算机上。 - URL(统一资源定位符)。 - 统一的资源的web资源会被放在一个文件夹。(web应用程序)----->Tomcat(服务器) - 一个web应用由多部分组成(静态web、动态web) - html、css、js - jsp、servlet - java程序 - jar包 - 配置文件(Properties) web应用程序编写完后、要被外界访问得部署到服务器上统一管理。 ## 1.3、静态web - *.html、*.css、这些静态资源页面的后缀,如果服务器一直有存在这些东西、我们就可以直接进行读取(网络) ![输入图片说明](https://images.gitee.com/uploads/images/2020/0820/105251_318274b1_7346127.png "image-20200819103807919.png") - 静态web存在的缺点 - web页面无法动态更新所有用户看到的都是同一个页面。 - 轮播图、点击特效:伪特效。 - JavaScript(实际开发、拥有最多)。 - 无法和数据库交互(数据无法持久化、用户无法交互)。 ## 1.4、动态web 页面动态展示:web页面展示的效果因人而异。 ![输入图片说明](https://images.gitee.com/uploads/images/2020/0820/105402_13cc3212_7346127.png "image-20200819104537733.png") ### 缺点: - 假如服务器的动态web资源出现了错误、我们需要重新编写我们的后台程序、重新发布。 - 停机维护 ### 优点: - Web页面动态更新。所有用户看到的数据不一样 - 它可以和数据库进行交互(数据可以持久化) ![输入图片说明](https://images.gitee.com/uploads/images/2020/0820/105414_3978bf80_7346127.png "image-20200819104938027.png") # 2、web服务器 ## 2.1、技术类型 **ASP** - 微软(国内最早流行的); - 在HTML中嵌入VB脚本、ASP + COM; **PHP** - PHP开发速度快、功能强大、跨平台、代码容易 - 无法承载大访问量的情况(局限性) **JSP/Servlet** B/S:浏览器和服务器 C/s:客户端和服务器 - sun公司主推的B/S架构 - 基于java语言的(所有的大公司、或者一些开源的组件、都是用java写的) - 可以承载三高问题带来的影响 - 语法像ASP、ASP---->JSP、加强市场的竞争度 ## 2.2、web服务器 **Tomcat** ![](https://bkimg.cdn.bcebos.com/pic/b3b7d0a20cf431adfe004e4e4e36acaf2fdd98f2?x-bce-process=image/resize,m_lfit,w_268,limit_1/format,f_jpg) Tomcat是Apache 软件基金会(Apache Software Foundation)的Jakarta 项目中的一个核心项目,由[Apache](https://baike.baidu.com/item/Apache/6265)、Sun 和其他一些公司及个人共同开发而成。由于有了Sun 的参与和支持,最新的Servlet 和JSP 规范总是能在Tomcat 中得到体现,Tomcat 5支持最新的Servlet 2.4 和JSP 2.0 规范。因为Tomcat 技术先进、性能稳定,而且免费,因而深受Java 爱好者的喜爱并得到了部分软件开发商的认可,成为目前比较流行的Web 应用服务器。 Tomcat 服务器是一个免费的开放源代码的Web 应用服务器,属于轻量级应用[服务器](https://baike.baidu.com/item/服务器),在中小型系统和并发访问用户不是很多的场合下被普遍使用,是开发和调试JSP 程序的首选。对于一个初学者来说,可以这样认为,当在一台机器上配置好Apache 服务器,可利用它响应[HTML](https://baike.baidu.com/item/HTML)([标准通用标记语言](https://baike.baidu.com/item/标准通用标记语言/6805073)下的一个应用)页面的访问请求。实际上Tomcat是Apache 服务器的扩展,但运行时它是独立运行的,所以当你运行tomcat 时,它实际上作为一个与Apache 独立的进程单独运行的。 Tomcat 实际上运行JSP 页面和Servlet。目前Tomcat最新版本为9.0.37**。** # 3、HTTP ## 3.1、什么是HTTP HTTP(超文本协议)是一个简单的请求-响应协议、它通常运行在TCP之上。 - 文本:html、字符串.... - 超文本:图片、音乐、视频、地图..... - 80端口 HTTPS:安全的 - 443端口 ## 4.2、两个时代 - http1.0 - Http/1.0:客户端可以与web服务器连接只能获得一个web资源 - http2.0 - Http/1.1:客户端可以与web服务器连接可以获得多个web资源 ## 百度 ### 4.1、请求行 - 请求行的请求方式:GET - 请求方式:GET POST HAED DELETE PUT... - GET:请求携带的参数比较少、大小有限制, 会在浏览器的URL地址栏上显示内容、不安全、但是高效。 - POST:请求携带的参数没有限制、大小没有限制、不会在浏览器的URL地址栏显示内容、安全、但是不高效 ### 4.2、消息头 ```java Accept:告诉浏览器、它所支持的数据类型 Accept-Encoding:支持哪种编码格式 GBK UTF-8 GB2312 ISO8859-1 Accept-Language:告诉浏览器、它的语言环境 Cache-Control:缓存控制 Connection:告诉浏览器、请求完成是断开还是保持连接 Host:主机 ``` ### 4.3、Http请求Request - 客户端----发请求(Request)-----服务器 ```java Request URL: https://www.baidu.com/ 请求地址 Request Method: GET 请求方法(GET、POST) Status Code: 200 OK 状态码:200(正常) Remote Address: 14.215.177.39:443 远程地址 ``` ```java Accept:text/html Accept-Encoding: gzip, deflate, br Accept-Language: zh-CN,zh;q=0.9 Cache-Control: max-age=0 Connection: keep-alive ``` ### 4.4、Http响应Response - 服务器---响应(Response)----客户端 ```java Cache-Control: private 缓存控制 Connection: keep-alive 保持连接 Content-Encoding: gzip 编码 Content-Type: text/html;charset=utf-8 类型 ``` #### 1、响应体 ```java Accept:告诉浏览器、它所支持的数据类型 Accept-Encoding:支持哪种编码格式 GBK UTF-8 GB2312 ISO8859-1 Accept-Language:告诉浏览器、它的语言环境 Cache-Control:缓存控制 Connection:告诉浏览器、请求完成是断开还是保持连接 Host:主机 ``` #### 2、响应状态码 200:请求响应成功 200 3xx:请求重定向 - 重定向:重新定位位置 4xx:找不到资源 404 - 资源不存在 5xx: 服务器代码错误 500 # 4、Servlet ## 4.1、什么是Servlet? Servlet(Server Applet)是[Java](https://baike.baidu.com/item/Java/85979) Servlet的简称,称为小服务程序或服务连接器,用Java编写的[服务器](https://baike.baidu.com/item/服务器/100571)端程序,具有独立于平台和[协议](https://baike.baidu.com/item/协议/13020269)的特性,主要功能在于交互式地浏览和生成数据,生成动态[Web](https://baike.baidu.com/item/Web/150564)内容。 狭义的Servlet是指Java语言实现的一个接口,广义的Servlet是指任何实现了这个Servlet接口的类,一般情况下,人们将Servlet理解为后者。Servlet运行于支持Java的应用服务器中。从原理上讲,Servlet可以响应任何类型的请求,但绝大多数情况下Servlet只用来扩展基于HTTP协议的Web服务器。 最早支持Servlet标准的是JavaSoft的Java [Web Server](https://baike.baidu.com/item/Web Server/9306055),此后,一些其它的基于Java的Web服务器开始支持标准的Servlet。 ## 4.2、HelloServlet **1、定义HelloServlet类** (继承HttpServlet接口重写 doGet() doPost()方法) ```java package cn.hxh.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; /** * @Author: HongXiaoHan * @Description * @Date: 2020/8/19 18:46 */ public class HelloServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setCharacterEncoding("utf-8"); PrintWriter writer = resp.getWriter(); writer.print("你好JavaWeb"); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { this.doGet(req,resp); } } ``` **2、配置Servlet** 在web.xml中配置: ```java helloServlet cn.hxh.servlet.HelloServlet helloServlet /hello ``` **3、配置Tomcat** ​ 注意:配置项目发布的路径 **4、启动测试 OK!** ![输入图片说明](https://images.gitee.com/uploads/images/2020/0820/105458_c21d1f11_7346127.png "image-20200819185250002.png") ![输入图片说明](https://images.gitee.com/uploads/images/2020/0820/105514_268a530f_7346127.png "image-20200819185302226.png") 这里的乱码可以通过setServletContext("text/html;charset=UTF-8")进行配置; ## 4.3、Servlet原理 Servlet是由Web服务器调用、web服务器在收到浏览器请求之后、会如图所示: ![输入图片说明](https://images.gitee.com/uploads/images/2020/0820/105936_cd9dc39a_7346127.png "image-20200819181702915.png") ## 4.4、ServletContext Web容器启动后的时候、它会为每个web程序创建一个对应的ServletContext对象。它代表当前的web应用。 ### 1、ServletContext对象 * 概念:代表Web应用、可以和程序的容器进行通讯 * 获取方法 * //获取context对象第一种方法 Request * ServletContext Context1 = req.getServletContext(); * //获取context对象第二种方法 HttpServlet * ServletContext Context2 = this.getServletContext(); * 功能: * 获取MIME类型 * MIME类型:互联网通讯过程定义的一种文件类型 * 格式 : 大类型/小类型 text/html image/jpeg ```java public class ContextDemo01 extends HttpServlet { @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //获取context对象第一种方法 Request ServletContext Context1 = req.getServletContext(); //获取context对象第二种方法 HttpServlet ServletContext Context2 = this.getServletContext(); /** * 单例模式 * 两个对象地址一样 */ } } ``` ### 2、共享数据 ![输入图片说明](https://images.gitee.com/uploads/images/2020/0820/105726_3bc9b42c_7346127.png "image-20200819183707269.png") **2.1编写ServletContext类** ```java package cn.hxh.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; import java.io.PrintWriter; /** * @Author: HongXiaoHan * @Description * @Date: 2020/8/19 18:46 */ public class ServletContext01 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { ServletContext servletContext = this.getServletContext(); String name = "洪潇涵"; //将数据存在ServletContext(以键值对形式存储) servletContext.setAttribute("user",name); System.out.println("user键内容存储成功"); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { this.doGet(req,resp); } } ``` ```java package cn.hxh.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; /** * @Author: HongXiaoHan * @Description * @Date: 2020/8/19 18:46 */ public class ServletContext02 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setCharacterEncoding("utf-8"); PrintWriter writer = resp.getWriter(); //获取ServletContext01存储的数据 String user = (String) this.getServletContext().getAttribute("user"); writer.print("你好"+user); System.out.println("获取ServletContext01数据成功"); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { this.doGet(req,resp); } } ``` **2.2将servlet注册到web.xml** ```xml ServletContext01 cn.hxh.servlet.ServletContext02 ServletContext02 cn.hxh.servlet.ServletContext01 ServletContext01 /a ServletContext02 /b ``` **2.3运行测试** 如果我们第一个访问的是/b 如图所示: ![输入图片说明](https://images.gitee.com/uploads/images/2020/0820/105604_3f35e428_7346127.png "image-20200819191810725.png") **原因:**获取不到存储的数据-->null 那是因为我们没有请求/a -->servlet 所以ServletContext并没有存储数据 如果我们第一个先访问的是/a 再访问/b 如图所示: ![输入图片说明](https://images.gitee.com/uploads/images/2020/0820/105737_d0f2f107_7346127.png "image-20200819192022424.png") 测试完毕! ### 3、获取初始化参数 ```xml url jdbc:mysql://localhost:3306/mybatis ``` ```java @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { ServletContext servletContext = this.getServletContext(); //获取初始化参数 String url = servletContext.getInitParameter("url"); resp.getWriter().print(url); } ``` ### 4、请求转发 ```java @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { ServletContext servletContext = this.getServletContext(); System.out.println("进入了ServletContext04"); servletContext.getRequestDispatcher("/c").forward(req,resp); } ``` * 重定向 * 资源的跳转 * resp.sendRedirect("跳转路径"); * 重定向特点 * 1、URL发生变化 * 2、请求2次 * 3、不能资源共享 * 4、可以访问本服务器之外的站点 * 转发特点 * 1、URL不发生变化 * 2、请求一次 * 3、资源共享 * 4、只能访问本服务器的资源 重定向是客户端路径 必须要加虚拟路径 转发是服务器路径不需要加虚拟路径 虚拟目录是可以改变的我们一个不能把一个虚拟路径写死了 而是使用一个变量保留虚拟目录的路径 这样子避免以后改虚拟路径的时候代码要进行改变 客户端路径 重定向、、form标签 ### 5、读取资源文件 Properties - 在java目录下新建properties - 在resources目录下新建properties 发现:都被打包到同一个路径下:classes、我们俗称为这路径为class path: 思路:需要一个文件流 ```properties username=root password=333 ``` ```java package cn.hxh.servlet; import javax.servlet.ServletContext; 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; import java.io.InputStream; import java.util.Properties; /** * @Author: HongXiaoHan * @Description properties读取配置文件 * @Date: 2020/8/19 20:52 */ @WebServlet("/e") //基于注解实现不需要注册 public class ServletContext05 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { ServletContext servletContext = this.getServletContext(); InputStream resourceAsStream = servletContext.getResourceAsStream("/WEB-INF/classes/db.properties"); Properties properties = new Properties(); properties.load(resourceAsStream); String username = properties.getProperty("username"); String password = properties.getProperty("password"); resp.getWriter().print(username+":"+password); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { this.doGet(req, resp); } } ``` 访问测试即可。 ![输入图片说明](https://images.gitee.com/uploads/images/2020/0820/105750_b47b5543_7346127.png "image-20200819212930458.png") ## 4.5HttpServletResponse web服务器接收客户端的Http请求、针对请求分别创建一个个 代表请求的HttpServletRequest 代表响应的HttpServletResponse - 如果要获取客户端请求过来的参数:HttpServletRequest - 如果给客户端响应信息: HttpServletResponse ### 1、简单分类 **负责向浏览器发送数据的常用方法:** ```java public ServletOutputStream getOutputStream() throws IOException; public PrintWriter getWriter() throws IOException; ``` **负责向浏览器发送响应体的常用方法:** ```java public void setCharacterEncoding(String charset); public void setContentType(String type); ``` **响应状态码:** ```java public static final int SC_CONTINUE = 100; public static final int SC_SWITCHING_PROTOCOLS = 101; public static final int SC_OK = 200; public static final int SC_CREATED = 201; public static final int SC_ACCEPTED = 202; public static final int SC_NON_AUTHORITATIVE_INFORMATION = 203; public static final int SC_NO_CONTENT = 204; public static final int SC_RESET_CONTENT = 205; public static final int SC_PARTIAL_CONTENT = 206; public static final int SC_MULTIPLE_CHOICES = 300; public static final int SC_MOVED_PERMANENTLY = 301; public static final int SC_MOVED_TEMPORARILY = 302; public static final int SC_FOUND = 302; public static final int SC_SEE_OTHER = 303; public static final int SC_NOT_MODIFIED = 304; public static final int SC_USE_PROXY = 305; public static final int SC_TEMPORARY_REDIRECT = 307; public static final int SC_BAD_REQUEST = 400; public static final int SC_UNAUTHORIZED = 401; public static final int SC_PAYMENT_REQUIRED = 402; public static final int SC_FORBIDDEN = 403; public static final int SC_NOT_FOUND = 404; public static final int SC_METHOD_NOT_ALLOWED = 405; public static final int SC_NOT_ACCEPTABLE = 406; public static final int SC_PROXY_AUTHENTICATION_REQUIRED = 407; public static final int SC_REQUEST_TIMEOUT = 408; public static final int SC_CONFLICT = 409; public static final int SC_GONE = 410; public static final int SC_LENGTH_REQUIRED = 411; public static final int SC_PRECONDITION_FAILED = 412; public static final int SC_REQUEST_ENTITY_TOO_LARGE = 413; public static final int SC_REQUEST_URI_TOO_LONG = 414; public static final int SC_UNSUPPORTED_MEDIA_TYPE = 415; public static final int SC_REQUESTED_RANGE_NOT_SATISFIABLE = 416; public static final int SC_EXPECTATION_FAILED = 417; public static final int SC_INTERNAL_SERVER_ERROR = 500; public static final int SC_NOT_IMPLEMENTED = 501; public static final int SC_BAD_GATEWAY = 502; public static final int SC_SERVICE_UNAVAILABLE = 503; public static final int SC_GATEWAY_TIMEOUT = 504; public static final int SC_HTTP_VERSION_NOT_SUPPORTED = 505; ``` ### 2、常见应用 **下载文件** 1. 要下载的文件路径 2. 下载文件名是什么? 3. 设置浏览器支持下载的文件 4. 获取下载文件流 5. 创建缓冲区 6. 获取OutputStream对象 7. 将FileOutputStream流写入buffer缓冲区 8. 使用OutputStream将缓冲区的数据输出到客户端 ```java package cn.hxh.servlet; 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; import java.io.PrintWriter; import java.net.URLDecoder; /** * @Author: HongXiaoHan * @Description * @Date: 2020/8/19 21:57 */ public class FileDowloadServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //获取下载的资源路径 FileInputStream in = new FileInputStream("D:\\Documents\\Pictures\\二次元\\8ceaabdd0d174bea1696e940bdde77cc.jpeg"); //设置响应头 resp.setHeader("Content-Disposition","attachment;filename="+URLDecoder.decode("Test.jpeg","UTF-8")); //获取输出流 ServletOutputStream outputStream = resp.getOutputStream(); //设置缓冲区 int len = 0; byte[] bytes = new byte[1024]; while ((len = in.read(bytes)) != -1) { outputStream.write(bytes,0,len); } in.close(); outputStream.close(); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { this.doGet(req, resp); } } ``` ### 3、验证码功能 验证码怎么来? - 前端实现 - 后端实现:用到Java的图片类、生成一个图片、响应到客户端 ```java package cn.hxh.servlet; import javax.imageio.ImageIO; 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.awt.*; import java.awt.image.BufferedImage; import java.io.IOException; import java.util.Random; /** * @Author: HongXiaoHan * @Description * @Date: 2020/8/19 22:29 */ @WebServlet("/images") public class ImagesServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { this.doPost(req,resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //如何让浏览器5秒后刷新 resp.setHeader("refresh","3"); //在内存中生成图片 BufferedImage image = new BufferedImage(80, 20, BufferedImage.TYPE_INT_RGB); //得到图片 Graphics2D graphics = (Graphics2D) image.getGraphics(); //设置图片背景颜色 graphics.setColor(Color.black); graphics.fillRect(0,0,80,20); //给图片写数据 graphics.setColor(Color.white); graphics.setFont(new Font(null,Font.BOLD,20)); graphics.drawString(getRandom(),0,20); resp.setContentType("image/jpeg"); //网站缓存关闭 resp.setDateHeader("expires",-1); resp.setHeader("Cache-Control","no-cache"); ImageIO.write(image,"jpg",resp.getOutputStream()); } public static String getRandom(){ Random random = new Random(); String s = random.nextInt(99999)+""; StringBuffer buffer = new StringBuffer(); for (int i = 0; i < 7; i++){ buffer.append(s); } String str = buffer.toString().substring(0, 4); return str; } } ``` ### 4、实现重定向 ![输入图片说明](https://images.gitee.com/uploads/images/2020/0820/110226_77f9e385_7346127.png "image-20200820110121149.png") B一个web资源收到A的请求后、B会去通知A去访问另一个web资源c、这个过程就是重定向。 **常见场景:** - 用户登录 ```java public void sendRedirect(String location) throws IOException; ``` 测试 ```java package cn.hxh.servlet; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; /** * @Author: HongXiaoHan * @Description * @Date: 2020/8/20 10:13 */ public class SendRedirectServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { this.doPost(req, resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.sendRedirect("/images"); } } ``` 面试题:请你聊聊重定向和转发的区别? 相同点: - 都会实现页面跳转。 不同点: - 重定向没有数据共享、转发有数据共享。 - 重定向是请求两个URL、转发只请求一次。 - 重定向可以访问的作用域是所有URL、转发只能访问当前的服务器URL。 - 重定向请求的URL会发生变化、转发的请求的URL不会发生变化。 ## 4.6HttpServletRequest ### 1、获取前端参数 **常用方法** ```java public String getParameter(String name); public String[] getParameterValues(String name); ``` **以下测试:** **前端:** ```jsp <%-- Created by IntelliJ IDEA. User: Administrator Date: 2020/8/19 Time: 22:24 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %>

Hello World!

点击下载
用户名: 密码:
``` ```jsp <%-- Created by IntelliJ IDEA. User: Administrator Date: 2020/8/20 Time: 10:39 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> Title 登陆成功 ``` **后端:** ```java package cn.hxh.servlet; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; /** * @Author: HongXiaoHan * @Description * @Date: 2020/8/20 10:26 */ public class RequestServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { this.doPost(req, resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String username = req.getParameter("username"); String password = req.getParameter("password"); System.out.println("用户名:"+username); System.out.println("密码:"+password); resp.sendRedirect(this.getServletContext().getContextPath()+"/success.jsp"); } } ``` 运行结果: ![输入图片说明](https://images.gitee.com/uploads/images/2020/0820/140538_4ec05bda_7346127.png "image-20200820111332604.png") ![输入图片说明](https://images.gitee.com/uploads/images/2020/0820/140544_4ee1acaf_7346127.png "image-20200820111313544.png") ### 2、请求转发 **编写后台** ```java package cn.hxh.servlet; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; /** * @Author: HongXiaoHan * @Description * @Date: 2020/8/20 11:18 */ public class ForWardServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { this.doPost(req, resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //转发学习 (记住转发的/是在当前服务器的默认路径 没有多级路径的情况下不要加入项目名的路径) req.getRequestDispatcher("success.jsp").forward(req,resp); } } ``` **注册Servlet到xml** ```xml ForWardServlet cn.hxh.servlet.ForWardServlet ForWardServlet /forward ``` **运行结果** ![输入图片说明](https://images.gitee.com/uploads/images/2020/0820/140408_b8a6aa34_7346127.png "image-20200820112223288.png") # 5、会话 **会话:**用户打开浏览器、点击的链接访问的web资源、一直到关闭浏览器。这一个过程就是会话。 **有状态会话:**一个同学来个教室、下次再来教室。我们就会知道这个同学曾经来过、这个过程就是有状态会话。 **如何证明你是一个学校的学生?** ​ 你 学校 1. 学校信息登记表 学校标记你是该学校学生 2. 学生证 学校给你学生证 **一个网站---->如何证明你来过?** ​ 客户端 服务端 1. 服务器给客户端一个信件、客户端下次访问服务器带上信件即可。-----> cookie 2. 服务器标记你来过了、下次你来访问时服务器来匹配你。----->Seesion ## 1、Cookie 1. 从请求拿到数据cookie信息 2. 服务器拿到cookie信息进行操作响应 ```java //常用方法 public Cookie(String name, String value);//构造方法 public void setMaxAge(int expiry);//持久化硬盘最大值时间 public String getName();//获取该cookie名字 public String getValue();//获取该cookie内容 public void setValue(String newValue);//设置该cookie内容 Cookie[] cookies = request.getCookies();//获取所有cookie ``` **案例:记住我上一次访问时间** **前端:** ```xml <%-- Created by IntelliJ IDEA. User: Administrator Date: 2020/8/20 Time: 11:53 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> Title

${pageContext.request.getAttribute("time")}

``` **后端:** ```java package cn.hxh.servlet; import javax.servlet.ServletException; 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.text.SimpleDateFormat; import java.util.Date; /** * @Author: HongXiaoHan * @Description * @Date: 2020/8/20 11:44 */ //保存用户上一次访问的时间 public class CookieServlet01 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { this.doPost(req, resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { SimpleDateFormat s = new SimpleDateFormat("yyyy-MM-dd-HH:mm:ss"); String format = s.format(new Date()); //搜索是否存在该cookie Cookie[] cookies = req.getCookies(); //标志 boolean flag = false; if (cookies != null) { for (Cookie cookie : cookies) { if (cookie.getName().equals("time")) { flag = true; break; } if (!cookie.getName().equals("time")) { flag = false; } } } //存在time cookie if (flag){ for (Cookie cookie : cookies) { if (cookie.getName().equals("time")) { //取cookie String value = cookie.getValue(); //重置cookie cookie.setValue(format); //设置一天有效期 cookie.setMaxAge(60 * 60 * 24); resp.addCookie(cookie); req.setAttribute("time","你上次的访问时间:"+value); break; } } } if (!flag){ //第一次如果没有 就进行cookie存储 Cookie cookie = new Cookie("time", format); //设置一天有效期 cookie.setMaxAge(60 * 60 * 24); resp.addCookie(cookie); req.setAttribute("time", "欢迎您的访问"); } req.getRequestDispatcher("time.jsp").forward(req, resp); } } ``` **注册:** ```xml CookieServlet01 cn.hxh.servlet.CookieServlet01 CookieServlet01 /cookie ``` **测试结果:** ![输入图片说明](https://images.gitee.com/uploads/images/2020/0820/140348_a0ed5b00_7346127.png "image-20200820125919594.png") ## 2、Session(重点) ![image-20200820133816111](https://images.gitee.com/uploads/images/2020/0820/140326_2fe427c3_7346127.png) 服务端技术、利用Session可以保存用户信息,可以把用户数据保存在Session中、来判断这个用户是否在访问服务端。 什么是session? - 服务器会给客户端创建一个对象 - 一个session占一个浏览器、只要浏览器没关、这个seesion就存在 - 用户登录后整个网站都可以访问。-->保存用户信息............ ```jsp <%-- Created by IntelliJ IDEA. User: Administrator Date: 2020/8/20 Time: 13:43 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> Title
``` ```java package cn.hxh.servlet; import javax.servlet.ServletContext; 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; /** * @Author: HongXiaoHan * @Description * @Date: 2020/8/20 13:42 */ @WebServlet("/session") public class SessionServlet01 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { this.doPost(req, resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String flag = req.getParameter("flag"); HttpSession session = req.getSession(); ServletContext servletContext = req.getServletContext(); if (flag.equals("1")) { session.setAttribute("user", "小涵"); servletContext.setAttribute("aa","小涵的servletContext"); } if (flag.equals("2")) { session.setAttribute("user", "小潇"); servletContext.setAttribute("aa","小潇的servletContext"); } String user = (String) session.getAttribute("user"); System.out.println(user+"登录了"); System.out.println(servletContext.getAttribute("aa")); } } ``` ```bash 小潇登录了 小潇的servletContext 小涵登录了 小涵的servletContext 小涵登录了 小涵的servletContext 小潇登录了 小涵的servletContext ``` 可见:servletContext的作用域十分大、可以给每一个人进行修改、而session是每一个人独一无二的。并不能进行修改。(如同对象的成员变量和静态变量一样) # 6、JSP ### 6.1、什么是JSP Java Server Pages : Java服务端页面、和Servlet一样、应用动态Web技术! 最大特点: - 写JSP和写HTML一样 - 区别: - JSP可以嵌入Java代码、为用户提供动态数据 - HTML只能给用户提供静态数据 ### 6.2、JSP基础语法 1. 指令 * 作用:用于配置JSP页面,导入资源文件 * 格式: <%@ 指令名称 属性名1=属性值1 属性名2=属性值2 ... %> * 分类: 1. page : 配置JSP页面的 * contentType:等同于response.setContentType() 1. 设置响应体的mime类型以及字符集 2. 设置当前jsp页面的编码(只能是高级的IDE才能生效,如果使用低级工具,则需要设置pageEncoding属性设置当前页面的字符集) * import:导包 * errorPage:当前页面发生异常后,会自动跳转到指定的错误页面 * isErrorPage:标识当前也是是否是错误页面。 * true:是,可以使用内置对象exception * false:否。默认值。不可以使用内置对象exception 2. include : 页面包含的。导入页面的资源文件 * <%@include file="top.jsp"%> 3. taglib : 导入资源 * <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> * prefix:前缀,自定义的 2. 注释: 1. html注释: :只能注释html代码片段 2. jsp注释:推荐使用 <%-- --%>:可以注释所有 3. 内置对象 * 在jsp页面中不需要创建,直接使用的对象 * 一共有9个: 变量名 真实类型 作用 * pageContext PageContext 当前页面共享数据,还可以获取其他八个内置对象 * request HttpServletRequest 一次请求访问的多个资源(转发) * session HttpSession 一次会话的多个请求间 * application ServletContext 所有用户间共享数据 * response HttpServletResponse 响应对象 * page Object 当前页面(Servlet)的对象 this * out JspWriter 输出对象,数据输出到页面上 * config ServletConfig Servlet的配置对象 * exception Throwable 异常对象 ### 6.3、EL表达式 1. 概念:Expression Language 表达式语言 2. 作用:替换和简化jsp页面中java代码的编写 3. 语法:${表达式} 4. 注意: * jsp默认支持el表达式的。如果要忽略el表达式 1. 设置jsp中page指令中:isELIgnored="true" 忽略当前jsp页面中所有的el表达式 2. \${表达式} :忽略当前这个el表达式 5. 使用: 1. 运算: * 运算符: 1. 算数运算符: + - * /(div) %(mod) 2. 比较运算符: > < >= <= == != 3. 逻辑运算符: &&(and) ||(or) !(not) 4. 空运算符: empty * 功能:用于判断字符串、集合、数组对象是否为null或者长度是否为0 * ${empty list}:判断字符串、集合、数组对象是否为null或者长度为0 * ${not empty str}:表示判断字符串、集合、数组对象是否不为null 并且 长度>0 2. 获取值 1. el表达式只能从域对象中获取值 2. 语法: 1. ${域名称.键名}:从指定域中获取指定键的值 * 域名称: 1. pageScope --> pageContext 2. requestScope --> request 3. sessionScope --> session 4. applicationScope --> application(ServletContext) * 举例:在request域中存储了name=张三 * 获取:${requestScope.name} 6. ${键名}:表示依次从最小的域中查找是否有该键对应的值,直到找到为止。 3. 获取对象、List集合、Map集合的值 1. 对象:${域名称.键名.属性名} * 本质上会去调用对象的getter方法 2. List集合:${域名称.键名[索引]} 3. Map集合: * ${域名称.键名.key名称} * ${域名称.键名["key名称"]} 3. 隐式对象: * el表达式中有11个隐式对象 * pageContext: * 获取jsp其他八个内置对象 * ${pageContext.request.contextPath}:动态获取虚拟目录 ### 6.4、JSTL 1. 概念:JavaServer Pages Tag Library JSP标准标签库 * 是由Apache组织提供的开源的免费的jsp标签 <标签> 2. 作用:用于简化和替换jsp页面上的java代码 3. 使用步骤: 1. 导入jstl相关jar包 2. 引入标签库:taglib指令: <%@ taglib %> 3. 使用标签 4. 常用的JSTL标签 1. if:相当于java代码的if语句 1. 属性: * test 必须属性,接受boolean表达式 * 如果表达式为true,则显示if标签体内容,如果为false,则不显示标签体内容 * 一般情况下,test属性值会结合el表达式一起使用 2. 注意: * c:if标签没有else情况,想要else情况,则可以在定义一个c:if标签 2. choose:相当于java代码的switch语句 1. 使用choose标签声明 相当于switch声明 3. 使用when标签做判断 相当于case 4. 使用otherwise标签做其他情况的声明 相当于default 5. foreach:相当于java代码的for语句 # 7、JavaBean 实体类 (JavaBean还有一些其他的别名pojo、domain.......) JavaBean特定写法: - 必须有一个无参构造 - 属性必须私有化 - 必须有get/set方法 一般用于和数据库一一映射:ORM ORM:对象关系映射 - 表=====》类 - 字段=====》属性 - 行记录====》对象 **people表** | id | name | age | | ---- | ---- | ---- | | 1 | 小海 | 18 | | 2 | 小明 | 17 | | 3 | 小花 | 18 | ```java class people{ private int id; private String name; private int age; } ``` # 8、MVC:开发模式 ### 1.jsp演变历史 1. 早期只有servlet,只能使用response输出标签数据,非常麻烦 2. 后来又jsp,简化了Servlet的开发,如果过度使用jsp,在jsp中即写大量的java代码,有写html表,造成难于维护,难于分工协作 3. 再后来,java的web开发,借鉴mvc开发模式,使得程序的设计更加合理性 ### 2.MVC: 1. M:Model,模型。JavaBean * 完成具体的业务操作,如:查询数据库,封装对象 2. V:View,视图。JSP * 展示数据 3. C:Controller,控制器。Servlet * 获取用户的输入 * 调用模型 * 将数据交给视图进行展示 ### 3.优缺点: 1. 优点: 1. 耦合性低,方便维护,可以利于分工协作 2. 重用性高 2. 缺点: 1. 使得项目架构变得复杂,对开发人员要求高 # 9、Fileter(重点) Fileter:过滤器、过滤网站数据。 - 中文乱码 - 登陆验证 ![输入图片说明](https://images.gitee.com/uploads/images/2020/0821/200144_3d45f6b5_7346127.png "image-20200821120638651.png") ​ ## 1.导包 ![输入图片说明](https://images.gitee.com/uploads/images/2020/0821/200128_9f95d391_7346127.png "image-20200821124451159.png") ## 2.编写过滤器 实现过滤器接口即可 ```java package cn.hxh.filter; import javax.servlet.*; import java.io.IOException; /** * @Author: HongXiaoHan * @Description * @Date: 2020/8/21 12:15 */ public class CharSetFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void destroy() { } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { request.setCharacterEncoding("utf-8"); response.setCharacterEncoding("utf-8"); response.setContentType("text/html;charset=UTF-8"); chain.doFilter(request,response); } } ``` ## 3.在web.xml配置filter过滤器 ```xml CharSetFilter cn.hxh.filter.CharSetFilter CharSetFilter /* ``` # 10、Listener Listener:监听器 实现一个监听器接口 ### 1.编写监听器(实现监听器的接口) ```java package cn.hxh.listener; import javax.servlet.ServletContext; import javax.servlet.http.HttpSession; import javax.servlet.http.HttpSessionEvent; import javax.servlet.http.HttpSessionListener; /** * @Author: HongXiaoHan * @Description * @Date: 2020/8/21 13:06 */ public class MyListener implements HttpSessionListener { @Override public void sessionCreated(HttpSessionEvent se) { ServletContext servletContext = se.getSession().getServletContext(); Integer onlineCount = (Integer) servletContext.getAttribute("OnlineCount"); System.out.println(se.getSession().getId()); if (onlineCount == null) { onlineCount = 1; } else { onlineCount = onlineCount + 1; } servletContext.setAttribute("OnlineCount", onlineCount); } @Override public void sessionDestroyed(HttpSessionEvent se) { ServletContext servletContext = se.getSession().getServletContext(); Integer onlineCount = (Integer) servletContext.getAttribute("OnlineCount"); onlineCount = onlineCount - 1; servletContext.setAttribute("OnlineCount", onlineCount); } } ``` ### 2.在web.xml注册监 ```xml cn.hxh.listener.MyListener ``` **总结:该内容已经很少遇到了。。根据现实情况使用。**