JavaWeb(一)

目录

一、基本概念

前言

静态web

动态web

web应用程序

静态web

动态web

web服务器

技术讲解

web服务器 

Tomcat

配置

发布一个web网站

网站应有的结构

HTTP

HTTP请求

请求行

消息头

HTTP响应

响应体 

响应状态码 

Maven

Maven项目架构管理工具

下载安装Maven

配置环境变量

本地仓库

在IDEA中使用Maven 

标记文件夹功能

在IDEA中配置Tomcat

pom文件

Servlet

Servlet简介

Hello Servlet

servlet原理

Mapping

ServletContext

共享数据

获取初始化参数

请求转发

​编辑读取资源文件  

HttpServletResponse

1、简单分类 

下载文件

验证码实现

实现重定向

简单实现登录重定向

HttpServletRequest

Cookie、Session

会话

保存会话的两种技术

Session

JSP

什么是JSP

JSP原理

JSP基础语法

JSP表达式

jsp脚本片段

JSP声明

JSP指令

9大内置对象

JSP标签、JSTL标签、EL表达式

JSP标签

JSTL表达式

核心标签

JSTL标签库使用步骤

JavaBean

MVC三层架构

早些年

MVC三层架构

Filter (重点)


一、基本概念

前言

静态web

HTML、CSS:提供给所有人看的数据始终不会发生改变

动态web

提供给所有人看的数据始终会发生变化,每个人在不同的时间,不同的地点看到的信息各不相同

技术栈:Servlet/JSP,ASP,PHP

在Java中,动态web资源开发的技术统称为JavaWeb

web应用程序

web应用程序:可以提供浏览器访问的程序;

能访问到的任何一个页面或者资源,都存在于这个世界的某一个角落的计算机上。

这个统一的web资源会被放在同一个文件夹下,web应用程序-->Tomcat:服务器

一个web应用由多部分组成(静态web、动态web)

HTML、CSS、js

jsp、servlet

Java程序        

jar包

配置文件(properties)        

web应用程序编写完毕后,若想提供给外界访问:需要一个服务器来统一管理

静态web

*.htm, *.html,这些都是网页的后缀,如果服务器上一直存在这些东西,我们就可以直接进行读取、通络;

静态web存在的缺点

1.Web页面无法动态更新,所有用户看到都是同一个页面

轮播图点击特效:伪动态
JavaScript [实际开发中,它用的最多] 

VBScript

2.它无法和数据库交互(数据无法持久化,用户无法交互)

动态web

页面会动态展示:“Web的页面展示的效果因人而异";

缺点:

加入服务器的动态web资源出现了错误,我们需要重新编写我们的后台程序,重新发布

优点:

Web页面可以动态更新,所有用户看到都不是同一个页面

它可以与数据库交互

web服务器

技术讲解

ASP

·微软:国内最早流行的就是ASP;
·在HTML中嵌入了VB的脚本,ASP + COM;
·在ASP开发中,基本一个页面都有几千行的业务代码,页面极其换乱维护成本高
·C#

PHP

·PHP开发速度很快,功能很强大,跨平台,代码很简单(70%, WP)
·无法承载大访问量的情况(局限性)

]SP/Servlet

B/S:浏览和服务器
C/S:客户端和服务器 

·sun公司主推的B/S架构
·基于Java语言的(所有的大公司,或者一些开源的组件,都是用Java写的)

·可以承载三高问题带来的影响

语法像ASP

web服务器 

服务器是一种被动的操作,用来处理用户的一些请求和给用户一些响应信息

IIS

微软的;ASP...,Windows中自带的

Tomcat

Tomcat是Apache 软件基金会(Apache Software Foundation)的Jakarta 项目中的一个核心项目,最新的Servlet 和JSP 规范总是能在Tomcat 中得到体现。因为Tomcat 技术先进、性能稳定,而且免费,因而深受Java 爱好者的喜爱并得到了部分软件开发商的认可,成为比较流行的Web 应用服务器。

Tomcat 服务器是一个免费的开放源代码的Web 应用服务器,属于轻量级应用服务器,在中小型系统和并发访问用户不是很多的场合下被普遍使用,是开发和调试JSP 程序的首选。对于一个初学者来说是最好的选择。

Tomcat 实际上运行JSP 页面和Servlet。Tomcat最新版本为10.0.23

Tomcat

下载地址:Apache Tomcat® - Welcome!

启动\关闭 Tomcat

可能遇到的问题:

1.Java环境变量没有配置
2.闪退问题:需要配置兼容性
3.乱码问题:配置文件中设置 

配置

可以配置启动的端口号:

tomcat的默认端口号:8080

mysql:3306

http:80

https:443

可以配置主机的名称

默认的主机名为:localhost->127.0.0

默认网站应用存放的位置:webapps

网站是如何进行访问的?

1.输入一个域名;回车

2.检查本机的C:\Windows\System32\drivers\etc\hosts配置文件下有没有这个域名映射;

有则直接返回对应的IP地址,这个地址中有我们需要访问的web程序,可以直接访问

无则去DNS服务器找,找到则返回,找不到则报错

发布一个web网站

将自己写的网站,放到服务器的(Tomcat)中的指定的web应用的文件夹(webapps)下,,就可以访问了。

网站应有的结构

--webapps:Tomcat服务器的web目录

        --ROOT

        --study:网站的目录名

                -WEB-INF

                     -web.xml:网站配置文件
                     -classes:JAVA程序

                     -lib :web应用所依赖的jar包

                -index.html:默认的首页

                -static

                     -css

                      -style.css

                     -js

                     -img

                     -....

HTTP

HTTP请求

客户端---发请求(Request) ---服务器

百度:

Request URL:https://www.baidu.com/   请求地址

Request Method:GET                         get方法/post方法
Status Code : 200 OK                          状态码:200
Remote(远程)Address : 14.215.177.39: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
请求方式:Get,Post,HEAD,DELETE,PUT,TRACT...

get:请求能够携带的参数比较少,大小有限制,会在浏览器的URL地址栏显示数据内容,不安全,但高效
post:请求能够携带的参数没有限制,大小没有限制,不会在浏览器的URL地址栏显示数据内容,安全,但不高效。

消息头

Accept:告诉浏览器,它所支持的数据类型

Accept-Encoding: 支持哪种编码格式 GBK UTF-8 GB2312  ISO8859-1

Accept-Language:  告诉浏览器它的语言环境

Cache-Control:缓存控制

Connection:告诉浏览器,请求完成是断开还是保持连接

HOST:主机

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:请求重定向(你重新到我给你新位置去)

4xx:找不到资源(资源不存在)  404

5xx:服务器代码错误  500        502:网关错误

当你的浏览器中地址栏输入地址并回车的一瞬间到页面能够展示回来,经历了什么?

域名解析 --> 发起TCP的3次握手 --> 建立TCP连接后发起http请求 --> 服务器响应http请求,浏览器得到html代码 --> 浏览器解析html代码,并请求html代码中的资源(如js、css、图片等) --> 浏览器对页面进行渲染呈现给用户

更多请参考

Maven

为什么要学习这个技术?

1.在Javaweb的开发中,需要使用大量的jar包,我们手动去导入
2.如何能够让一个东西自动帮我导入和配置这个jar包

Maven项目架构管理工具

Maven核心思想:约定大于配置

  ·有约束不要去违反

Maven会规定好你该如何去编写我们的Java代码,必须要按照这个规范来

下载安装Maven

官网:Maven – Welcome to Apache Maven

配置环境变量

配置如下配置:
M2_HOME maven目录下的bin目录
MAVEN_HOMEmaven的目录
在系统的path中配置%MAVEN_HOME%\bin

本地仓库

建立一个本地仓库:localRepository

  <localRepository>D:\Environment\apache-maven-3.8.6\maven-repo</localRepository>

在IDEA中使用Maven 

1.在启动IDEA后创建一个Maven项目

 最终显示画面为:

最干净的maven页面(无需设置其他):

标记文件夹功能

在IDEA中配置Tomcat

注:在官方社区版并不能设置Tomcat

记得点击应用

退出后点击运行

 最终得到界面

pom文件

pom.xml是Maven的核心配置文件

Servlet

Servlet简介

Servlet就是sun公司开发动态web的一门技术

Sun在这些API中提供一个接口叫做:Serviet,如果你想开发一个Servlet程序,只需要完成两个小步骤:
1.编写一个类,实现Servlet接口
2.把开发好的Java类部署到web服务器中

把实现了Servlet接口的Java程序叫做Servlet

Hello Servlet

1.构建一个普通的Maven项目,删掉里面的src目录,以后我们的学习就在这个项目里面建立Moudel      
2.关于Maven父子工程的理解:父项目中会有

    <modules>
        <module>servlet-01</module>
    </modules>

子项目有

    <parent>
        <artifactId>javaweb-02-servlet</artifactId>
        <groupId>org.example</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>

 父项目中的java子项目可以直接使用

3.Maven环境优化        

1.修改web.xml为最新的

2.将maven的结构搭建完整

4.编写一个Servlet程序

1.编写一个普通类

2.实现Servlet接口,这里我们直接继承HttpServlet

public class HelloServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //ServletOutputStream outputStream = resp.getOutputStream();
        PrintWriter writer = resp.getWriter(); //响应流

        writer.print("Hello,Servlet");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        super.doPost(req, resp);
    }
}

5.编写Servlet的映射

为什么需要映射:我们写的是JAVA程序,但是要通过浏览器访问,而浏览器需要连接web服务器,所以我们需要再web服务中注册我们写的Servlet,还需给他一个浏览器能够访问的路径

<!--    注册servlet-->
    <servlet>
        <servlet-name>Hello</servlet-name>
        <servlet-class>com.example.servlet.HelloServlet</servlet-class>
    </servlet>
<!--servlet请求路径-->
    <servlet-mapping>
        <servlet-name>Hello</servlet-name>
        <url-pattern>/hello</url-pattern>
    </servlet-mapping>

6.配置Tomcat 

7.启动测试

servlet原理

Servlet是由Web服务器调用,web服务器在收到浏览器请求之后,会:

Mapping

1.一个Servlet可以指定一个映射路径

    <servlet-mapping>
        <servlet-name>Hello</servlet-name>
        <url-pattern>/hello/</url-pattern>
    </servlet-mapping>

2.一个Servlet可以指定多个映射路径

    <servlet>
        <servlet-name>Hello</servlet-name>
        <servlet-class>com.example.servlet.HelloServlet</servlet-class>
    </servlet>
    <!--servlet请求路径-->
    <servlet-mapping>
        <servlet-name>Hello</servlet-name>
        <url-pattern>/hello</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>Hello</servlet-name>
        <url-pattern>/hello2</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>Hello</servlet-name>
        <url-pattern>/hello3</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>Hello</servlet-name>
        <url-pattern>/hello4</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>Hello</servlet-name>
        <url-pattern>/hello5</url-pattern>
    </servlet-mapping>

3.一个Servlet可以指定通用映射路径

    <servlet-mapping>
        <servlet-name>Hello</servlet-name>
        <url-pattern>/hello/*</url-pattern>
    </servlet-mapping>

4.默认请求路径

    <servlet-mapping>
        <servlet-name>Hello</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>

5.指定一些后缀或者前缀等等...

    <servlet-mapping>
        <servlet-name>Hello</servlet-name>
        <url-pattern>*.xiaoxian</url-pattern>
    </servlet-mapping>

6.优先级问题
指定了固有的映射路径优先级最高,如果找不到就会走默认的处理请求;

public class ErrorServlet extends HelloServlet{
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html");
        resp.setCharacterEncoding("utf-8");

        PrintWriter writer = resp.getWriter();
        writer.print("<h1>404</h1>");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        super.doPost(req, resp);
    }
}
    <servlet>
        <servlet-name>error</servlet-name>
        <servlet-class>com.example.servlet.ErrorServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>error</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>

ServletContext

web 容器在启动的时候,它会为每个 web 程序都创建一个对应的 ServletContext 对象,它代表了当前的web应用

共享数据

我在这个 Servlet 中保存的数据,可以在另外一个 servlet 中拿到
public class HelloServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

//        this.getInitParameter(); 初始化参数
//        this.getServletConfig(); Servlet配置
//        this.getServletContext(); Servlet上下文

        ServletContext context = this.getServletContext();

        String username = "小贤";//数据
        context.setAttribute("username",username);//将一个数据保存在ServletContext中,名字为username
    }
}
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 {
    }
}
    <servlet>
        <servlet-name>hello</servlet-name>
        <servlet-class>com.example.servlet.HelloServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>/hello</url-pattern>
    </servlet-mapping>

    <servlet>
        <servlet-name>get</servlet-name>
        <servlet-class>com.example.servlet.GetServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>get</servlet-name>
        <url-pattern>/get</url-pattern>
    </servlet-mapping>

获取初始化参数

<!--配置一些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);
    }

请求转发

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext context = this.getServletContext();
        System.out.println("进入了Demo04");
//        RequestDispatcher requestDispatcher = context.getRequestDispatcher("/gp");
//        requestDispatcher.forward(req,resp); //调用forward实现请求转发
        context.getRequestDispatcher("/gp").forward(req,resp);
    }


读取资源文件  

Properties
java 目录下新建 properties
resources 目录下新建 properties
发现:都被打包到了同一个路径下: classes ,我们俗称这个路径为 classpath:
思路:需要一个文件流;
username = root12312
password = zxczxczxc

public class ServletDemo05 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        InputStream is = this.getServletContext().getResourceAsStream("/WEB-INF/classes/db.properties");

        Properties prop = new Properties();
        prop.load(is);
        String user = prop.getProperty("username");
        String pwd = prop.getProperty("password");

        resp.getWriter().print(user+":"+pwd);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

HttpServletResponse

web 服务器接收到客户端的 http 请求,针对这个请求,分别创建一个代表请求的 HttpServletRequest 对 象,代表响应的一个HttpServletResponse
如果要获取客户端请求过来的参数:找HttpServletRequest
如果要给客户端响应一些信息:找 HttpServletRespons

1、简单分类 

负责向浏览器发送数据的方法
ServletOutputStream getOutputStream() throws IOException;
PrintWriter getWriter() throws IOException;
负责向浏览器发送响应头的方法
void setCharacterEncoding(String var1);
void setContentLength(int var1);
void setContentLengthLong(long var1);
void setContentType(String var1);
void setDateHeader(String var1, long var2);
void addDateHeader(String var1, long var2);
void setHeader(String var1, String var2);
void addHeader(String var1, String var2);
void setIntHeader(String var1, int var2);
void addIntHeader(String var1, int var2);
响应的状态码
int SC_CONTINUE = 100;
int SC_SWITCHING_PROTOCOLS = 101;
int SC_OK = 200;
int SC_CREATED = 201;
int SC_ACCEPTED = 202;
int SC_NON_AUTHORITATIVE_INFORMATION = 203;
int SC_NO_CONTENT = 204;
int SC_RESET_CONTENT = 205;
int SC_PARTIAL_CONTENT = 206;
int SC_MULTIPLE_CHOICES = 300;
int SC_MOVED_PERMANENTLY = 301;
int SC_MOVED_TEMPORARILY = 302;
int SC_FOUND = 302;
int SC_SEE_OTHER = 303;
int SC_NOT_MODIFIED = 304;
int SC_USE_PROXY = 305;
int SC_TEMPORARY_REDIRECT = 307;
int SC_BAD_REQUEST = 400;
int SC_UNAUTHORIZED = 401;
int SC_PAYMENT_REQUIRED = 402;
int SC_FORBIDDEN = 403;
int SC_NOT_FOUND = 404;
int SC_METHOD_NOT_ALLOWED = 405;
int SC_NOT_ACCEPTABLE = 406;
int SC_PROXY_AUTHENTICATION_REQUIRED = 407;
int SC_REQUEST_TIMEOUT = 408;
int SC_CONFLICT = 409;
int SC_GONE = 410;
int SC_LENGTH_REQUIRED = 411;
int SC_PRECONDITION_FAILED = 412;
int SC_REQUEST_ENTITY_TOO_LARGE = 413;
int SC_REQUEST_URI_TOO_LONG = 414;
int SC_UNSUPPORTED_MEDIA_TYPE = 415;
int SC_REQUESTED_RANGE_NOT_SATISFIABLE = 416;
int SC_EXPECTATION_FAILED = 417;
int SC_INTERNAL_SERVER_ERROR = 500;
int SC_NOT_IMPLEMENTED = 501;
int SC_BAD_GATEWAY = 502;
int SC_SERVICE_UNAVAILABLE = 503;
int SC_GATEWAY_TIMEOUT = 504;
int SC_HTTP_VERSION_NOT_SUPPORTED = 505;

下载文件

1. 向浏览器输出消息
2. 下载文件
1. 要获取下载文件的路径
2. 下载的文件名是啥?
3. 设置想办法让浏览器能够支持下载我们需要的东西
4. 获取下载文件的输入流
5. 创建缓冲区
6. 获取 OutputStream 对象
7. FileOutputStream 流写入到 buffffer 缓冲区
8. 使用 OutputStream 将缓冲区中的数据输出到客户端!
public class FileServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String realPath ="C:\\Users\\Lenovo\\Desktop\\java\\中文.png";
        System.out.println("下载路径为"+realPath);
        String filename = realPath.substring(realPath.lastIndexOf("\\") + 1);
        resp.setHeader("Content-Disposition","attachment;filename="+ URLEncoder.encode(filename,"UTF-8"));
        FileInputStream in = new FileInputStream(realPath);
        int len = 0;
        byte[] buffer = new byte[1024];
        ServletOutputStream out = resp.getOutputStream();
        while ((len=in.read(buffer))>0){
            out.write(buffer,0,len);
        }
        in.close();
        out.close();
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

验证码实现

public class ImageServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //如何让浏览器3秒自动刷新一次;
        resp.setHeader("refresh", "5");
        //在内存中创建一个图片
        BufferedImage image = new BufferedImage(80,20,BufferedImage.TYPE_INT_RGB);
        //得到图片
        Graphics2D graphics = (Graphics2D) image.getGraphics();
        //设置图片的背景颜色
        graphics.setColor(Color.white);
        graphics.fillRect(0,0,80,20);
        //给图片写数据
        graphics.setColor(Color.BLUE);
        graphics.setFont(new Font(null,Font.BOLD,20));
        graphics.drawString(makeNumber(),0,20);

        //告诉浏览器,这个请求用图片的方式打开
        resp.setContentType("image/jpeg");
        //网站存在缓存,不让浏览器缓存
        resp.setDateHeader("expires",-1);
        resp.setHeader("Cache-Control","no-cache");
        resp.setHeader("Pragma","no-cache");

        //把图片写给浏览器
        ImageIO.write(image,"jpg", resp.getOutputStream());
    }
    //
    public String makeNumber(){
        Random random = new Random();
        String num = random.nextInt(99999999) + " ";
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < 7-num.length(); i++) {
            sb.append("0");
        }
        num = sb.toString() + num;
        return num;
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

实现重定向

B 一个 web 资源收到客户端 A 请求后, B 他会通知 A 客户端去访问另外一个 web 资源 C ,这个过程叫重定向 常见场景
用户登录 
void sendRedirect(String var1) throws IOException;
public class RedirectServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.sendRedirect("http://localhost:8080/Response_war/img");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
请你聊聊重定向和转发的区别?
相同点:
页面都会实现跳转
不同点:
请求转发的时候, url 不会产生变化
重定向时候, url 地址栏会发生变化; 

 

简单实现登录重定向

<%--这里提交的路径,需要寻找到项目的路径--%>
<%--${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>
public class RequestTest extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("进入这个请求了");

        String username = req.getParameter("username");
        String password = req.getParameter("password");
        System.out.println(username+":"+password);
        resp.sendRedirect("./success.jsp");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
    <servlet>
        <servlet-name>request</servlet-name>
        <servlet-class>com.example.servlet.RequestTest</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>request</servlet-name>
        <url-pattern>/login</url-pattern>
    </servlet-mapping>
<html>
<head>
    <title>Title</title>
</head>
<body>
<h1>success</h1>
</body>
</html>

HttpServletRequest

HttpServletRequest 代表客户端的请求,用户通过 Http 协议访问服务器, HTTP 请求中的所有信息会被封 装到HttpServletRequest ,通过这个 HttpServletRequest 的方法,获得客户端的所有信息

 获取参数,请求转发

public class LoginServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("UTF-8");
        resp.setCharacterEncoding("UTF-8");

        String username = req.getParameter("username");
        String pwd = req.getParameter("password");
        String[] hobbies = req.getParameterValues("hobbies");
        System.out.println("--------------------------");
        System.out.println(username);
        System.out.println(pwd);
        System.out.println(Arrays.toString(hobbies));
        System.out.println("--------------------------");

        req.setCharacterEncoding("UTF-8");
        req.getRequestDispatcher("./success.jsp").forward(req,resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
请你聊聊重定向和转发的区别?
相同点:页面都会实现跳转
不同点:请求转发的时候,url 不会产生变化 307
            重定向时候, url 地址栏会发生变化  302

Cookie、Session

会话

会话 :用户打开一个浏览器,点击了很多超链接,访问多个 web 资源,关闭浏览器,这个过程可以称之为会话;
有状态会话 :一个同学来过教室,下次再来教室,我们会知道这个同学,曾经来过,称之为有状态会话
一个网站,怎么证明你来过?
客户端 服务端
1. 服务端给客户端一个 信件,客户端下次访问服务端带上信件就可以了; cookie
2. 服务器登记你来过了,下次你来的时候我来匹配你; seesion

保存会话的两种技术

cookie

·客户端技术(响应,请求)

session

服务器技术,可以保存用户会话的信息;我们可以把信息或数据放在session中

常见场景:网站登录之后,你下次不用再登录了,第二次访问直接就上去了

1. 从请求中拿到 cookie 信息
2. 服务器响应给客户端 cookie
Cookie [] cookies = req . getCookies (); // 获得 Cookie
cookie . getName (); // 获得 cookie 中的 key
cookie . getValue (); // 获得 cookie 中的 vlaue
new Cookie ( "lastLoginTime" , System . currentTimeMillis () + "" ); // 新建一个 cookie
cookie . setMaxAge ( 24 * 60 * 60 ); // 设置 cookie 的有效期
resp . addCookie ( cookie ); // 响应给客户端一个 cookie
public class CookieDemo01 extends HttpServlet {
    @Override
    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();//这里返回数组,说明cookie可能存在多个
        
        //判断Cookie是否存在
        if (cookies != null) {
            out.write("你上一次访问时间为");
            for (int i = 0; i < cookies.length; i++) {
                Cookie cookie = cookies[i];
                //获取cookie的名字
                if (cookie.getName().equals("lastLoginTime")) {
                    //获取cookie中的值
                    long lastLoginTime = Long.parseLong(cookie.getValue());
                    Date date = new Date(lastLoginTime);
                    out.write(date.toLocaleString());
                }
            }
        } else {
            out.write("这是你第一次访问");
        }

        //服务给客户端I响应一个cookie;
        Cookie cookie = new Cookie("lastLoginTime", System.currentTimeMillis() + "");

        //cookie有效期1天
        cookie.setMaxAge(24*60*60);

        resp.addCookie(cookie);

    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

 cookie:一般会保存在本地的 用户目录下 appdata

一个网站cookie是否存在上限?
一个Cookie
只能保存一个信息;
一个web
站点可以给浏览器发送多个cookie,最多存放20cookie
Cookie大小有限制
4kb
300个cookie浏览器上限

删除 Cookie
不设置有效期,关闭浏览器,自动失效;
设置有效期时间为 0

编码解码:

URLEncoder . encode ( " 小贤 " , "utf-8" )
URLDecoder . decode ( cookie . getValue (), "UTF-8" )

Session

什么是session:

服务器会给每一个用户(浏览器)创建一个Seesion对象;
一个Seesion独占一个浏览器,只要浏览器没有关闭,这个Session就存在;
用户登录之后,整个网站它都可以访问!--> 保存用户的信息;保存购物车的信息

    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //解决乱码问题
        resp.setCharacterEncoding("UTF-8");
        req.setCharacterEncoding("UTF-8");
        resp.setContentType("text/html;charset=utf-8");

        //得到session
        HttpSession session = req.getSession();

        //给session中存东西
        session.setAttribute("name", new Person("小贤",1));

        //获取session的id
        String id = session.getId();

        //判断Session是不是新创建
        if (session.isNew()) {
            resp.getWriter().write("session 创建成功,id为" + id);
        } else {
            resp.getWriter().write("session已经在服务器中存在,id为" + id);
        }

        //Session创建的时候做了什么事情;
        //Cookie cookie = new Cookie("JSESSIONID",sessionId);
        // resp.addCookie(cookie);
    }
public class SessionDemo02 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //解决乱码问题
        resp.setCharacterEncoding("UTF-8");
        req.setCharacterEncoding("UTF-8");
        resp.setContentType("text/html;charset=utf-8");

        //得到session
        HttpSession session = req.getSession();

        Person person =(Person)session.getAttribute("name");

        System.out.println(person.toString());


    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
public class SessionDemo03 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        HttpSession session = req.getSession();
        session.removeAttribute("name");
        session.invalidate();
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
    <!--设置Session默认的失效时间-->
    <session-config>
        <!--15分钟后Session自动失效,以分钟为单位-->
        <session-timeout>15</session-timeout>
    </session-config
Sessioncookie的区别:
Cookie 是把用户的数据写给用户的浏览器,浏览器保存 (可以保存多个)
Session 把用户的数据写到用户独占 Session 中,服务器端保存 (保存重要的信息,减少服务器资
源的浪费)
Session 对象由服务创建
使用场景:
保存一个登录用户的信息;
购物车信息;
在整个网站中经常会使用的数据,我们将它保存在 Session

JSP

什么是JSP

Java Server Pages Java 服务器端页面,也和 Servlet 一样,用于动态 Web 技术
最大的特点:
JSP 就像在写 HTML
区别:
HTML 只给用户提供静态的数据
JSP 页面中可以嵌入 JAVA 代码,为用户提供动态数据;

JSP原理

思路: JSP 到底怎么执行的
·代码层面没有任何问题
·服务器内部工作
   tomcat 中有一个 work 目录;
   IDEA 中使用 Tomcat 的会在 IDEA tomcat 中生产一个 work 目录

 我电脑的地址: C:\Users\Lenovo\AppData\Local\JetBrains\IntelliJIdea2022.2\tomcat\963f37be-f6ea-4466-87dd-adf7c79c034d\work\Catalina\localhost\ROOT\org\apache\jsp

发现页面转变成了 Java 程序

浏览器向服务器发送请求,不管访问什么资源,其实都是在访问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; //页面上下文
javax.servlet.http.HttpSession session = null; //session
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:当前
HttpServletRequest request //请求
HttpServletResponse response //响应
3. 输出页面前增加的代码
response.setContentType("text/html"); //设置响应的页面类型
pageContext = _jspxFactory.getPageContext(this, request, response,
null, true, 8192, true);
_jspx_page_context = pageContext;
application = pageContext.getServletContext();
config = pageContext.getServletConfig();
session = pageContext.getSession();
out = pageContext.getOut();
_jspx_out = out;
4. 以上的这些个对象我们可以在 JSP 页面中直接使用

 

 JSP页面中; 只要是 JAVA代码就会原封不动的输出; 如果是HTML代码,就会被转换为:

out.write("<html>\r\n");

JSP基础语法

任何语言都有自己的语法, JAVA 中有 , JSP 作为 java 技术的一种应用,它拥有一些自己扩充的语法(了解,知道即可!),Java 所有语法都支持

JSP表达式

<%--JSP表达式
作用:用来将程序的输出,输出到客户端
<%= 变量或者表达式%>
--%>
<%= new java.util.Date()%>

jsp脚本片段

<%--jsp脚本片段--%>
<%
int sum = 0;
for (int i = 1; i <=100 ; i++) {
sum+=i;
}
out.println("<h1>Sum="+sum+"</h1>");
%>
脚本片段的再实现
  <%
    int x = 10;
    out.println(x);
  %>
  <p>这是一个JSP文档</p>
  <%
    int y = 2;
    out.println(y);
  %>
  <hr>
  <%--在代码嵌入HTML元素--%>
  <%
    for (int i = 0; i < 5; i++) {
  %>
  <h1>Hello,World <%=i%> </h1>
  <%
    }
  %>

JSP声明

  <%!
    static {
      System.out.println("Loading Servlet!");
    }
    private int globalVar = 0;
    public void xian(){
      System.out.println("进入了方法xian");
    }
  %>
JSP 声明:会被编译到 JSP 生成 Java 的类中。其他的,就会被生成到 _jspService 方法中!
JSP ,嵌入 Java 代码即可
<%%>
<% = %>
<% ! %>
<% -- 注释 -- %>

JSP的注释,不会在客户端显示,HTML

JSP指令

<%@include file="common/header.jsp"%>
<h1>项目主题</h1>
<%@include file="common/footer.jsp"%>

<hr>

<jsp:include page="/common/header.jsp"/>
<h1>网页主体</h1>
<jsp:include page="/common/footer.jsp"/>
@include 会将两个页面合二为一
jsp : include :拼接页面,本质还是三个

9大内置对象

PageContext 存东西
Request 存东西
Response
Session 存东西
Application SerlvetContext 存东西
confifig SerlvetConfifig
out
page ,不用了解
exception


<%
  pageContext.setAttribute("name1", "小贤1");//保存的数据只在一个页面中有效
  request.setAttribute("name2", "小贤2");//保存的数据只在一次请求中有效,请求转发会携带这个数据
  session.setAttribute("name3","小贤3");//保存的数据只在一次会话中有效,从打开浏览器到关闭浏览器
  application.setAttribute("name4","小贤4");//保存的数据只在服务器中有效,从打开服务器到关闭服务器
%>
<%--脚本片段中的代码,会被原封不动生成到.JSP.java
要求:这里面的代码:必须保证Java语法的正确性
--%>

<%
    //从pageContext取出,我们通过寻找的方式
    //从底层到高层(作用域)
    String name1 = (String) pageContext.findAttribute("name1");
    String name2 = (String) pageContext.findAttribute("name2");
    String name3 = (String) pageContext.findAttribute("name3");
    String name4 = (String) pageContext.findAttribute("name4");
    String name5 = (String) pageContext.findAttribute("name5");//不存在

%>

<%--使用EL表达式输出--%>

<h1>取出的值为</h1>
<h3>${name1}</h3>
<h3>${name2}</h3>
<h3>${name3}</h3>
<h3>${name4}</h3>
<h3>${name5}</h3>

  pageContext.setAttribute("hello1", "hello1", PageContext.SESSION_SCOPE);
  //等价于session.setAttribute(""hello1","hello1"");
pageContext.forward("/index.jsp");//一般在前端使用
request.getRequestDispatcher("/index.jsp").forward(request,response);
request :客户端向服务器发送请求,产生的数据,用户看完就没用了,比如:新闻,用户看完没用的!
session :客户端向服务器发送请求,产生的数据,用户用完一会还有用,比如:购物车;
application :客户端向服务器发送请求,产生的数据,一个用户用完了,其他用户还可能使用,比如: 聊天数据;

JSP标签、JSTL标签、EL表达式

EL 表达式: ${ }
获取数据
执行运算
获取 web 开发的常用对象

JSP标签

<jsp:forward page="/jsptag2.jsp">
  <jsp:param name="name" value="xiaoxian"></jsp:param>
  <jsp:param name="age" value="3"></jsp:param>
</jsp:forward>

JSTL表达式

JSTL标签库的使用就是为了弥补HTML标签的不足;它自定义许多标签,可以供我们使用,标签的功能和Java代码一样 

SQL标签

XML标签

核心标签

 核心标签是最常用的 JSTL标签。引用核心标签库的语法如下:

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

JSTL标签库使用步骤

1.引入对应的 taglib
2.使用其中的方法
3.在 Tomcat 也需要引入 jstl 的包,否则会报错: JSTL 解析错误
c if
<head>
<title>Title</title>
</head>
<body>
<h4>if测试</h4>
<hr>
<form action="coreif.jsp" method="get">
<%--
EL表达式获取表单中的数据
${param.参数名}
--%>
<input type="text" name="username" value="${param.username}">
<input type="submit" value="登录">
</form>
<%--判断如果提交的用户名是管理员,则登录成功--%>
<c:if test="${param.username=='admin'}" var="isAdmin">
<c:out value="管理员欢迎您!"/>
</c:if>
<%--自闭合标签--%>
<c:out value="${isAdmin}"/>
</body>
c:choose c:when
<body>
<%--定义一个变量score,值为85--%>
<c:set var="score" value="55"/>
<c:choose>
<c:when test="${score>=90}">
你的成绩为优秀
</c:when>
<c:when test="${score>=80}">
你的成绩为一般
</c:when>
<c:when test="${score>=70}">
你的成绩为良好
</c:when>
<c:when test="${score<=60}">
你的成绩为不及格
</c:when>
</c:choose>
</body>
c:forEach
<%
ArrayList<String> people = new ArrayList<>();
people.add(0,"张三");
people.add(1,"李四");
people.add(2,"王五");
people.add(3,"赵六");
people.add(4,"田六");
request.setAttribute("list",people);
%>
<%--
var , 每一次遍历出来的变量
items, 要遍历的对象
begin, 哪里开始
end, 到哪里
step, 步长
--%>
<c:forEach var="people" items="${list}">
<c:out value="${people}"/> <br>
</c:forEach>
<hr>
<c:forEach var="people" items="${list}" begin="1" end="3" step="1" >
<c:out value="${people}"/> <br>
</c:forEach>

JavaBean

实体类
JavaBean 有特定的写法:
必须要有一个无参构造
属性必须私有化
必须有对应的 get/set 方法;
一般用来和数据库的字段做映射 ORM
ORM :对象关系映射
--->
字段 --> 属性
行记录 ----> 对象

SQLyog表

public class People {
    private int id;
    private String name;
    private int age;
    private String address;

    public People(int id, String name, int age, String address) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.address = address;
    }

    public People() {
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }
}
<jsp:useBean id="people" class="com.example.pojo.People" scope="page"/>

<jsp:setProperty name="people" property="address" value="北京"/>
<jsp:setProperty name="people" property="id" value="123456"/>
<jsp:setProperty name="people" property="name" value="小明"/>
<jsp:setProperty name="people" property="age" value="3"/>

地址:<jsp:getProperty name="people" property="address" />
id:<jsp:getProperty name="people" property="id" />
姓名:<jsp:getProperty name="people" property="name" />
年龄:<jsp:getProperty name="people" property="age" />

MVC三层架构

什么是MVC Model view Controller 模型、视图、控制器

早些年

 用户直接访问控制层,控制层就可以直接操作数据库

servlet -- CRUD --> 数据库
弊端:程序十分臃肿,不利于维护
servlet 的代码中:处理请求、响应、视图跳转、处理 JDBC 、处理业务代码、处理逻辑代码
架构:没有什么是加一层解决不了的!
程序猿调用
|
JDBC
|
Mysql Oracle SqlServer ....

MVC三层架构

Model
业务处理 :业务逻辑( Service
数据持久层: CRUD Dao
View
展示数据
提供链接发起 Servlet 请求 (a, form img…
Controller Servlet
接收用户的请求 :(req:请求参数、 Session 信息 ….
交给业务层处理对应的代码
控制视图的跳转
登录 ---> 接收用户的登录请求 ---> 处理用户的请求(获取用户登录的参数, username, password) ----> 交给业务层处理登录业务(判断用户名密码是否正确:事务) ---> Dao 层查询用
户名和密码是否正确 --> 数据库

Filter (重点)

Filter :过滤器 ,用来过滤网站的数据;

Filter 开发步骤:
1. 导包
2. 编写过滤器

导包不要错

实现Filter接口,重写对应的方法即可

public class CharacterEncodingFilter implements Filter {
//初始化:web服务器启动,就以及初始化了,随时等待过滤对象出现!
public void init(FilterConfig filterConfig) throws
ServletException {
System.out.println("CharacterEncodingFilter初始化");
}
//Chain : 链
/*
1. 过滤中的所有代码,在过滤特定请求的时候都会执行
2. 必须要让过滤器继续同行
chain.doFilter(request,response);
*/
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");
System.out.println("CharacterEncodingFilter执行前....");
chain.doFilter(request,response); //让我们的请求继续走,如果不
写,程序到这里就被拦截停止!
System.out.println("CharacterEncodingFilter执行后....");
}
//销毁:web服务器关闭的时候,过滤会销毁
public void destroy() {
System.out.println("CharacterEncodingFilter销毁");
}
}

 3. web.xml中配置 Filter

<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>com.kuang.filter.CharacterEncodingFilter</filterclass>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<!--只要是 /servlet的任何请求,会经过这个过滤器-->
<url-pattern>/servlet/*</url-pattern>
<!--<url-pattern>/*</url-pattern>-->
</filter-mapping>
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值