JAVA学习笔记—JAVA WEB(一)JAVA WEB核心(上)

本文详细介绍了JAVA WEB的核心技术,包括Servlet的基本概念、HTTP协议、Tomcat服务器的使用、Servlet的生命周期及请求响应处理,强调了GET和POST请求的区别以及处理乱码的方法。此外,还探讨了ServletConfig和ServletContext接口的作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

文章目录

1. Servlet核心技术(上)

1.1 基本概念(常识)

1.1.1 C/S架构的概念

C/S架构(Client/Server,客户端/服务器模式),是一种比较早的软件体系结构,也是生活中很常见的结构。这种结构将需要处理的业务合理地分配到客户端和服务器端,客户端通常负责完成与用户的交互任务,服务器通常负责数据的管理。
C/S架构的主要优点如下:
客户端的界面和功能可以很丰富。
应用服务器的负荷较轻。
响应速度较快。
C/S架构的主要缺点如下:
适用面窄,用户群固定。
维护和升级的成本高,所有的客户端都需要更新版本。

1.1.2 B/S架构的概念

B/S架构(Browser/Server,浏览器/服务器模式),是互联网兴起后的软件体系结构,该结构将系统功能实现的主要业务逻辑集中到服务器端,极少数业务逻辑在浏览器实现,浏览器通常负责完成与用户的交互任务,服务器通常负责数据的管理。
B/S架构的主要优点如下:
无需安装客户端,只要有浏览器即可。
适用面广,用户群不固定。
通过权限控制实现多客户访问的目的,交互性较强。
维护和升级的成本低,无需更新所有客户端版本。
B/S架构的主要缺点如下:
应用服务器的负荷较重。
浏览器的界面和功能想要达到客户端的丰富程度需要花费大量的成本。
在跨浏览器上不尽如人意,适配比较麻烦。

1.1.3 JavaWeb的概念

Web本意为网页的含义,这里表示互联网上供外界访问的资源。
互联网上供外界访问的资源主要分为以下两种:
静态资源:主要指Web页面中供人们浏览的数据始终是不变。
动态资源:主要指Web页面中供人们浏览的数据由程序产生,不同时间点访问页面看到的内容各不相同。
JavaWeb主要指使用Java语言进行动态Web资源开发技术的统称,是解决相关Web互联网领域的技术总和。
早期的B/S架构

image-20201125134011481

后来的B/S架构

image-20201125133513735

1.2 HTTP协议(熟悉)

1.2.1 HTTP协议的概念

HTTP协议(HyperText Transfer Protocol,超文本传输协议)是由W3C(万维网联盟)组织制定的一种应用层协议,是用来规范浏览器与Web服务器之间如何通讯的数据格式,主要涉及浏览器的发请求格式和服务器的响应格式。
HTTP协议通常承载于TCP协议之上,而承载于TLS或SSL协议层之上的协议就是常说的HTTPS协议。
HTTP默认的端口号为80,HTTPS默认的端口号为443。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PmGFZojF-1606287693401)(https://i.loli.net/2020/11/25/nkl2OjNHuBRf6tM.png)]

1.2.2 HTTP请求格式

客户端发送一个HTTP请求到服务器的请求消息主要包括:请求行、请求头、空白行和请求体。

请求行用来说明请求类型和要访问的资源以及所使用的HTTP版本,格式如下:
请求类型 请求的路径 协议的版本(1.1)
请求头是紧接着请求行(即第一行)之后的部分,用来说明服务器要使用的附加信息,格式
(key:value)如下:
主机 请求长度 请求的浏览器相关信息
空白行就是请求头部的空行,即使后面的请求数据为空则必须有空行。
请求体也叫请求数据,可以添加任意的其他数据。

1.2.3 HTTP响应格式

通常情况下服务器接收并处理客户端发过来的请求后会返回一个HTTP的响应消息,主要包括:响应行、响应头、空白行和响应体。

响应行用来说明HTTP协议版本号和状态码以及状态消息,格式如下:
协议的版本(1.0 1.1) 状态码 (200 成功 404 路径错误 500 服务错误) 状态信息
响应头用来说明客户端要使用的一些附加信息,格式(key:value)。
空白行就是响应头部的空行,即使后面的请求数据为空则必须有空行。
响应体用来服务器返回给客户端的文本信息。

1.3 Tomcat服务器(重点)

1.3.1 基本概念

Tomcat本意为公猫的含义,最初是由Sun公司的软件架构师詹姆斯·邓肯·戴维森开发的,后来他帮助将其变为开源项目并由Sun公司贡献给Apache软件基金会。
Tomcat 服务器是一个开源的轻量级Web应用服务器,在中小型系统和并发量小的场合下被普遍使用,是开发和调试Servlet、JSP 程序的首选。

1.3.3 目录结构

bin 主要存放二进制可执行文件和脚本。
conf 主要存放各种配置文件。
lib 主要用来存放Tomcat运行需要加载的jar包。
logs 主要存放Tomcat在运行过程中产生的日志文件。
temp 主要存放Tomcat在运行过程中产生的临时文件。
webapps 主要存放应用程序,当Tomcat启动时会去加载该目录下的应用程序。
work 主要存放tomcat在运行时的编译后文件,例如JSP编译后的文件。

1.3.4 启动和关闭

启动方式
使用bin目录下的批处理文件startup.bat来启动Tomcat服务器,若出现一个毫秒数说明启动成功。
关闭方式
使用bin目录下的批处理文件shutdown.bat来关闭Tomcat服务器。
注意事项
启动之前首先安装JDK并配置环境变量JAVA_HOME,若希望Tomcat服务器可以在任意路径启动,则需要配置环境变量CATALINA_HOME。
启动信息乱码的处理方式:logging.properties文件修改为
java.util.logging.ConsoleHandler.encoding = GBK

1.3.5 配置文件

server.xml文件是服务器的主配置文件,可以设置端口号、设置域名或IP、默认加载的项目、请求编码等。

<Connector port="8888" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />

tomcat-users.xml文件用来配置管理Tomcat服务器的用户与权限 。

<role rolename="manager-gui"/>
<user username="admin" password="123456" roles="manager-gui"/>

1.4 Servlet的概念和使用(重点)

1.4.1 基本概念

Servlet(Server Applet)是Java Servlet的简称,称为小服务程序或服务连接器,是Java语言编写的服务器端程序,换句话说,Servlet就是运行在服务器上的Java类。
Servlet用来完成B/S架构下客户端请求的响应处理,也就是交互式地浏览和生成数据,生成动态Web内容。

1.4.2 Servlet的编程步骤

建立一个Java Web Application项目并配置Tomcat服务器。
自定义类实现Servlet接口或继承 HttpServlet类(推荐) 并重写service方法。
将自定义类的信息配置到 web.xml文件并启动项目,配置方式如下:

<!-- 配置Servlet -->
<servlet>
<!-- HelloServlet是Servlet类的别名 -->
<servlet-name> HelloServlet </servlet-name>
<!-- com.lagou.task01.HelloServlet是包含路径的真实的Servlet类名 -->
<servlet-class> com.lagou.task01.HelloServlet </servlet-class>
</servlet>
<!-- 映射Servlet -->
<servlet-mapping>
<!-- HelloServlet是Servlet类的别名,与上述名称必须相同 -->
<servlet-name> HelloServlet </servlet-name>
<!-- /hello是供浏览器使用的地址 -->
<url-pattern> /hello </url-pattern>
</servlet-mapping>

在浏览器上访问的方式为:

http://localhost:8080/工程路径/url-pattern的内容

1.4.3 Servlet接口

(1)基本概念
javax.servlet.Servlet接口用于定义所有servlet必须实现的方法。
(2)常用的方法

方法声明功能介绍
void init(ServletConfig config)由servlet容器调用,以向servlet指示servlet正在 被放入服务中
void service(ServletRequest req, ServletResponse res)由servlet容器调用,以允许servlet响应请求
ServletConfig getServletConfig()返回ServletConfig对象,该对象包含此servlet的初 始化和启动参数
String getServletInfo()返回有关servlet的信息,如作者、版本和版权
void destroy()由servlet容器调用,以向servlet指示该servlet正 在退出服务
public class HelloServlet implements Servlet {
    @Override
    public void init(ServletConfig servletConfig) throws ServletException {

    }

    @Override
    public ServletConfig getServletConfig() {
        return null;
    }

    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        System.out.println("接收到了浏览器的请求并做出了响应!");
    }

    @Override
    public String getServletInfo() {
        return null;
    }

    @Override
    public void destroy() {

    }
}

1.4.5 GenericServlet类

(1)基本概念
javax.servlet.GenericServlet类主要用于定义一个通用的、与协议无关的servlet,该类实现了Servlet接口。
若编写通用servlet,只需重写service抽象方法即可。
(2)常用的方法

方法声明功能介绍
abstract void service(ServletRequest req, ServletResponse res)由servlet容器调用允许servlet响应 请求
public class HelloServlet2 extends GenericServlet {
    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        System.out.println("继承GenericServlet类的方式来创建Servlet");
    }
}

1.4.6 HttpServlet类

(1)基本概念
javax.servlet.http.HttpServlet类是个抽象类并继承了GenericServlet类。
用于创建适用于网站的HTTP Servlet,该类的子类必须至少重写一个方法。
(2)常用的方法

方法声明功能介绍
void doGet(HttpServletRequest req, HttpServletResponse resp)处理客户端的GET请求
void doPost(HttpServletRequest req, HttpServletResponse resp)处理客户端的POST请求
void init()进行初始化操作
void service(HttpServletRequest req, HttpServletResponse resp)根据请求决定调用doGet还是 doPost方法
void destroy()删除实例时释放资源
public class HelloServlet3 extends HttpServlet {

    public HelloServlet3() {
        System.out.println("构造方法调用了");
    }

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("这是采用继承HttpServlet类的方式创建,以后的开发中推荐该方式!");
    }

    @Override
    public void destroy() {
        System.out.println("销毁操作开始喽...");
    }

    @Override
    public void init() throws ServletException {
        System.out.println("初始化操作开始喽...");
    }
}

1.4.7 Servlet 的生命周期

image-20201125134450785

构造方法只被调用一次,当第一次请求Servlet时调用构造方法来创建Servlet的实例。
init方法只被调用一次,当创建好Servlet实例后立即调用该方法实现Servlet的初始化。
service方法被多次调用,每当有请求时都会调用service方法来用于请求的响应。
destroy方法只被调用一次,当该Servlet实例所在的Web应用被卸载前调用该方法来释放当前占用的资源。

1.5 POST和GET请求(重点)

1.5.1 GET请求

发出GET请求的主要方式:
(1)在浏览器输入URL按回车
(2)点击<a>超链接
(3)点击submit按钮,提交 <form method=“get”>表单
GET请求特点:
会将请求数据添加到请求URL地址的后面,只能提交少量的数据、不安全

1.5.2 POST请求

发出POST请求的方法如下:
点击submit按钮,提交 <form method=“post”>表单
POST请求的特点:
请求数据添加到HTTP协议体中,可提交大量数据、安全性好
public class HelloServlet4 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("Post请求方式...");
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("Get请求方式...");
        this.doPost(request, response);
    }

   /* @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("原来使用注解可以如此潇洒...");
        String method = req.getMethod();
        System.out.println("获取到的请求方式为:" + method);
        if ("get".equalsIgnoreCase(method)) {
            doGet(req, resp);
        }
        if ("post".equalsIgnoreCase(method)) {
            doPost(req, resp);
        }
    }*/
}

1.5.3 ServletRequest接口

(1)基本概念
javax.servlet.ServletRequest接口主要用于向servlet提供客户端请求信息,可以从中获取到任何请求信息。
Servlet容器创建一个ServletRequest对象,并将其作为参数传递给Servlet的service方法。
(2)常用的方法

方法声明功能介绍
String getParameter(String name)以字符串形式返回请求参数的值,如果该参数不存在,则返回空 值
String[] getParameterValues( String name)返回一个字符串对象数组,其中包含给定请求参数所具有的所有 值,如果该参数不存在,则返回空值
Enumeration getParameterNames()返回包含此请求中包含的参数名称的字符串对象的枚举。如果请 求没有参数,则方法返回空枚举
Map<String, String[]> getParameterMap()返回请求参数的键值对,一个键可以对应多个值
String getRemoteAddr()返回发送请求的客户端或最后一个代理的IP地址
int getRemotePort()返回发送请求的客户端或最后一个代理的端口号
public class ParameterServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 6.设置请求信息中的编码方式为utf-8来解决乱码问题
        request.setCharacterEncoding("utf-8");

        // 1.获取指定参数名称对应的参数值并打印
        String name = request.getParameter("name");
        System.out.println("获取到的姓名为:" + name);
        String[] hobbies = request.getParameterValues("hobby");
        System.out.print("获取到的爱好有:");
        for (String ts : hobbies) {
            System.out.print(ts + " ");
        }
        System.out.println();

        System.out.println("-------------------------------------------------------");
        // 2.获取所有参数的名称
        Enumeration<String> parameterNames = request.getParameterNames();
        System.out.print("获取到的所有参数名称为:");
        while (parameterNames.hasMoreElements()) {
            System.out.print(parameterNames.nextElement() + " ");
        }
        System.out.println();

        System.out.println("-------------------------------------------------------");
        // 3.获取请求参数名和对应值的第二种方式
        Map<String, String[]> parameterMap = request.getParameterMap();
        // 使用Map集合中所有的键值对组成Set集合
        Set<Map.Entry<String, String[]>> entries = parameterMap.entrySet();
        // 遍历Set集合
        for (Map.Entry<String, String[]> me : entries) {
            System.out.print(me.getKey() + "对应的数值有:");
            for (String ts : me.getValue()) {
                System.out.print(ts + " ");
            }
            System.out.println();
        }

        System.out.println("-------------------------------------------------------");
        // 4.获取客户端请求的其它信息
        System.out.println("发送请求的客户端IP地址为:" + request.getRemoteAddr());
        System.out.println("发送请求的客户端端口号为:" + request.getRemotePort());
        System.out.println("请求资源的路径为:" + request.getRequestURI());
        System.out.println("请求资源的完整路径为:" + request.getRequestURL());
        System.out.println("请求方式为:" + request.getMethod());
        System.out.println("请求的附带参数为:" + request.getQueryString());
        System.out.println("请求的Servlet路径为:" + request.getServletPath());

        System.out.println("-------------------------------------------------------");
        // 5.向浏览器发出响应数据
        // 获取响应数据的默认编码方式
        String characterEncoding = response.getCharacterEncoding();
        System.out.println("服务器响应数据的默认编码方式为:" + characterEncoding); // ISO-8859-1
        // 设置服务器和浏览器的编码方式以及文本类型
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter writer = response.getWriter();
        //writer.write("I Received!");
        //writer.write("我接收到了!");
        Random ra = new Random();
        int num = ra.nextInt(100) + 1;
        writer.write("<h1>" + num + "</h1>");
        System.out.println("服务器发送数据成功!");
        writer.close();
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }
}

1.5.4 HttpServletRequest接口

(1)基本概念
javax.servlet.http.HttpServletRequest接口是ServletRequest接口的子接口,主要用于提供HTTP请求信息的功能。
不同于表单数据,在发送HTTP请求时,HTTP请求头直接由浏览器设置。
可直接通过HttpServletRequest对象提供的一系列get方法获取请求头数据。
(2)常用的方法

方法声明功能介绍
String getRequestURI()返回此请求的资源路径信息
StringBuffer getRequestURL()返回此请求的完整路径信息
String getMethod()返回发出此请求的HTTP方法的名称,例如GET、POST
String getQueryString()返回路径后面请求中附带的参数
String getServletPath()返回此请求中调用servlet的路径部分

1.5.5 ServletResponse接口

(1)基本概念
javax.servlet.ServletResponse接口用于定义一个对象来帮助Servlet向客户端发送响应。
Servlet容器创建ServletResponse对象,并将其作为参数传递给servlet的service方法。
(2)常用方法

方法声明功能介绍
PrintWriter getWriter()返回可向客户端发送字符文本的PrintWriter对象
String getCharacterEncoding()获取响应内容的编码方式
void setContentType(String type)如果尚未提交响应,则设置发送到客户端响应的内容类型。内容类型 可以包括字符编码规范,例如text/html;charset=UTF-8

1.5.6 HttpServletResponse接口

(1)基本概念
javax.servlet.http.HttpServletResponse接口继承ServletResponse接口,以便在发送响应时提供特定于HTTP的功能。
(2)常用的方法

方法声明功能介绍
void sendRedirect(String location)使用指定的重定向位置URL向客户端发送临时重定向响应

1.5.7 使用示例

// 继承HttpServlet
public class HelloWorld extends HttpServlet {
    // 重写HttpServlet中的doGet方法
    protected void doGet(HttpServletRequest request, HttpServletResponseresponse)
    throws IOException, ServletException {
    // 设置响应输出编码,避免中文乱码
    response.setContentType(“text/html;charset=utf-8);
    // 获取响应输出流
    PrintWriter out= response.getWriter();
    // 利用输出流输出信息
    out.println(<html><body> Hello world!</body></html>);
    //关闭流
    out.close();
    }
}

1.6 Servlet接收中文乱码(重点)

1.6.1 接收乱码原因

浏览器在提交表单时,会对中文参数值进行自动编码。当Tomcat服务器接收到浏览器请求后自动解码,当编码与解码方式不一致时,就会导致乱码。

1.6.2 解决POST接收乱码

接收之前设置编码方式:
request.setCharacterEncoding(“utf-8”)
提示:
必须在调用request.getParameter(“name”)之前设置

1.6.3 解决GET接收乱码

将接收到的中文乱码重新编码:
// 接收到get请求的中文字符串
String name = request.getParameter("name");
// 将中文字符重新编码,默认编码为ISO-8859-1
String userName = new String(name.getBytes(“ISO-8859-1”),“utf-8");

1.7 ServletConfig接口(熟悉)

(1)基本概念
javax.servlet.ServletConfig接口用于描述Servlet本身的相关配置信息,在初始化期间用于将信息传递给Servlet配置对象。
(2)配置方式

<!-- 在web.xml中配置ServletConfig初始化参数 -->
<servlet>
<servlet-name>actionservlet</servlet-name>
<servlet-class>com.lagou.demo01.ActionServlet</servlet-class>
<!-- 配置 Serlvet 的初始化参数 -->
<init-param>
<!-- 参数名 -->
<param-name>config</param-name>
<!-- 参数值 -->
<param-value>struts.xml</param-value>
</init-param>
</servlet>
方法声明功能介绍
String getServletName()返回Servlet的别名
String getInitParameter(String name)返回包含初始化参数值的字符串,如果该参数不存在,则返回null
Enumeration getInitParameterNames()将servlet的初始化参数的名称作为字符串对象的枚举返回,如果 servlet没有初始化参数,则返回空枚举
ServletContext getServletContext()返回对调用方正在其中执行的ServletContext的引用
public class ConfigServlet implements Servlet {
    @Override
    public void init(ServletConfig servletConfig) throws ServletException {
        System.out.println("初始化操作执行了...");
        System.out.println("Servlet的别名是:" + servletConfig.getServletName()); // ConfigServlet

        System.out.println("-----------------------------------------------");
        // 获取配置文件中的初始化参数信息
        String userName = servletConfig.getInitParameter("userName");
        System.out.println("获取到的初始化用户名为:" + userName);
        // 获取所有配置参数的名称
        Enumeration<String> initParameterNames = servletConfig.getInitParameterNames();
        while (initParameterNames.hasMoreElements()) {
            System.out.println("初始化参数名为:" + initParameterNames.nextElement());
        }

        System.out.println("-----------------------------------------------");
        // 获取ServletContext接口的引用
        ServletContext servletContext = servletConfig.getServletContext();
        System.out.println("获取到的ServletContext引用为:" + servletContext);
    }

    @Override
    public ServletConfig getServletConfig() {
        return null;
    }

    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {

    }

    @Override
    public String getServletInfo() {
        return null;
    }

    @Override
    public void destroy() {

    }
}

1.8 ServletContext接口(熟悉)

(1)基本概念
javax.servlet.ServletContext接口主要用于定义一组方法,Servlet使用这些方法与它的Servlet容器通信。
服务器容器在启动时会为每个项目创建唯一的一个ServletContext对象,用于实现多个Servlet之间的信息共享和通信。
在Servlet中通过this.getServletContext()方法可以获得ServletContext对象。
(2)配置方式

<!--在web.xml中配置ServletContext初始化参数 -->
<context-param>
<param-name>username</param-name>
<param-value>scott</param-value>
<context-param>
<context-param>
<param-name>password</param-name>
<param-value>tiger</param-value>
<context-param>
方法声明功能介绍
String getInitParameter(String name)返回包含初始化参数值的字符串,如果该参数不存在,则返回 null
Enumeration getInitParameterNames()将servlet的初始化参数的名称作为字符串对象的枚举返回,如 果servlet没有初始化参数,则返回空枚举
String getRealPath(String path)返回包含给定虚拟路径的实际路径的字符串
String getContextPath()返回与此上下文关联的主路径
InputStream getResourceAsStream(String path)将位于指定路径的资源作为InputStream对象返回
void setAttribute(String name, Object object)将指定的属性名和属性值绑定到当前对象
Object getAttribute(String name)根据执行的属性名获取属性值
void removeAttribute(String name)删除指定的属性名信息
public class ContextServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 1.配置参数的获取
        ServletContext servletContext = getServletConfig().getServletContext();
        Enumeration<String> initParameterNames = servletContext.getInitParameterNames();
        while (initParameterNames.hasMoreElements()) {
            String s = initParameterNames.nextElement();
            System.out.println( s + "对应的值为:" + servletContext.getInitParameter(s));
        }

        System.out.println("----------------------------------------------------------");
        // 2.相关路径的获取
        // 本质上就是获取工程路径    /工程名
        String contextPath = servletContext.getContextPath();
        System.out.println("获取上下文关联的路径信息为:" + contextPath); // /task01_demo02

        // / 在服务器被解析为: http://ip地址:端口号/工程名  获取实际路径信息
        // 获取到的是部署工程路径信息   对应  当前工程中的web目录
        String realPath = servletContext.getRealPath("/");
        // C:\Users\Marz\IdeaProjects\javaweb\out\artifacts\task01_demo02_war_exploded\
        System.out.println("获取到的实际路径信息为:" + realPath);

        System.out.println("----------------------------------------------------------");
        // 3.设置和获取属性信息
        servletContext.setAttribute("key", "value");
        Object key = servletContext.getAttribute("key");
        System.out.println("根据参数指定的属性名获取到的属性值为:" + key); // value
        servletContext.removeAttribute("key");
        key = servletContext.getAttribute("key");
        System.out.println("根据参数指定的属性名获取到的属性值为:" + key); // null
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }
}

2. Servlet核心技术(下)

2.1 Servlet+JDBC应用(重点)

在Servlet中可以使用JDBC技术访问数据库,常见功能如下:
查询DB数据,然后生成显示页面,例如:列表显示功能。
接收请求参数,然后对DB操作,例如:注册、登录、修改密码等功能。
为了方便重用和便于维护等目的,经常会采用DAO(Data Access Object)模式对数据库操作进行独立封装。

image-20201125135905111

DAO工厂(工厂模式)
工厂类:封装了对象的创建细节,为调用者提供符合要求的对象。

//dao
public class UserDao {

    public int createUser(User user) {
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        try {
            // 1.获取连接
            connection = DbUtil.getConnection();
            // 2.准备sql语句
            String sql = "insert into t_user values(null, ?, ?)";
            // 3.获取PrepareStatement类型的引用
            preparedStatement = connection.prepareStatement(sql);
            // 4.向问号所占的位置设置数据
            preparedStatement.setString(1, user.getUserName());
            preparedStatement.setString(2, user.getPassword());
            // 5.执行sql语句
            int row = preparedStatement.executeUpdate();
            return row; // 执行成功
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            // 6.关闭资源
            try {
                DbUtil.closeConnection(connection, preparedStatement);
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        return 0; // 执行失败
    }
}


//model
public class User {
    private int id;
    private String userName;
    private String password;

    public User() {
    }

    public User(String userName, String password) {
        this.userName = userName;
        this.password = password;
    }

    public int getId() {
        return id;
    }

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

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public String toString() {
        return "User{" +
                "userName='" + userName + '\'' +
                ", password='" + password + '\'' +
                '}';
    }
}


//servlet
public class RegisterServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 1.获取请求对象中保存的用户名和密码信息
        String userName = request.getParameter("userName");
        System.out.println("获取到的用户名为:" + userName);
        String password = request.getParameter("password");
        System.out.println("获取到的密码为:" + password);
        // 2.将接受到的用户名和密码信息打包成用户对象交给DAO层进行处理
        User user = new User(userName, password);
        UserDao userDao = new UserDao();
        int res = userDao.createUser(user);
        // 3.将处理结果响应到浏览器
        response.setContentType("text/html;charset=utf-8");
        PrintWriter writer = response.getWriter();
        if (1 == res) {
            System.out.println("注册成功!");
            writer.write("<h1>注册成功!</h1>");
        } else {
            writer.write("<h1>注册失败!</h1>");
        }
        writer.close();
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }
}


//DBUtils

public class DbUtil {
    private static String jdbcName;   // 用于描述驱动信息
    private static String dbUrl;      // 用于描述URL信息
    private static String dbUserName; // 用户描述用户名信息
    private static String dbPassword; // 用户描述密码信息

    // 进行静态成员的初始化操作
    static {
        jdbcName = "com.mysql.jdbc.Driver";
        dbUrl = "jdbc:mysql://localhost:3306/db_web";
        dbUserName = "root";
        dbPassword = "123456";
        try {
            Class.forName(jdbcName);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取连接
     * @return
     * @throws SQLException
     */
    public static Connection getConnection() throws SQLException {
        Connection con = DriverManager.getConnection(dbUrl, dbUserName, dbPassword);
        return con;
    }

    /**
     * 关闭连接
     * @param con
     * @throws SQLException
     */
    public static void closeConnection(Connection con, PreparedStatement psts) throws SQLException {
        if (null != con) {
            con.close();
        }
        if (null != psts) {
            psts.close();
        }
    }
}

//HTML
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>实现简单的注册功能</title>
</head>
<body>
<form action="register" method="post">
    用户名:<input type="text" name="userName"/><br/>&nbsp;&nbsp;&nbsp;&nbsp;码:<input type="text" name="password"/><br/>
    <input type="submit" value="注册"/>
</form>
</body>
</html>

2.2 重定向和转发(重点)

2.2.1 重定向的概述

(1)重定向的概念
首先客户浏览器发送http请求,当web服务器接受后发送302状态码响应及对应新的location给客户浏览器,客户浏览器发现是302响应,则自动再发送一个新的http请求,请求url是新的location地址,服务器根据此请求寻找资源并发送给客户。
(2)重定向的实现
实现重定向需要借助javax.servlet.http.HttpServletResponse接口中的以下方法:

方法声明功能介绍
void sendRedirect(String location)使用指定的重定向位置URL向客户端发送临时重定向响 应

(3)重定向的原理

image-20201125140046342

(4)重定向的特点
重定向之后,浏览器地址栏的URL会发生改变。
重定向过程中会将前面Request对象销毁,然后创建一个新的Request对象。

重定向的URL可以是其它项目工程。

public class RedirectServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("接收到了浏览器的请求...");
        // 重定向,也就是给浏览器发送一个新的位置
        //response.sendRedirect("target.html");
        response.sendRedirect("https://www.baidu.com/index.php?tn=monline_3_dg");
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }
}

2.2.2 转发的概述

(1) 转发的概念
一个Web组件(Servlet/JSP)将未完成的处理通过容器转交给另外一个Web组件继续处理,转发的各个组件会共享Request和Response对象。
(2) 转发的实现
绑定数据到Request对象

方法声明功能介绍
Object getAttribute(String name)将指定属性值作为对象返回,若给定名称属性不存 在,则返回空值
void setAttribute(String name,Object o)在此请求中存储属性值

获取转发器对象

方法声明功能介绍
RequestDispatcher getRequestDispatcher(String path)返回一个RequestDispatcher对象,该对象充当位 于给定路径上的资源的包装器

转发操作

方法声明功能介绍
void forward(ServletRequest request, ServletResponse response)将请求从一个servlet转发到服务器上的另一个资 源(Servlet、JSP文件或HTML文件)
public class ForwardServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("接收到了浏览器的请求...");
        // 向request对象中设置属性信息
        request.setAttribute("key1", "value1");
        // 转发,也就是让Web组件将任务转交给另外一个Web组件
        //RequestDispatcher requestDispatcher = request.getRequestDispatcher("/targetServlet");
        RequestDispatcher requestDispatcher = request.getRequestDispatcher("https://www.baidu.com/index.php?tn=monline_3_dg");
        requestDispatcher.forward(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }
}


public class TargetServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("转发过来了...");
        // 获取request对象中的属性值判断是否共享
        Object key1 = request.getAttribute("key1");
        System.out.println("获取到的属性值为:" + key1); // value1
        // 通过打印流向页面写入转发成功的信息
        response.setContentType("text/html;charset=utf-8");
        response.getWriter().write("<h1>转发成功!</h1>");
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }
}

(3)转发的特点
转发之后浏览器地址栏的URL不会发生改变。
转发过程中共享Request对象。
转发的URL不可以是其它项目工程。
(4) 重定向和转发的比较

image-20201125140317665

2.3 Servlet线程安全(重点)

服务器在收到请求之后,会启动一个线程来进行相应的请求处理。
默认情况下,服务器为每个Servlet只创建一个对象实例。当多个请求访问同一个Servlet时,会有
多个线程访问同一个Servlet对象,此时就可能发生线程安全问题。
多线程并发逻辑,需要使用synchronized对代码加锁处理,但尽量避免使用。

2.4 状态管理(重点)

Web程序基于HTTP协议通信,而HTTP协议是”无状态”的协议,一旦服务器响应完客户的请求之后,就断开连接,而同一个客户的下一次请求又会重新建立网络连接。
服务器程序有时是需要判断是否为同一个客户发出的请求,比如客户的多次选购商品。因此,有必要跟踪同一个客户发出的一系列请求。
把浏览器与服务器之间多次交互作为一个整体,将多次交互所涉及的数据保存下来,即状态管理。
多次交互的数据状态可以在客户端保存,也可以在服务器端保存。状态管理主要分为以下两类:
客户端管理:将状态保存在客户端。基于Cookie技术实现。
服务器管理:将状态保存在服务器端。基于Session技术实现。

2.5 Cookie技术(重点)

2.5.1 基本概念

Cookie本意为”饼干“的含义,在这里表示客户端以“名-值”形式进行保存的一种技术。
浏览器向服务器发送请求时,服务器将数据以Set-Cookie消息头的方式响应给浏览器,然后浏览器会将这些数据以文本文件的方式保存起来。
当浏览器再次访问服务器时,会将这些数据以Cookie消息头的方式发送给服务器。

2.5.2 相关的方法

使用javax.servlet.http.Cookie类的构造方法实现Cookie的创建。

方法声明功能介绍
Cookie(String name, String value)根据参数指定数值构造对象

使用javax.servlet.http.HttpServletResponse接口的成员方法实现Cookie的添加。

@WebServlet(name = "CookieServlet", urlPatterns = "/cookie")
public class CookieServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 1.测试一下浏览器的请求是否到达
        System.out.println("看看有没有执行到这里哦!");
        // 2.创建Cookie对象并添加到响应信息中
        Cookie cookie = new Cookie("name", "zhangfei");
        response.addCookie(cookie);
        System.out.println("创建Cookie成功!");
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }
}

方法声明功能介绍
void addCookie(Cookie cookie)添加参数指定的对象到响应

使用javax.servlet.http.HttpServletRequest接口的成员方法实现Cookie对象的获取。

方法声明功能介绍
Cookie[] getCookies()返回此请求中包含的所有Cookie对象
@WebServlet(name = "CookieServlet2", urlPatterns = "/cookie2")
public class CookieServlet2 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 1.获取客户端发来的Cookie信息并打印出来
        Cookie[] cookies = request.getCookies();
        System.out.println("获取到的Cookie信息有:");
        for (Cookie tc : cookies) {
            System.out.println(tc.getName() + "对应的值为:" + tc.getValue());
        }
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }
}

使用javax.servlet.http.Cookie类的构造方法实现Cookie对象中属性的获取和修改。

方法声明功能介绍
String getName()返回此Cookie对象中的名字
String getValue()返回此Cookie对象的数值
void setValue(String newValue)设置Cookie的数值
@WebServlet(name = "CookieServlet3", urlPatterns = "/cookie3")
public class CookieServlet3 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 1.获取客户端发来的Cookie信息并打印出来
        Cookie[] cookies = request.getCookies();
        for (Cookie tc : cookies) {
            // 2.当获取到的Cookie对象的名字为name时,将对应的数值修改为guanyu并添加到响应信息中
            if ("name".equalsIgnoreCase(tc.getName())) {
                tc.setValue("guanyu");
                response.addCookie(tc);
                break;
            }
        }
        System.out.println("修改Cookie信息成功!");
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }
}

2.5.3 Cookie的生命周期

默认情况下,浏览器会将Cookie信息保存在内存中,只要浏览器关闭,Cookie信息就会消失。
如果希望关闭浏览器后Cookie信息仍有效,可以通过Cookie类的成员方法实现。

方法声明功能介绍
int getMaxAge()返回cookie的最长使用期限(以秒为单位)
void setMaxAge(int expiry)设置cookie的最长保留时间(秒)
@WebServlet(name = "CookieServlet4", urlPatterns = "/cookie4")
public class CookieServlet4 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 1.创建Cookie信息
        Cookie cookie = new Cookie("name", "liubei");
        // 2.获取Cookie信息的默认使用期限
        int maxAge = cookie.getMaxAge();
        System.out.println("该Cookie的默认使用期限是:" + maxAge);
        // 3.修改Cookie信息的使用期限
        // 正数表示在指定的秒数后失效   负数表示浏览器关闭后失效   0表示马上失效
        //cookie.setMaxAge(0);
        cookie.setMaxAge(60*10);
        // 4.添加到响应信息中
        response.addCookie(cookie);
        System.out.println("设置Cookie的生命周期成功!");
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }
}

2.5.4 Cookie的路径问题

浏览器在访问服务器时,会比较Cookie的路径与请求路径是否匹配,只有匹配的Cookie才会发送给服务器。
Cookie的默认路径等于添加这个Cookie信息时的组件路径,例如:/项目名/目录/add.do请求添加
了一个Cookie信息,则该Cookie的路径是 /项目名/目录。

方法声明功能介绍
void setPath(String uri)设置cookie的路径信息

访问的请求地址必须符合Cookie的路径或者其子路径时,浏览器才会发送Cookie信息。

2.5.5 Cookie的特点

Cookie技术不适合存储所有数据,程序员只用于存储少量、非敏感信息,原因如下:

将状态数据保存在浏览器端,不安全。
保存数据量有限制,大约4KB左右。
只能保存字符串信息。
可以通过浏览器设置为禁止使用。

2.6 Session技术(重点)

2.6.1 基本概念

Session本意为"会话"的含义,是用来维护一个客户端和服务器关联的一种技术。
浏览器访问服务器时,服务器会为每一个浏览器都在服务器端的内存中分配一个空间,用于创建一个Session对象,该对象有一个id属性且该值唯一,我们称为SessionId,并且服务器会将这个SessionId以Cookie方式发送给浏览器存储。
浏览器再次访问服务器时会将SessionId发送给服务器,服务器可以依据SessionId查找相对应的Session对象

2.6.2 相关的方法

使用javax.servlet.http.HttpServletRequest接口的成员方法实现Session的获取。

方法声明功能介绍
HttpSession getSession()返回此请求关联的当前Session,若此请求没有则创建一个

使用javax.servlet.http.HttpSession接口的成员方法实现判断和获取。

@WebServlet(name = "SessionServlet", urlPatterns = "/session")
public class SessionServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 1.调用getSession方法获取或者创建Session对象
        HttpSession session = request.getSession();
        // 2.判断该Session对象是否为新建的对象
        System.out.println(session.isNew()? "新创建的Session对象": "已有的Session对象");
        // 3.获取编号并打印
        String id = session.getId();
        System.out.println("获取到的Session编号为:" + id);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }
}

方法声明功能介绍
boolean isNew()判断是否为新创建的Session
String getId()获取Session的编号

使用javax.servlet.http.HttpSession接口的成员方法实现属性的管理。

方法声明功能介绍
Object getAttribute(String name)返回在此会话中用指定名称绑定的对象,如果没有对象在 该名称下绑定,则返回空值
void setAttribute(String name, Object value)使用指定的名称将对象绑定到此会话
void removeAttribute(String name)从此会话中删除与指定名称绑定的对象
@WebServlet(name = "SessionServlet2", urlPatterns = "/session2")
public class SessionServlet2 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        HttpSession session = request.getSession();
        // 1.设置属性名和属性值
        session.setAttribute("name", "machao");
        // 2.获取指定属性名对应的属性值
        System.out.println("获取到的属性值为:" + session.getAttribute("name")); // machao
        // 3.删除指定的属性名
        session.removeAttribute("name");
        // 4.获取指定属性名对应的属性值
        System.out.println("获取到的属性值为:" + session.getAttribute("name")); // null
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }
}

2.6.3 Session的生命周期

为了节省服务器内存空间资源,服务器会将空闲时间过长的Session对象自动清除掉,服务器默认的超时限制一般是30分钟。
使用javax.servlet.http.HttpSession接口的成员方法实现失效实现的获取和设置。

方法声明功能介绍
int getMaxInactiveInterval()获取失效时间
void setMaxInactiveInterval(int interval)设置失效时间

可以配置web.xml文件修改失效时间。

<session-config>
<session-timeout>30</session-timeout>
</session-config>
@WebServlet(name = "SessionServlet3", urlPatterns = "/session3")
public class SessionServlet3 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 1.获取Session对象
        HttpSession session = request.getSession();
        // 2.获取对象的默认失效时间并打印
        int maxInactiveInterval = session.getMaxInactiveInterval();
        System.out.println("获取到的失效时间为:" + maxInactiveInterval); // 1800
        // 3.修改实现时间后重新获取并打印
        session.setMaxInactiveInterval(1200);
        maxInactiveInterval = session.getMaxInactiveInterval();
        System.out.println("获取到的失效时间为:" + maxInactiveInterval); // 1200
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }
}

2.6.4 Session的特点

数据比较安全。
能够保存的数据类型丰富,而Cookie只能保存字符串。
能够保存更多的数据,而Cookie大约保存4KB。
数据保存在服务器端会占用服务器的内存空间,如果存储信息过多、用户量过大,会严重影响服务器的性能。

3. JSP核心技术

3.1 JSP的概述(熟悉)

3.1.1 JSP的概念

JSP是Java Server Pages的简称,跟Servlet一样可以动态生成HTML响应, JSP文件命名为xxx.jsp。
与Servlet不同,JSP文件以HTML标记为主,然后内嵌Java代码段,用于处理动态内容。

3.1.2 JSP的示例

<%@ page import="java.util.Date" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Hello Time</title>
</head>
<body>
现在的时间是:<%= new Date()%>
</body>
</html>

3.1.3 JSP与Servlet的关系

image-20201125142244928

3.2 JSP的语法(熟悉)

3.2.1 JSP语法结构

声明区
程序代码区
表达式
注释
指令和动作
内置对象

3.2.2 声明区

基本语法:
<%! %>
说明:可以定义全局变量、方法、类。

<%!
int i;
public void setName(){… …}
%>

3.2.3 程序代码区

基本语法:
<%程序代码区%>
说明:可以定义局部变量以及放入任何的Java程序代码。

<%
int j;
for (int k=0; k<10; k++) {
… …
}
%>

3.2.4 表达式

基本语法:
<%=… …%>
说明:可以输出一个变量或一个具体内容,但=后面必须是字符串变量或者可以被转换成字符串的表达式。
注意:不需要以;结束,只有一行

<%=“hello world”%>
<%=i+1%>

3.2.5 注释

格式:
<!--… …--> HTML文件的注释,浏览器可以查看到
<%--… …--%> JSP文件的注释,浏览器看不到
<%//… …%> Java语言中的单行注释,浏览器看不到
<%/*… …*/%> Java语言中的多行注释,浏览器看不到
注释的内容不会被执行

3.2.6 指令和动作

指令格式:
<%@指令 属性=“属性值”%>
指令的属性可以设定多个。
JSP常用指令有:page、taglib、include。
(1)page指令
page指令用于导包和设置一些页面属性,常用属性如下:

import 导入相应的包,惟一允许在同一文档中多次出现的属性
contentType 设置Content-Type响应报头,标明即将发送到浏览器的文档类型
pageEncoding 设置页面的编码
language 指定页面使用的语言
session 控制页面是否参与HTTP会话
errorPage 处理当前页面中抛出但未被捕获的任何异常
isErrorPage 当前页是否可以作为其他页面的错误处理页面

(2)taglib指令
taglib指令用来扩展JSP程序的标签元素,引入其他功能的标签库文件。

<!-- prefix属性用于指定库前缀 -->
<!-- uri属性用于指定库的标识 -->
<%@taglib uri=“tagLibary” prefix=“prefix”%>

(3)include指令
include指令用于引入另一个JSP程序或HTML文件等,格式如下:

<%@include file=“被包含的文件地址%>

JSP引擎会在JSP文件的转换时期先把file属性设定的文件包含进来,然后开始执行转换及编译的工作。
(4)jsp:include/jsp:param
jsp:include动作用于引入另一个JSP程序或HTML文件等。
执行到include时,被include的文件才会被编译。
如果include的是jsp文件,那它不会被转换成Servlet文件。

<jsp:include page=“URLSpec” flush=“true”/>
<jsp:include page=“URLSpec” flush=“true”>
<jsp:param name=“key” value=“value”/>
</jsp:include>

(5)include指令和include动作的区别
include指令是在JSP程序的转换时期就将file属性所指定的程序内容嵌入再编译执行(静态包含)。
include动作在转换时期是不会被编译的,只有在客户端请求时期被执行到才会被动态的编译载入(动态包含,推荐)。
(6)jsp:forward/jsp:param
forward动作用于在JSP中实现转发,将请求转发到另一个指定的JSP程序或者Servlet中处理。

<jsp:forward page=“urlSpec” flush=“true”/>
<jsp:forward page=“urlSpec”>
<!-- 用于指定参数和其对应的值 -->
<jsp:param name=“key” value=“value”/>
</jsp:forward>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>JSP页面的转发实现</title>
</head>
<body>
<jsp:forward page="target.jsp">
    <jsp:param name="name" value="zhangfei"/>
</jsp:forward>
</body>
</html>



<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>转发的目标文件</title>
</head>
<body>
<h1>服务器转发后执行这里的代码哦!</h1>
<%= "获取到的数值为:" + request.getParameter("name")%><br/>
</body>
</html>

3.3 JSP内置对象(重点)

3.3.1 基本概念

在JSP程序中有9个内置对象由容器为用户进行实例化,程序员可以不用定义就直接使用这些变量。
在JSP转换成Servlet后,会自动追加这些变量的定义,使用内置对象可以简化JSP的开发。

3.3.2 对象名称

对象变量对象类型作用
outJSPWriter输出流
requestHttpServletRequest请求信息
responseHttpServletResponse响应信息
sessionHttpSession会话
applicationServletContext全局的上下文对象
pageContextPageContextJSP页面上下文
pageObjectJSP页面本身
configServletConfigServlet配置对象
exceptionThrowable捕获网页异常

3.3.3 out内置对象

out内置对象是一个缓冲的输出流,用来给客户端输出信息。

常用方法如下:

方法声明功能介绍
void println(String x)向客户端输出各种类型数据
void newLine()输出一个换行符
void close()关闭输出流
int getBufferSize()返回缓冲区的大小
int getRemaining()返回缓冲区中未使用的字节数
void flush()输出缓冲区里的数据
void clearBuffer()清除缓冲区里的数据,同时把数据输出到客户端
void clear()清除缓冲区里的数据,但不把数据输出到客户端
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>out内置对象的使用</title>
</head>
<body>
<%
    out.println("<h1>");
    out.println("Hello World!");
    out.println("</h1>");
    //out.close();

    int bufferSize = out.getBufferSize();
    System.out.println("缓冲区的总大小是:" + bufferSize);
    int remaining = out.getRemaining();
    System.out.println("缓冲区的剩余字节数为:" + remaining);
    System.out.println("已经使用的字节数为:" + (bufferSize - remaining));

    out.clear(); // 清除缓冲区  数据不会输出
    remaining = out.getRemaining();
    System.out.println("缓冲区的剩余字节数为:" + remaining);
%>
</body>
</html>

3.3.4 request内置对象

request对象封装的是调用JSP页面的请求信息,它是HttpServletRequest接口的一个实例。
该对象的属性值只在一个请求中保存。
常用方法如下:

方法声明功能介绍
String getMethod()返回客户端向服务器端传送数据的方式
String getParameter(String name)返回客户端向服务器端传送的参数值
String[] getParameterValues( String name)获得指定参数的所有值
String getRequestURI()获得请求地址
String getRemoteAddr()返回发送请求的客户端或最后一个代理的IP地址
int getRemotePort()返回发送请求的客户端或最后一个代理的端口号
String getServerName()获取服务器的名字
int getServerPort()获取服务器端的端口
void setAttribute(String name,Object o)在此请求中存储属性。属性在请求之间重置
Object getAttribute(String name)将指定属性的值作为对象返回,若不存在则返回空 值
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>request内置对象的使用</title>
</head>
<body>
<%
    String serverName = request.getServerName();
    System.out.println("获取到的服务器名称为:" + serverName);
    int serverPort = request.getServerPort();
    System.out.println("获取到的服务器端口号为:" + serverPort);
    // 通过内置对象设置属性信息,也就是存储数据
    request.setAttribute("name", "guanyu");
%>
<%-- 实现转发效果,也就是服务器跳转 --%>
<jsp:forward page="requestTarget.jsp"></jsp:forward>
</body>
</html>


<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>获取request对象中的属性值</title>
</head>
<body>
<%= "获取到的属性值为:" + request.getAttribute("name")%>  <%--  guanyu --%>
</body>
</html>

3.3.5 response内置对象

response对象用于给客户端相应输出处理结果,它是HttpServletResponse接口的一个实例。
经常用于设置HTTP标题,添加cookie、设置响应内容的类型和状态、发送HTTP重定向和编码URL。
常用方法如下:

方法声明功能介绍
void addCookie(Cookie cookie)添加一个Cookie对象,用于在客户端保存特定的信 息
void addHeader(String name, String value)添加HTTP头信息,该Header信息将发送到客户端
boolean containsHeader(String name)判断指定名字的HTTP文件头是否存在
void sendRedirect(String location)重定向JSP文件
void setContentType(String type)设置类型与编码方式
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>reponse内置对象的使用</title>
</head>
<body>
<%
    // 表示每隔1秒刷新一次
    response.addHeader("refresh", "1");
    // 获取当前系统时间
    Date d1 = new Date();
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    String format = sdf.format(d1);
%>
<%= "当前时间为:" + format %>
</body>
</html>

3.3.6 session内置对象

session对象表示浏览器和服务器之间的一次会话,一次会话可以包含多次请求,在多次请求之间可以借助session对象存储信息,它是HttpSession类型的一个实例。
该对象的属性值在一次会话范围中保存,保存在服务器端,只要不关闭浏览器,默认半个小时内都可以访问。
常用方法如下:

方法声明功能介绍
void setAttribute(String name, Object value)使用指定的名称将对象绑定到此会话
Object getAttribute(String name)返回在此会话中用指定名称绑定的对象,如果没有对象在该 名称下绑定则返回空值
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>session内置对象的使用</title>
</head>
<body>
<%
    session.setAttribute("name", "liubei");
    System.out.println("session内置对象中的数据设置成功!");
%>
</body>
</html>


<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>获取session内置对象中的数据</title>
</head>
<body>
<%= "获取到的属性值为:" + session.getAttribute("name")%>
</body>
</html>

3.3.7 application内置对象

application对象是一个web程序的全局变量,它是ServletContext类型的一个实例。在整个服务器上保存数据,所有用户共享。
常用方法如下:

方法声明功能介绍
void setAttribute(String name, Object object)将对象绑定到此servlet上下文中的给定属性名
Object getAttribute(String name)返回给定名称的servlet容器属性,若没有该名称的属 性返回null
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>application内置对象的使用</title>
</head>
<body>
<%
    application.setAttribute("name", "zhaoyun");
    System.out.println("application内置对象中的数据设置成功!");
%>
</body>
</html>



<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>application内置对象的获取</title>
</head>
<body>
<%= "获取到的application内置对象的属性为:" + application.getAttribute("name")%> <%-- zhaoyun --%>
</body>
</html>

3.3.8 pageContext内置对象

pageContext对象是PageContext类型的对象,可以使用这个对象来管理其他的隐含对象。
只在一个页面中保存数据。

在JSP页面中,保存数据的范围由小到大依次是 pageContext,request,session,application。

方法声明功能介绍
void setAttribute(String name, Object value, int scope)使用适当的作用域设置指定的名称和值
Object getAttribute(String name, int scope)返回指定作用域中名称关联的对象,若找不到 则返回null
ServletRequest getRequest()获取请求对象
ServletResponse getResponse()获取响应对象
HttpSession getSession()获取会话对象
ServletConfig getServletConfig()获取配置对象
JspWriter getOut()获取输出对象
Object getPage()获取页面对象
Exception getException()获取异常对象
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>pageContext内置对象的使用</title>
</head>
<body>
<%
    pageContext.setAttribute("name", "huangzhong");
    System.out.println("pageContext内置对象中的数据设置成功!");
%>
<%= "获取到的pageContext内置对象中的属性值为:" + pageContext.getAttribute("name")%>
</body>
</html>


<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>pageContext内置对象属性的获取</title>
</head>
<body>
<%= "获取到的pageContext内置对象中的属性值为:" + pageContext.getAttribute("name")%> <%-- null --%>
</body>
</html>

3.3.9 exception内置对象

exception 对象是Throwable的实例,表示的是JSP的异常信息。
如果要使用它,必须将对应页面page指令的isErrorPage属性设置成true。
单个页面的处理方式

<%@page errorPage="error.jsp" %>

在web.xml中配置统一的异常处理页面。

<error-page>
<exception-type>java.lang.Throwable</exception-type>
<location>/error.jsp</location>
</error-page>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page isErrorPage="true" %>
<html>
<head>
    <title>异常处理的页面</title>
</head>
<body>
<%
    if (exception != null) {
        out.println("异常的错误信息为:" + exception.getMessage());
    }
%>
</body>
</html>



<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%--<%@ page errorPage="error.jsp" %>--%>
<html>
<head>
    <title>exception内置对象的使用</title>
</head>
<body>
<%
    int ia = 10;
    int ib = 0;
    System.out.println(ia / ib); // 算术异常
%>
</body>
</html>

3.4 JavaBean组件(熟悉)

(1)基本概念
JavaBean 是使用 Java 语言开发的一个可重用的组件,在 JSP 开发中可以使用 JavaBean 减少重复代码,使整个 JSP 代码的开发更加简洁。
JavaBean本质上就是Java类,通常要求如下:
属性:全部私有化,通过get和set方法进行访问。
方法:必须是public关键字修饰。
构造器 :必须有无参构造方法。
(2)使用方式
使用jsp:useBean的方式创建javaBean实例

<jsp:useBean id=“对象名” scope=“保存范围 class=“包名.类名” />
保存范围有:page|request|sessin|application,默认为page范围。
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>JavaBean组件的使用</title>
</head>
<body>

<%-- 表示创建Student类型的对象由student引用变量负责记录  有效范围是当前页面 --%>
<jsp:useBean id="student" scope="page" class="com.xxx.demo02.Student"/>
<%-- 表示将student对象中名字为id的属性值设置为1002 --%>
<jsp:setProperty name="student" property="id" value="1002"/>
<jsp:setProperty name="student" property="name" value="guanyu"/>

<%
    // 创建Student类型的对象并设置成员变量的数值
    //Student student = new Student();
    //student.setId(1001);
    //student.setName("zhangfei");
%>

<%--<%= "获取到的学号是:" + student.getId() %>   &lt;%&ndash; 1001 1002 &ndash;%&gt;
<%= "获取到的姓名是:" + student.getName() %> &lt;%&ndash; zhangfei guanyu &ndash;%&gt;--%>
学号是:<jsp:getProperty name="student" property="id"/><br/>
姓名是:<jsp:getProperty name="student" property="name"/><br/>
</body>
</html>

使用jsp:setProperty的方式设置javaBean的属性值

<jsp:setProperty name="对象名" property="属性名" value="属性值" param="参数名"/>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>实现前端页面传入过来参数的接收和设置</title>
</head>
<body>
<jsp:useBean id="student" scope="session" class="com.xxx.demo02.Student"/>
<jsp:setProperty name="student" property="id" param="id1"/>
<jsp:setProperty name="student" property="name" param="name1"/>
</body>
</html>

使用jsp:getProperty的方式获取javaBean的属性值

<jsp:getProperty name="对象名" property="属性名"/>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>实现JavaBean组件中对象属性值的打印</title>
</head>
<body>
<jsp:useBean id="student" scope="session" class="com.xxx.demo02.Student"/>
<%-- 获取名字为student对象中属性为id的数值并打印 --%>
经过参数赋值后获取到的学号是:<jsp:getProperty name="student" property="id"/><br/>
经过参数赋值后获取到的姓名是:<jsp:getProperty name="student" property="name"/><br/>
</body>
</html>

(3)保存范围
JavaBean的保存范围有page、request、session以及application,默认是page范围。
(4)删除方式

<%
内置对象.removeAttribute(“JavaBean的名字”);
%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>实现JavaBean组件数据的删除</title>
</head>
<body>
<%
    // 表示从session对象中删除名字为student的属性
    session.removeAttribute("student");
%>
<%= "删除数据成功!" %>
</body>
</html>

3.5 MVC设计模式(重点)

3.5.1 基本概念

MVC是模型(Model)和视图(View)以及控制器(Controller)的简写,是一种将数据、界面显示和业务
逻辑进行分离的组织方式,这样在改进界面及用户交互时,不需要重新编写业务逻辑,从而提高了
代码的可维护性。
M:主要用于封装业务数据的JavaBean(Bean) 和 业务逻辑的JavaBean(Service)及访问数据库的DAO对象。
V:主要负责数据收集 和 数据展现,通常由JSP文件完成。
C:主要负责流程控制 和 页面跳转,通常由Servlet完成。

3.5.2 基本模型

image-20201125143617584

用户登录案例

//登录界面
<%@ page contentType="text/html;charset=utf-8" language="java" %>
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>实现简单的登录功能</title>
</head>
<body>
<form action="login" method="post">
  用户名:<input type="text" name="userName"/><br/>
  密&nbsp;&nbsp;&nbsp;&nbsp;码:<input type="text" name="password"/><br/>
  <span style="color: red"><%= request.getAttribute("error")==null?"":request.getAttribute("error")%></span><br/>
  <input type="submit" value="登录"/>
</form>
</body>
</html>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>主页面</title>
</head>
<body>
<h1>登录成功,欢迎<%= ((User)session.getAttribute("user")).getUserName() %>使用!</h1>
</body>
</html>

//bean
public class User {
    private int id;
    private String userName;
    private String password;

    public User() {
    }

    public User(String userName, String password) {
        this.userName = userName;
        this.password = password;
    }

    public int getId() {
        return id;
    }

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

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public String toString() {
        return "User{" +
                "userName='" + userName + '\'' +
                ", password='" + password + '\'' +
                '}';
    }
}
//dao

//UserDao
public interface UserDao {
    // 自定义抽象方法描述登录功能的实现
    public abstract User userLogin(User user);
}

//UserDaoImp
public class UserDaoImp implements UserDao {
    @Override
    public User userLogin(User user) {
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        try {
            // 1.获取数据库连接
            connection = DbUtil.getConnection();
            // 2.准备sql语句
            String sql = "select * from t_user where userName = ? and password = ?";
            // 3.执行sql语句后获取结果并返回
            preparedStatement = connection.prepareStatement(sql);
            preparedStatement.setString(1, user.getUserName());
            preparedStatement.setString(2, user.getPassword());
            resultSet = preparedStatement.executeQuery();
            if (resultSet.next()) {
                User tu = new User(resultSet.getString("userName"), resultSet.getString("password"));
                return tu; // 表示查找成功
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            // 4.释放相关的资源
            try {
                DbUtil.closeResource(connection, preparedStatement);
                if (null != resultSet) {
                    resultSet.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        return  null; // 表示查找失败
    }
}

//factory
public class UserDaoFactory {

    /**
     * 通过静态工程方法模式来实现UserDao实现类对象的创建并返回
     * @return
     */
    public static UserDao getUserDao() {
        return new UserDaoImp();
    }
}

//service
public class UserService {
    private UserDao userDao;

    public UserService() {
        this.userDao = UserDaoFactory.getUserDao();
    }
    /**
     * 自定义成员方法实现根据参数指定的User对象来调用DAO层实现登录功能
     * @param user
     * @return
     */
    public User userLoginService(User user) {
        return userDao.userLogin(user);
    }
}

//servlet
@WebServlet(name = "LoginServlet", urlPatterns = "/login")
public class LoginServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 1.获取请求中的用户名和密码信息并打印出来
        String userName = request.getParameter("userName");
        System.out.println("获取到的用户名为:" + userName);
        String password = request.getParameter("password");
        System.out.println("获取到的密码为:" + password);
        // 2.创建UserService类型的对象去实现数据的校验功能
        UserService userService = new UserService();
        User user = userService.userLoginService(new User(userName, password));
        if (null == user) {
            System.out.println("登录失败,用户名或密码错误!");
            request.setAttribute("error", "登录失败,用户名或密码错误!");
            // 实现服务器跳转  共享request和response对象
            RequestDispatcher requestDispatcher = request.getRequestDispatcher("login.jsp");
            requestDispatcher.forward(request, response);
        } else {
            System.out.println("登录成功,欢迎使用!");
            // 将登录成功的用户信息放入session对象中实现多个请求共享
            request.getSession().setAttribute("user", user);
            // 实现客户端跳转
            response.sendRedirect("main.jsp");
        }
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }
}

//DBUtil
public class DbUtil {
    private static String jdbcName;   // 用于描述驱动信息
    private static String dbUrl;      // 用于描述URL信息
    private static String dbUserName; // 用户描述用户名信息
    private static String dbPassword; // 用户描述密码信息

    // 进行静态成员的初始化操作
    static {
        jdbcName = "com.mysql.jdbc.Driver";
        dbUrl = "jdbc:mysql://localhost:3306/db_web";
        dbUserName = "root";
        dbPassword = "123456";
        try {
            Class.forName(jdbcName);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取连接
     * @return
     * @throws SQLException
     */
    public static Connection getConnection() throws SQLException {
        Connection con = DriverManager.getConnection(dbUrl, dbUserName, dbPassword);
        return con;
    }

    /**
     * 关闭连接
     * @param con
     * @throws SQLException
     */
    public static void closeResource(Connection con, PreparedStatement psts) throws SQLException {
        if (null != con) {
            con.close();
        }
        if (null != psts) {
            psts.close();
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值