(Servlet+Jsp)Web编程笔记(一套就够了)

Posted SmallCuteMonkey

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了(Servlet+Jsp)Web编程笔记(一套就够了)相关的知识,希望对你有一定的参考价值。

文章目录

Web编程技术笔记

1. BS架构与CS架构

BS: Browser Server 浏览器服务器结构 类似于通过浏览器访问访问 客户端只需要一个浏览器 主要逻辑集中在服务器

CS: Client Server 客户端服务器结构 类似于QQ软件,腾讯视频等 富客户端:主要的程序集中在本机客户端软件上面

java核心优势就在于web服务器端编程,其实就是bs架构 ,面向web的服务端编程

前台: 浏览器页面呈现出来的内容;用户看得到的东西,技术html,js,css,jsp

后台:用户看不到的,能够实现某些功能,处理某些业务逻辑;对程序员,必须要了解前后台技术,前后台执行的原理

servlet+jsp

2. idea安装及使用

安装 直接下一步 和普通软件安装方法 注意不要中文路径

破解教程地址: https://blog.lupf.cn/articles/2020/08/24/1598265235879.html

软件版本:

idea2020.1+ apache tomcat 9+jdk8+mysql5.7

3. Servlet介绍

Servlet是一个容器,用来接收客户端请求,并进行相应的业务逻辑操作,并且产生响应给客户端浏览器

servlet接收请求,处理逻辑,产生响应的过程

servlet是个过程,有自己的生命周期,有初始化,执行,销毁的过程

servlet特点:

servlet是无状态的,不连续的,web服务器就是我可以敲不同的url访问不同的模块,可以切入到不同的模块里面

1. 新建一个Servlet

使用idea创建一个 web project: web工程 针对于web项目来说的

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cD7B5it5-1629527148254)(img\\1.png)]

选择JavaEE版本,建议选择JavaEE6,因为从6版本开始,支持Servlet注解了,勾选web application

tomcat可以在这关联,或者项目创建成功之后关联也可以;已经关联的不需要再次关联

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9j1eA3rs-1629527148259)(img\\2.png)]

创建工程名: 注意工程名命名规则,下面是工程所在路径,到工程名那一级

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AsknCmAS-1629527148261)(img\\3.png)]

web project目录结构:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vlRI3Xfa-1629527148264)(img\\4.png)]

2. 配置web服务器

web项目还需要配置web服务器:

web服务器使用tomcat:

  1. 添加配置

添加tomcat服务器

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VKGBQxcs-1629527148290)(img\\5.png)]

  1. 选择tomcat server-local 本地

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mOF2FyhJ-1629527148291)(img\\6.png)]

  1. 点击配置 ,添加本机tomcat路径到根路径

    tomcat压缩包直接解压即可 ,注意不要放在中文路径底下

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MRpBGrV2-1629527148292)(img\\7.png)]

  1. 发布项目: 即把该项目放到web服务器里面; 点击deployment 发布 点击+ 选择第一个 确定即可

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2Py9y1be-1629527148292)(img\\8.png)]

5.直接点击tomcat右边绿色箭头即可启动tomcat服务器

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iVkOZxuj-1629527148293)(img\\9.png)]

创建第一个servlet:

  1. 点src 右键— create new servlet

  2. 写上servlet name 和所在包名

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Lbxm19ID-1629527148294)(img\\10.png)]

  3. 注解加上 urlPattern属性 urlPattern表示浏览器访问该Servlet时需要对应的路径 /表示项目根路径

    package servlet;
    
    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;
    
    @WebServlet(name = "AServlet",urlPatterns = "/aaa")
    public class AServlet extends HttpServlet {
    
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
        }
    
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
            System.out.println("这是我的第一个Servlet....");
        }
    }
    
    
    1. doGet()方法里面写处理逻辑

    2. 启动tomcat

    3. 浏览器url访问 http://localhost:8080/servlet0100_war_exploded/aaa

      aaa就是urlPattern里面的值 对应一致才可以访问

    4. 运行结果

      注意: 代码改动过后服务器必须重启

      Servlet有两种配置方式

      注意: servlet有下面2种配重方式;一个servlet只需要选择其中一种配置方式即可;不能2种方式同时配置

      1. 注解方式

      javaee6版本之后开始支持注解 刚才上一种

      2. xml配置方式

      package servlet;
      
      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 BServlet extends HttpServlet {
          protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 
      
          }
      
          protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
              System.out.println("Hello world!!!!!");
          }
      }
      
      
      <?xml version="1.0" encoding="UTF-8"?>
      <web-app xmlns="http://java.sun.com/xml/ns/javaee"
                 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                 xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
      		  http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
                 version="3.0">
      
          <servlet>
              <servlet-name>BServlet</servlet-name>
              <servlet-class>servlet.BServlet</servlet-class>
          </servlet>
      
          <servlet-mapping>
              <servlet-name>BServlet</servlet-name>
              <url-pattern>/bbb</url-pattern>
          </servlet-mapping>
      </web-app>
      
      

url-pattern对应的是该Servlet的访问路径

localhost表示本机ip地址;本机ip表示方式: localhost 127.0.0.1 本机实际ip

tomcat默认端口号 8080

Servlet和JSP规范版本对应关系:

Servlet规范版本JSP版本JSF版本JAVA EE版本
Servlet2.3JSP1.2、JSP1.1J2EE1.3
Servlet2.4JSP2.0JSF1.1J2EE1.4
Servlet2.5JSP2.1JSF1.2、JSF2.0Java EE5
Servlet3.0JSP2.2Java EE6

3. Tomcat所对应的Servlet/JSP规范和JDK版本:

Servlet/JSP SpecApache Tomcat versionActual release revisionMinimum Java Version
3.0/2.27.0.x7.0.121.6
2.5/2.16.0.x6.0.321.5
2.4/2.05.5.x5.5.331.4
2.3/1.24.1.x (archived)4.1.40 (archived)1.3
2.2/1.13.3.x (archived)3.3.2 (archived)1.1

4. Servlet体系结构:

1. Servlet继承体系

	javax.servlet.Servlet(接口)   javax.servlet。ServletConfig(接口)
		|
		|实现
		|
	javax.servlet.GenericServlet(抽象类)不针对具体协议
		|
		|继承
		|
	javax.servlet.http.HttpServlet(抽象类):针对HTTP协议的
		|
		|继承
		|
	自定义Servlet类(接收客户请求与响应)

2. Servlet: 接口

​ 常用方法:

​ void init() 初始化方法

​ void init(ServletConfig config) servlet初始化方法

​ void service(ServletRequst request,ServletResponse response) servlet的服务方法

​ void destroy() servlet的销毁方法

​ ServletConfig getServletConfig() 获取ServletConfig对象

3. HttpServlet: 抽象类

​ protected void doGet(HttpServletRequest req, HttpServletResponse resp) 处理get请求

​ protected void doPost(HttpServletRequest req, HttpServletResponse resp) 处理post请求

​ protected void service(HttpServletRequest req, HttpServletResponse resp) 处理所有的请求方式

4 HttpServletRequest: 请求对象

当用户发送的请求到达servlet容器时,包含数据的请求将被转换为HttpServletRequest对象,对请求数据的处理工作便由HttpServletRequest对象完成。

方法:

​ public String getParameter(String name) 返回指定name对应的参数的值

​ public String[] getParameterValues(String name) 返回指定name对应的一组参数值,返回值是数组

​ public Enumeration getParameterNames() 返回所有客户请求的参数名

​ String getMethod() 获取请求的方法 (GET,POST)

​ String getRequestURI() 获取请求的uri

​ StringBuffer gerTrequestURL() 获取请求的URL

​ String getProtocol() 获取请求协议的版本号

5. HttpServletResponse: 响应对象

​ 把服务器对客户端浏览器的所有响应内容封装到该对象里面

​ 常用方法:

​ void setContentType(String str) 专门设置content-type这个响应头

​ PrintWriter getWriter() 获取一个字符方式的响应 输出流

​ ServletOutputStream getOutputSttream() 获取一个字节方式的响应 输出流

6. ServletConfig: 接口

常用方法:

​ getInitParameter(String param) 根据参数name值返回对用的初始化参数值 一个名称对应一个值

​ getInitParameterNames(String param) 根据参数名返回该name对应的所有的参数值 一个名称对应多个值

​ getServletContext() 返回一个ServletContext对象

​ getServletName() 返回当前servlet的名称,即@WebServlet的name属性值,如果没配,返回全限命名

注意: 一个Servlet对应一个ServletConfig对象

7. ServletConext: 接口

​ 如何在servlet中获取ServletContext对象,下面3个类里面有相应的方法
​ HttpServlet: getServletContext();
​ ServletConfig: getServletContext();
​ HttpSession: getServletContext();
​ 好用API:
​ String getRealPath(String relativePath)//相对路径的参数,获得运行时本应用在tomcat中的绝对路径
​ InputStream getResourceAsStream(String relativePath)文件的相对(应用)路径,直接取得它的文件输入流

​ ServletContext初始化参数(类似servlet初始化参数)

初始化参数配置:

<context-param>
		<param-name>参数名</param-name>
		<param-value>参数值</param-value>
</context-param>

获取初始化参数的方法:
​ String getInitParameter(String name) 根据参数名获取对应的初始化参数值
​ Enumeration getInitParameterNames() 获取所有的初始化参数的名称

5. Servlet生命周期:

servlet的生命周期: 指的是Servlet实例从创建到响应客户请求,直至销毁的过程
​四个阶段: 加载和实例化 ,初始化 ,处理请求,销毁

​ void init() 初始化方法

​ void init(ServletConfig config) servlet初始化方法 servlet被创建的时候执行 默认的是浏览器访问该servlet的时候加载

​ void service(ServletRequst request,ServletResponse response) servlet的服务方法

​ void destroy() servlet的销毁方法 web服务器关闭的时候执行

6. Servlet加载时机:

load-on-startup

注解配置 和 xml配置

默认值是-1

在servlet的配置当中,1的含义是:

标记容器是否在启动的时候就加载这个servlet。

当值为0或者大于0时,表示容器在应用启动时就加载这个servlet;正数的值越小,启动该servlet的优先级越高;

当是一个负数时或者没有指定时,则指示容器在该servlet被选择时才加载。

如果我们在web.xml中设置了多个servlet的时候,可以使用load-on-startup来指定servlet的加载顺序,服务器会根据load-on-startup的大小依次对servlet进行初始化。不过即使我们将load-on-startup设置重复也不会出现异常,服务器会自己决定初始化顺序

配置load-on-startup后,servlet在startup后立即加载,但只是调用servlet的init()方法,用以初始化该servlet相关的资源。初始化成功后,该servlet可响应web请求;如未配置load-on-startup,容器一般在第一次响应web请求时,会先检测该servlet是否初始化,如未初始化,则调用servlet的init()先初始化,初始化成功后,再响应请求

package com.jishou.servlet;

import javax.servlet.ServletConfig;
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;

@WebServlet(name = "LifeServlet",urlPatterns = "/life",loadOnStartup = 1)
public class LifeServlet extends HttpServlet {

    //声明周期  init()  service()  destroy()
    //loadOnStartup 加载时机

    //初始化方法
    @Override
    public void init(ServletConfig config) throws ServletException {
        System.out.println("该servlet被初始化了。。。");
    }

    //执行
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        System.out.println("该Servlet被执行了。。。。");
    }

    //销毁
    @Override
    public void destroy() {
        System.out.println("该Servlet被销毁了。。。。");
    }
}

7. Http请求方法:

1. 请求方法有:

GET POST PUT DELETE TRACE OPTIONS HEAD


2. GET与POST的区别:

​ GET携带数据是走地址栏传递不安全
​ 地址栏有长度限制(长度1024字节),如果数据大,走地址栏中传递不方便
​ 安全性比post低
没有请求体

​ POST携带数据走请求体
​ 请求体理论上没有长度限制
​ 安全性比get高

3. servlet里方法区别:

​ doGet() 处理的是get请求 直接敲url,超链接,表单method=“get”属于get请求

​ doPost() 处理的是post请求 表单method="post"属于post请求

service()方法处理所有请求方式,它能够把不同的请求分发给相应的请求方法

4. 详细理解service()方法

HttpServlet里面 service()方法源码:

    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String method = req.getMethod();
        long lastModified;
        if (method.equals("GET")) {
            lastModified = this.getLastModified(req);
            if (lastModified == -1L) {
                this.doGet(req, resp);
            } else {
                long ifModifiedSince;
                try {
                    ifModifiedSince = req.getDateHeader("If-Modified-Since");
                } catch (IllegalArgumentException var9) {
                    ifModifiedSince = -1L;
                }

                if (ifModifiedSince < lastModified / 1000L * 1000L) {
                    this.maybeSetLastModified(resp, lastModified);
                    this.doGet(req, resp);
                } else {
                    resp.setStatus(304);
                }
            }
        } else if (method.equals("HEAD")) {
            lastModified = this.getLastModified(req);
            this.maybeSetLastModified(resp, lastModified);
            this.doHead(req, resp);
        } else if (method.equals("POST")) {
            this.doPost(req, resp);
        } else if (method.equals("PUT")) {
            this.doPut(req, resp);
        } else if (method.equals("DELETE")) {
            this.doDelete(req, resp);
        } else if (method.equals("OPTIONS")) {
            this.doOptions(req, resp);
        } else if (method.equals("TRACE")) {
            this.doTrace(req, resp);
        } else {
            String errMsg = lStrings.getString("http.method_not_implemented");
            Object[] errArgs = new Object[]{method};
            errMsg = MessageFormat.format(errMsg, errArgs);
            resp.sendError(501, errMsg);
        }

    }

由此可见: service()方法处理所有请求方式,它能够吧不同的请求分发给相应的请求方法

*注意:8. 中文乱码问题:

tomcat默认编码为iso-8859-1,不支持中文,中文传输时会出现中文乱码问题

中文编码有: utf-8, gb2312 ,gbk,gb18030等,出现问题时,按照情形分别处理即可:

解决方案:

请求request:

post请求:

​ 1.保证页面中(html)编码是中文编码

​ 2.在服务器端(servlet中)接收请求之前,写在请求的最上方;要设置一下请求对象的字符编码方式变成中文

​ request.setCharacterEncoding(“中文编码”)

get请求:

​ 1.保证页面中编码是中文编码

​ 2.修改tomcat配置文件(在tomcat安装根目录\\conf\\server.xml)设置请求的URI编码方式
大概在server.xml中69行
​ <Connector… URIEncoding=“utf-8”/>

​ 3.改完server.xml一定要记得重新启动tomcat

注意: tomcat9中get请求不需设置,默认支持中文编码

​ 不区分POST与GET的,再获取输出流之前设置响应对象的字符编码,一般写在响应的最上方
​ response.setCharacterEncoding(“中文编码”);

*注意:9. 常见报错问题解决方法

  1. web peoject 引入依赖方式和java project不一样,依赖必须放在web底下web-inf底下的lib目录底下,默认位置

  2. web-inf目录下的东西前端无法访问,但是后台可以访问

  3. 报错提示信息

    20X,30X: 说明成功,没有问题

    40x: 客户端问题

    ​ 400:前后台参数类型不一致

    ​ 404: 路径问题

    50x: 后台代码问题

    ​ 看报错提示: 一般看报错信息的第一行

    ​ 经常会碰到NullPointException: 如果一个对象为null,调用他的属性或方法的时候会报空指针异常

  4. mysql版本问题

    如何查看mysql版本: select version()

    如果mysql5.x版本的,jar包可以使用5或8版本的依赖

    如果mysql8.x版本的,jar包尽量使用8版本的依赖

    mysql依赖包有5.X和8.X版本,他们配置的时候是有区别的:

​ mysql5:

​ 驱动名: com.mysql.jdbc.Driver

​ url: url=“jdbc:mysql://localhost:3306/示例数据库名?characterEncoding=utf8”

​ mysql8:

​ 驱动名: com.mysql.cj.jdbc.Driver

​ url: url=“jdbc:mysql://localhost:3306/示例数据库名?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=GMT%2B8”

  1. 报错信息如何调试:

    ​ 前端问题: 直接在浏览器上面调试 F12 console:

    ​ 后台问题: 直接使用debug模式提示

    1. 打断点
    2. 以debug模式启动
    3. 运行程序,到断点的地方程序会停止下来,由程序员自行调控测试

10. Tomcat目录结构:

参考: https://www.jb51.net/article/148995.htm

打开tomcat的解压之后的目录可以看到如下的目录结构:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EEZMYM83-1629527148294)(img\\tomcat1)]

1.Tomcat的bin目录:

bin目录主要是用来存放tomcat的命令,主要有两大类,一类是以.sh结尾的(linux命令),另一类是以.bat结尾的(windows命令)。

很多环境变量的设置都在此处,例如可以设置JDK路径、tomcat路径

startup 用来启动tomcat

shutdown 用来关闭tomcat

修改catalina可以设置tomcat的内存

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wHGQtkOv-1629527148295)(img\\tomcat2)]

2.Tomcat的conf目录:

conf目录主要是用来存放tomcat的一些配置文件。

server.xml可以设置端口号、设置域名或IP、默认加载的项目、请求编码

web.xml可以设置tomcat支持的文件类型

context.xml可以用来配置数据源之类的

tomcat-users.xml用来配置管理tomcat的用户与权限

在Catalina目录下可以设置默认加载的项目

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-glKbgEuy-1629527148296)(img\\tomcat3)]

3.Tomcat的lib目录:

lib目录主要用来存放tomcat运行需要加载的jar包。

例如,像连接数据库的jdbc的包我们可以加入到lib目录中来。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Si3VToCX-1629527148296)(img\\tomcat4)]

4.Tomcat的logs目录:

logs目录用来存放tomcat在运行过程中产生的日志文件,非常重要的是在控制台输出的日志。(清空不会对tomcat运行带来影响)

在windows环境中,控制台的输出日志在catalina.xxxx-xx-xx.log文件中

在linux环境中,控制台的输出日志在catalina.out文件中

5.temp:

temp目录用户存放tomcat在运行过程中产生的临时文件。(清空不会对tomcat运行带来影响)

6.Tomcat的webapps目录:

webapps目录用来存放应用程序,当tomcat启动时会去加载webapps目录下的应用程序。可以以文件夹、war包、jar包的形式发布应用。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TXD9owRP-1629527148297)(img\\tomcat5)]

7.Tomcat的work目录:

work目录用来存放tomcat在运行时的编译后文件,例如JSP编译后的文件。

清空work目录,然后重启tomcat,可以达到清除缓存的作用

11. Servlet初始化参数:

​ 注解配置和xml配置2种方式:

1. 注解配置

@WebServlet(name = "InitParamServlet",urlPatterns = "/init",initParams = {@WebInitParam(name ="username",value = "root"),@WebInitParam(name = "password",value = "123456")})
public class InitParamServlet extends HttpServlet{}

2. xml配置

​ 在web.xml文件里面配置

 <!--xml方式来配置servlet-->
    <servlet>
        <servlet-name>BServlet</servlet-name>
        <servlet-class>servlet.BServlet</servlet-class>

        <!--配置初始化参数-->
        <init-param>
            <param-name>username</param-name>
            <param-value>张三</param-value>
        </init-param>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>utf8</param-value>
        </init-param>

        <!-- 配置加载时机 -->
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>BServlet</servlet-name>
        <url-pattern>/bbb</url-pattern>
    </servlet-mapping>

初始化参数demo:

package com.jishou.servlet;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebInitParam;
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.util.Enumeration;

@WebServlet(name = "InitParamServlet",urlPatterns = "/init",initParams = {@WebInitParam(name ="username",value = "root"),@WebInitParam(name = "password",value = "123456")})
public class InitParamServlet extends HttpServlet {

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        ServletConfig config = this.getServletConfig();
        String username = config.getInitParameter("username");
        String password = config.getInitParameter("password");
        System.out.println("用户名: "+username+"密码: "+password);

        Enumeration<String> names = config.getInitParameterNames();
        //循环遍历枚举对象
        while (names.hasMoreElements()){
            String name = names.nextElement();
            System.out.println("参数名是: "+name);
        }
    }
}

12. Servlet之间的协作:

FIR:

forward:

​ 请求转发: request对象的方法

RequestDispatcher requestDispatcher = request.getRequestDispatcher(String path);
requestDispatcher.forward(request,response);

include:

​ 包含: request对象的方法

RequestDispatcher requestDispatcher = request.getRequestDispatcher(String path);
requestDispatcher.include(request,response);

redirect:

​ 重定向:response对象的方法,也可以重定向到第三方网址

response.sendRedirect(String path);

eg:

forward:

  1. FServlet1:
package forward;

import javax.servlet.RequestDispatcher;
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.PrintWriter;

@WebServlet(name = "FServlet1",urlPatterns = "/f1")
public class FServlet1 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        //请求 设置属性值
        request.setAttribute("name","servlet1...");
        //响应
        response.setContentType("text/html");
        PrintWriter out = response.getWriter();
        out.println("1111");
        //out.flush();
        //out.close();

        //forward 请求转发
        RequestDispatcher requestDispatcher = request.getRequestDispatcher("f2");
        requestDispatcher.forward(request,response);
    }
}
  1. FServlet2:
package forward;

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.PrintWriter;

@WebServlet(name = "FServlet2",urlPatterns = "/f2")
public class FServlet2 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        //取request携带过来的数据
        String name = (String) request.getAttribute("name");
        //响应
        response.setContentType("text/html");
        PrintWriter out = response.getWriter();
        out.println("22222");
        out.println("name: "+name);
        out.flush();
        out.close();
    }
}
  1. url访问:

http://localhost:8080/fir_war_exploded/f1

include:

  1. IServlet1

    package include;
    
    import javax.servlet.RequestDispatcher;
    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.PrintWriter;
    
    @WebServlet(name = "IServlet1",urlPatterns = "/i1")
    public class IServlet1 extends HttpServlet {
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
        }
    
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
            //请求 设置属性值
            request.setAttribute("name","servlet1...");
            //响应
            response.setContentType("text/html");
            PrintWriter out = response.getWriter();
            out.println("1111");
            //out.flush();
            //out.close();
    
            //include 包含
            RequestDispatcher requestDispatcher = request.getRequestDispatcher("i2");
            requestDispatcher.include(request,response);
    
        }
    }
    
  2. IServlet2

    package include;
    
    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.PrintWriter;
    
    @WebServlet(name = "IServlet2",urlPatterns = "/i2")
    public class IServlet2 extends HttpServlet {
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
        }
    
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
            //取request携带过来的数据
            String name = (String) request.getAttribute("name");
            //响应
            response.setContentType("text/html");
            PrintWriter out = response.getWriter();
            out.println("22222");
            out.println("name: "+name);
            out.flush();
            out.close();
        }
    }
    
  3. url访问:

    http://localhost:8080/fir_war_exploded/i1

redirect:

  1. RServlet1

    package redirect;
    
    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.PrintWriter;
    
    @WebServlet(name = "RServlet1",urlPatterns = "/r1")
    public class RServlet1 extends HttpServlet {
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
        }
    
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
            //请求 设置属性值
            request.setAttribute("name","servlet1...");
            //响应
            response.setContentType("text/html");
            PrintWriter out = response.getWriter();
            out.println("1111");
            //out.flush();
            //out.close();
            //重定向
            response.sendRedirect("r2");
        }
    }
    
  2. RServlet2

    package redirect;
    
    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.PrintWriter;
    
    @WebServlet(name = "RServlet2",urlPatterns = "/r2")
    public class RServlet2 extends HttpServlet {
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
        }
    
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
            //取request携带过来的数据
            String name = (String) request.getAttribute("name");
            //响应
            response.setContentType("text/html");
            PrintWriter out = response.getWriter();
            out.println("22222");
            out.println("name: "+name);
            out.flush();
            out.close();
        }
    }
    
  3. url访问:

    http://localhost:8080/fir_war_exploded/r1

区别:

forward()与include()区别:

forward方法是把请求的内容转发到另外的一个servlet.而include是把另一个servlet处理过后的内容拿过来.

举例来说:

比如在servlet1打一句out.print(“1111”),servlet2打上out.print(“22222”),

在servlet1中用forward命令会转到servlet2中,显示22222.

而在servlet1中使用include方法会依然在servlet1的页面中,但是在1111后打出22222.

forward()与redirect()区别:

forward仅是容器中控制权的转向,在客户端浏览器地址栏中不会显示出转向后的地址;

redirect则是完全的跳转,浏览器将会得到跳转的地址,并重新发送请求链接。这样,从浏览器的地址栏中可以看到跳转后的链接地址。

所以,forward更加高效,在forward可以满足需要时,尽量使用forward()方法,并且,这样也有助于隐藏实际的链接。

在有些情况下,比如,需要跳转到一个其它服务器上的资源,则必须使用sendRedirect()方法.从地址栏显示来说 forward是服务器请求资源,服务器直接访问目标地址的URL,把那个URL的响应内容读取过来,然后把这些内容 再发给浏览器.浏览器根本不知道服务器发送的内容从哪里来的,所以它的地址栏还是原来的地址. redirect是服务端根据逻辑,发送一个状态码,告诉浏览器

2. forward 和include 前后两个页面**request对象里的数据可以共享,**redirect前后数据不能共享
3. forward和include的url不会发生改变,redirect中url地址会发生改变
4. forward和include是在服务器端转发,redirect是发生在客户端浏览器

13. 会话( HttpSession )

1. HttpSession:

​ 概念:

​ 什么是会话?

​ 一段时间之内客户端(浏览器)与服务器之间进行的多次交互,这个过程就称为会话

​ 为什么要有会话?

​ 我们开发的servlet程序是基于http协议,此协议有这么特征,无状态协议(文本来,文本会,连接就断)
​ 解决问题的时候,有麻烦,就要在无状态协议之上实现所谓“有状态”的应用。

​ servlet的API中为我们提供了一个类型(HttpSession)它内部实现了“有状态”

​ 如何获取HttpSession对象:

​ HttpSession session = request.getSession();

​ 作用域:

​ 在整个会话期间有效,会话期间数据可以做到共享

​ 是用户级别的,一个用户的整个流程就是一个HttpSession对象;正常来说一个浏览器对应一个HttpSession 对象

​ 方法:

​ void setAttribute(String,Object) 设置键值对

​ Object getAttribute(String) 根据键来取值

​ void removeAttribute(String) 根据键来删除指定的键值对

2. 会话的过期:

2种方式设置:

​ 1.声明方式(配置文件)
​ tomcat安装根目录\\conf\\web.xml这个文件中是对tomcat中所有应用有效。
​ 如果自己的项目中与tomcat配置有冲突,以自己应用中的配置为准。

		<session-config>
			<session-timeout>分钟</session-timeout>
		</session-config>

​ <=0的数表示session永远不过期。禁止这样做。

  1. 编码方式

    void setMaxInactiveInterval(int seconds)次与次之间的间隔不能超过参数对应的秒钟 慢性自杀
    void invalidate() 立即失效 立即自杀

14. ServletContext:

ServletContext对象 : 代表该项目;相当于所有用户都可以共享的东西;可以用于统计访问次数等

一个项目里面一个ServletContext时间,他没有失效时间

如何获取ServletContext对象:

  1. 通过request对象来获取

    ServletContext servletContext = req.getServletContext();
    
  2. 通过httpSession对象来获取

    ServletContext servletContext = session.getServletContext();
    

方法:

​ void setAttribute(String,Object) 设置键值对

​ Object getAttribute(String) 根据键来取值

15. 作用域总结:

​ request对象: 类型HttpServletRequest: 数据在请求的前后两个页面可以共享

​ session对象: 类型HttpSession 数据在某个会话中可以共享,用户级别

​ servletContext对象:类型ServletContext: 数据在整个项目中,该应用中可以共享,所有用户都能共享的全局变量

3个作用域里面都有数据共享(取值传值)的方法:但是作用域不同

​ void setAttribute(String,Object) 设置键值对

​ Object getAttribute(String) 根据键来取值

16. JSP ( Java Server Pages ):

1. JSP概念

全称: Java Server Pages

jsp=html(js,css)+java代码片段 以html为主,java为辅

2. Jsp与servlet之间的关系:

web 容器处理JSP文件请求的三个阶段: 翻译阶段 编译阶段 执行阶段

jsp本质上是个servlet,在翻译阶段中会转成一个java文件,而这个java文件就间接的继承了HttpServlet

3. JSP语法

jsp中java代码表示方式:

	<%@   %>	jsp指令
	
				<%@ page  import="" pageEncoding="utf-8" %>   
					定义页面的相关信息   import 导包   pageEncoding="utf-8"  指明该页面编码方式 utf-8   中文编码
					
				<%@ include file="" %>
				
					引入另外一个jsp文件
	<%   %>		jsp代码片段  小脚本
	
				js 运行在客户端  jsp 运行在服务器端
	<%!   %>    全局变量  属性或方法放在这里面
	<%=   %>    表达式  取值   这个标记等同于out.println()。例如<%=1%>等同于out.print(1);
	<%--  --%>  jsp注释

JSP中的注释:
(1)、HTML注释:
(2)、JSP注释标记: <%–JSP注释(客户端不可以看到源代码)–%>
(3)、JSP脚本中注释 <%//单行注释%>、<%/多行注释法/%>

eg: jsp基本语法demo:

1.jsp

在web目录下创建jsp文件

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>

<h1>jsp语法</h1>
<%-- jsp注释 客户端看不到源代码--%>
<!-- html注释 客户端可以看到源代码-->
<%!
    String name="张三";
    int age=23;
%>
jsp中java代码片段演示:
<%
    out.println("姓名是:"+name);
    age++;
%>
表达式演示:
<%=(12+23)*3%><br/>
<%=age%>


</body>
</html>

4. jsp三大指令(3个指令)

指导(jsp)性命令

page include taglib

<%@ page import="" pageEncoding="utf-8"%>		
		import 导包   pageEncoding="utf-8"  页面的编码方式 utf-8中文编码

<%@ include file=“应用文件路径”%> 引入外部文件

<%@ taglib prefix="c" uri=""%>

eg: include标签用法展示:

include01.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ include file="include02.jsp"%>
<html>
<head>
    <title>Title</title>
</head>
<body>
        包含01
</body>
</html>

include02.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
        被包含02
</body>
</html>

浏览器访问:

http://localhost:8080/jspdemo_war_exploded/include01.jsp

结果两个jsp页面一并显示出来

eg: List集合循环遍历demo:

2.jsp

<%@ page import="com.zjj.pojo.Student" %>
<%@ page import="java.util.ArrayList" %>
<%@ page import="java.util.List" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>

<html>
<head>
    <title>Title</title>
</head>
<body>
    <h1>学生管理系统</h1>
    <table>
        <tr>
            <td>编号</td><td>姓名</td>
        </tr>

<%
  List<Student> list=new ArrayList<Student>();
  Student s1=new Student(1,"张三");
  Student s2=new Student(2,"李四");
  Student s3=new Student(3,"王五");

  list.add(s1);
  list.add(s2);
  list.add(s3);

  for(Student s: list){
      %>
        <tr>
            <td><%=s.getId()%></td><td><%=s.getName()%></td>
        </tr>
    <%
  }
%>
    </table>

</body>
</html>

5. jsp九大内置对象

9个内置对象说的是9个变量可以再java代码片段中直接使用。

request HttpServletRequest
response HttpServletResponse
session HttpSession
application ServletContext

out JspWriter(等同于PrintWriter)
​pageContext PageContext页面上下文
​exception Throwable
​config ServletConfig
​page jsp生成的java类型的当前对象

eg: 将后台定义的List集合在前台jsp页面展示:

  1. 创建实体类Student

    package com.zjj.pojo;
    
    public class Student {
    
        int id;
        String name;
    
        public Student() {
        }
    
        public Student(int id, String name) {
            this.id = id;
            this.name = name;
        }
    
        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;
        }
    
        @Override
        public String toString() {
            return "Student{" +
                    "id=" + id +
                    ", name='" + name + '\\'' +
                    '}';
        }
    }
    
  2. 创建ListServlet

    package com.zjj.servlet;
    
    import com.zjj.pojo.Student;
    
    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.util.ArrayList;
    import java.util.List;
    
    @WebServlet(name = "ListServlet",urlPatterns = "/list")
    public class ListServlet extends HttpServlet {
        @Override
        protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            List<Student> list=new ArrayList<Student>();
            Student s1=new Student(1,"张三");
            Student s2=new Student(2,"李四");
            Student s3=new Student(3,"王五");
    
            list.add(s1);
            list.add(s2);
            list.add(s3);
    
            req.setAttribute("list",list);
            req.getRequestDispatcher("list2.jsp").forward(req,resp);
    
        }
    }
    
  3. 创建list1.jsp

    <%@ page import="com.zjj.pojo.Student" %>
    <%@ page import="java.util.List" %><%--
      Created by IntelliJ IDEA.
      User: mumusan
      Date: 2021/4/24
      Time: 14:36
      To change this template use File | Settings | File Templates.
    --%>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>Title</title>
    </head>
    <body>
    
    <h1>学生管理系统</h1>
    <table>
        <tr>
            <td>编号</td><td>姓名</td>
        </tr>
    
        <%
            List<Student> list= (List<Student>) request.getAttribute("list");
            for(Student s: list){
        %>
        <tr>
            <td><%=s.getId()%></td><td><%=s.getName()%></td>
        </tr>
        <%
            }
        %>
    </table>
    
    </body>
    </html>
    
  4. 浏览器访问

    http://localhost:8080/jspdemo_war_exploded/list

6. jsp四大作用域

page范围:只在一个页面保留数据(javax.servlet.jsp.PageContext(抽象类))

request范围:只在一个请求中保存数据(javax.servlet.httpServletRequest)

Session范围:在一次会话中保存数据,仅供单个用户使用(javax.servlet.http.HttpSession)

Application范围:在整个服务器中保存数据,全部用户共享(javax.servlet.ServletContext)

7. EL表达式:

EL表达式的全称是 Expression Language

	语法:
		${  el表达式 }
		
	操作符:  

		关系操作符	
			==(eq)等于		!=(ne)不等于
			<(lt)小于		>(gt)大于
			<=(le)小于等于		>=(ge)大于等于

		逻辑操作符
			&&(and) 与
			||(or) 或
			!(not)非
    隐式对象: 

        作用域对象:

        pageScope 本页面	requestScope 请求
        sessionScope 会话	applicationScope 程序

        参数访问对象
        Param  单一
        paramValues 一组

        jsp对象:    pageContext

demo:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>

out内置对象取值:
<%
    out.println((12+34)*4);
    User user1=new User(2,"李四","123456");
    User user2=new User(3,"张三","123456");
    User user3=new User(4,"王五","123456");
    request.setAttribute("user",user1);
    session.setAttribute("user",user2);
    application.setAttribute("user",user3);
%>
<br>
表达式取值: <%=(12+56)/4%>
<br>
el表达式取值: ${ (14+78)%7}
取javabean值:
request name: ${requestScope.user.username}<br>
session name: ${sessionScope.user.username}<br>
application name: ${applicationScope.user.username}<br>
<!--当没有指定作用域的时候,他将从小到大依次搜索-->
name: ${user.username}

</body>
</html>

8. JSTL(JavaServerPage Standard Tag Library)jsp标准标记库

作用:使用标记来替换java代码,整个页面都是标签,方便好看

标签:

core:核心标签库,里面的代码都是一些java编程语言的基础,例如分支判断,设置值,取值,显示值

fmt: 格式化标签库:可以格式化日期等数据

	通用标签
		<c:set>   <c:out>  <c:remove>
	条件标签
		<c:if>	  <c:choose>   <c:when>  <c:otherwise>
	迭代标签
		<c:forEach>

使用步骤:

  1. 引入jstl标签库的依赖,复制粘贴到web-inf/lib目录里面

    jstl-1.2.jar

  2. 引入jstl标签声明

    核心标签库:
    <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
    
    格式化标签库:
    <%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
    
  3. 使用标签

    <%@ page import="com.jishou.pojo.Student" %>
    <%@ page import="java.util.ArrayList" %>
    <%@ page import="java.util.List" %>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
    <%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
    <html>
    <head>
        <title>Title</title>
    </head>
    <body>
    <%
        List<Student> list=new ArrayList<>();
        Student s1=new Student(1,"aa",12,new Date(),"北京","aa");
        Student s2=new Student(2,"bb",13,new Date(),"上海","bb");
        Student s3=new Student(3,"cc",14,new Date(),"长沙","cc");
    
        list.add(s1);
        list.add(s2);
        list.add(s3);
    
        request.setAttribute("list",list);
    %>
    <table width="70%" height="50%">
        <tr>
            <td>编号</td>
            <td>姓名</td>
            <td>年龄</td>
            <td>生日</td>
            <td>地址</td>
            <td>头像</td>
            <td>
                <a href="add.jsp">添加学生</a>
            </td>
        </tr>
    
        <!--test 判断的条件-->
        <c:if test="${list!=null && list.size()>0}">
    
            <!--items 要循环遍历的集合对象 var 集合中的每个对象-->
                <tr>
                    <td>${s.id}</td>
                    <td>${s.sname}</td>
                    <td>${s.age}</td>
                    <td>
                        <fmt:formatDate value="${s.birthday}" pattern="yyyy-MM-dd"/>
    
                    </td>
                    <td>${s.address}</td>
                    <td>${s.photo}</td>
    
    
                    <td>
                        <a href="">修改</a>
                        <a href="">删除</a>
                    </td>
                </tr>
            </c:forEach>
        </c:if>
    </table>
    </body>
    </html>
    

eg: 将之前列表页面使用jstl标签库+el表达式改造:

list2.jsp

<%@ page import="com.zjj.pojo.Student" %>
<%@ page import="java.util.List" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
    <title>Title</title>
</head>
<body>

<h1>学生管理系统</h1>
<table>
    <tr>
        <td>编号</td><td>姓名</td>
    </tr>


   <c:forEach var="s" items="${requestScope.list}">
       <tr>
           <td>${s.id}</td><td>${s.name}</td>
       </tr>
   </c:forEach>
</table>

</body>
</html>

17. 过滤器(Filter):

作用:
过滤请求以及响应,针对请求与响应的时候,字符编码过滤,安全过滤

开发filter:

​ 1.编写普通java类,实现javax.servlet.Filter接口

​ 2.重写接口中方法(过滤逻辑)

​ 3.配置此过滤器(配置过滤器过滤那些资源)

​ 4.启动web服务器(过滤的功能是服务器自动调用)

18. 监听器:

监听器用于监听web应用中某些对象、信息的创建、销毁、增加,修改,删除等动作的发生,然后作出相应的响应处理。当范围对象的状态发生变化的时候,服务器自动调用监听器对象

以上是关于(Servlet+Jsp)Web编程笔记(一套就够了)的主要内容,如果未能解决你的问题,请参考以下文章

SpringCloud微服务框架一套就够(下集)

jsp/servlet学习笔记(核心编程)servlet部分

jsp/servlet学习笔记(核心编程)jsp部分

JSP/Servlet Web 学习笔记 DayFour

JSP/Servlet Web 学习笔记 DayThree

JSP/Servlet Web 学习笔记 DayTwo