零基础学JavaWeb开发(十)之 servlet

导读:本篇文章讲解 零基础学JavaWeb开发(十)之 servlet,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

十三、servlet

1、什么是servlet

Servlet定义:Servlet是基于Java技术的Web组件,由容器管理并产生动态的内容。Servlet与客户端通过Servlet容器实现的请求/响应模型进行交互。

springmvc—-底层基于Servlet

演示代码:

package com.mayikt.servlet;

import jakarta.servlet.*;
import jakarta.servlet.annotation.WebServlet;

import java.io.IOException;
import java.io.PrintWriter;


@WebServlet("/mayikt")
public class IndexServlet 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 {
        String userName = servletRequest.getParameter("userName");
        servletResponse.setContentType("text/html;charset=utf-8");
        PrintWriter writer = servletResponse.getWriter();
        if ("mayikt".equals(userName)) {
            writer.println("可以访问");
        } else {
            writer.println("无法访问");
        }
        writer.close();
    }
    
    @Override
    public String getServletInfo() {
        return null;
    }
    
    @Override
    public void destroy() {
        
    }
}

2、servlet 环境搭建

1.在我们的项目中创建libs目录存放第三方的jar包

2.项目中导入servlet-api.jar libs目录中

   就在我们tomcat安装的目录 中 lib 目录中

   servlet-api.jar 在 文档中可以直接下载

3.创建servlet包 专门存放就是我们的servlet

4.创建IndexServlet 实现Servlet 重写方法

5.IndexServlet 类上加上@WebServlet(”/mayikt”)注解定义 URL访问的路径

6.重写Servlet 类中service 在service中编写 动态资源

package com.mayikt.servlet;

import jakarta.servlet.*;
import jakarta.servlet.annotation.WebServlet;

import java.io.IOException;
import java.io.PrintWriter;


@WebServlet("/mayikt")
public class IndexServlet implements Servlet {
    
    /**
    * @param servletConfig
    * @throws ServletException
    */
    @Override
    public void init(ServletConfig servletConfig) throws ServletException {
        
    }
    
    @Override
    public ServletConfig getServletConfig() {
        return null;
    }
    
    /**
    * tomcat启动完成
    * 127.0.0.1:8080/项目名称/mayikt 执行 service 通过service方法获取servletRequest、servletResponse
    *
    * @param servletRequest
    * @param servletResponse
    * @throws ServletException
    * @throws IOException
    */
    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        System.out.println("mayikt644");
        // 需要通过servletRequest对象获取到客户端传递参数到服务器端
        String userName = servletRequest.getParameter("userName");
        PrintWriter writer = servletResponse.getWriter();
        if ("mayikt".equals(userName)) {
            // 返回数据 ok
            writer.println("ok");
        } else {
            // fail
            writer.println("fail");
        }
        writer.close();// 关闭资源
        
    }
    
    @Override
    public String getServletInfo() {
        return null;
    }
    
    @Override
    public void destroy() {
        
    }
}

3、servlet debug调试

养成习惯 学会通过 debug模式 运行项目—非常重要

f8—下一步

f9—跳到下一个断点

零基础学JavaWeb开发(十)之 servlet

4、servlet 执行流程

思考点:

1.servlet是谁创建的?我们的service是谁在调用?

servlet tomcatweb服务器创建

service tomcatweb服务器创建

2.tomcat服务器如何执行到servlet中的service方法?

我们自己创建的servlet 必须实现servlet接口重写service方法。

报错:

Caused by: java.lang.IllegalArgumentException: 名为 [com.mayikt.servlet.MayiktServlet]和 [com.mayikt.servlet.MeiteServlet] 的servlet不能映射为一个url模式(url-pattern) [/mayiktmeite]

at org.apache.tomcat.util.descriptor.web.WebXml.addServletMappingDecoded(WebXml.java:346)

at org.apache.tomcat.util.descriptor.web.WebXml.addServletMapping(WebXml.ja

原因:

servleturl 映射路径不要重复哦!

1.servlet是谁创建的?我们的service是谁在调用?

servlet是由我们的 web服务器(tomcat)创建、该方法是由我们的 web服务器(tomcat)调用

断点分析

零基础学JavaWeb开发(十)之 servlet

2.tomcat服务器如何执行到servlet中的service方法?

这是因为我们创建的servlet实现httpservlet接口 重写了service方法

5、servlet 生命周期(重点)

1.创建servlet 被 服务器(tomcat)加载servlet

选择创建servlet ?

如果是第一次访问servlet 才会创建servlet —优点

第一次访问到servlet (单例模式) 线程安全问题

先创建servlet

在执行service方法

该servlet 创建好了以后 在jvm内存中只会存在一份。

如果是第二次访问servlet

在执行service方法

提前创建servlet 或者当你第一次访问servlet 创建servlet 对象

提前创建servlet —-优点可以 第一次访问的时候就不需要创建

servlet 对象可以提高效率、但是 项目启动时提前创建servlet

这样就会导致tomcat启动变得比较慢了。 浪费内存—

2.执行servlet类中init—初始化方法

当我们的servlet类被创建时,执行servlet类初始化方法init 代码初始化

该方法只会执行一次。

3.servlet类—service—–执行每次请求

每次客户端发送请求达到服务器端 都会执行到 servlet类service方法

4.servlet类—destroy—当我们tomcat容器停止时卸载servlet

存放销毁相关代码

1. 创建Servlet实例

web容器负责加载Servlet,当web容器启动时或者是在第一次使用这个Servlet时,容器会负责创建Servlet实例,但是用户必须通过部署描述符(web.xml)指定Servlet的位置,或者在类上加上@WebServlet,成功加载后,web容器会通过反射的方式对Servlet进行实例化。

@WebServlet(urlPatterns = “/mayiktmeite”,loadOnStartup = 1)

负数—第一次被访问时创建Servlet对象 @WebServlet(urlPatterns = “/mayiktmeite”,loadOnStartup = -1)

0或者正数:服务器启动时创建Servlet对象 数字越小优先级越高

MeiteServlet loadOnStartup = 1

YushengjunServlet loadOnStartup = 2

底层会根据loadOnStartup (从0开始)值排序 越小越优先加载创建

2. WEB容器调用Servlet的init()方法,对Servlet进行初始化

在Servlet实例化之后,Servlet容器会调用init()方法,来初始化该对象,主要是为了让Servlet对象在处理客户请求前可以完成一些初始化的工作,例如,建立数据库的连接,获取配置信息等。对于每一个Servlet实例,init()方法只能被调用一次。init()方法有一个类型为ServletConfig的参数,Servlet容器通过这个参数向Servlet传递配置信息。Servlet使用ServletConfig对象从Web应用程序的配置信息中获取以名-值对形式提供的初始化参数。另外,在Servlet中,还可以通过ServletConfig对象获取描述Servlet运行环境的ServletContext对象,使用该对象,Servlet可以和它的Servlet容器进行通信。无论有多少客户机访问Servlet,都不会重复执行init()。

零基础学JavaWeb开发(十)之 servlet

3. Servlet初始化之后,将一直存在于容器中,service()响应客户端请求

1. 如果客户端发送GET请求,容器调用Servlet的doGet方法处理并响应请求

2. 如果客户端发送POST请求,容器调用Servlet的doPost方法处理并响应请求

3. 或者统一用service()方法处理来响应用户请求

service()是Servlet的核心,负责响应客户的请求。每当一个客户请求一个HttpServlet对象,该对象的Service()方法就要调用,而且传递给这个方法一个“请求”(ServletRequest)对象和一个“响应”(ServletResponse)对象作为参数。在HttpServlet中已存在Service()方法。默认的服务功能是调用与HTTP请求的方法相应的do功能。要注意的是,在service()方法被容器调用之前,必须确保init()方法正确完成。容器会构造一个表示客户端请求信息的请求对象(类型为ServletRequest)和一个用于对客户端进行响应的响应对象(类型为ServletResponse)作为参数传递给service()方法。在service()方法中,Servlet对象通过ServletRequest对象得到客户端的相关信息和请求信息,在对请求进行处理后,调用ServletResponse对象的方法设置响应信息。

4. WEB容器决定销毁Servlet时,先调用Servlet的destroy()方法,通常在关闭web应用之前销毁Servlet

destroy()仅执行一次,在服务器端停止且卸载Servlet时执行该方法。当容器检测到一个Servlet对象应该从服务中被移除的时候,容器会调用该对象的destroy()方法,以便让Servlet对象可以释放它所使用的资源,保存数据到持久存储设备中,例如,将内存中的数据保存到数据库中,关闭数据库的连接等。当需要释放内存或者容器关闭时,容器就会调用Servlet对象的destroy()方法。在Servlet容器调用destroy()方法前,如果还有其他的线程正在service()方法中执行,容器会等待这些线程执行完毕或等待服务器设定的超时值到达。一旦Servlet对象的destroy()方法被调用,容器不会再把其他的请求发送给该对象。如果需要该Servlet再次为客户端服务,容器将会重新产生一个Servlet对象来处理客户端的请求。在destroy()方法调用之后,容器会释放这个Servlet对象,在随后的时间内,该对象会被Java的垃圾收集器所回收。

6、servlet 线程是否安全?

servlet 对象默认是单例 在jvm内存中只会存在一份

当多个线程如果共享到同一个全局变量可能会存在线程安全性问题

需求:需要统计 你是第一个人访问网站?

package com.mayikt.servlet;


import jakarta.servlet.*;
import jakarta.servlet.annotation.WebServlet;

import java.io.IOException;
import java.io.PrintWriter;



@WebServlet("/count")
public class CountServlet implements Servlet {
    private Integer count = 1;
    
    public CountServlet() {
        System.out.println("CountServlet 对象被创建");
    }
    
    @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 {
        servletResponse.setContentType("text/html;charset=utf-8");
        PrintWriter writer = servletResponse.getWriter();
        writer.println("您是第" + count + "个人访问网站!");
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        writer.close();
        synchronized (this) {
            count++;
        }
        
    }
    
    @Override
    public String getServletInfo() {
        return null;
    }
    
    @Override
    public void destroy() {
        
    }
}

7、servlet 方法介绍

Servlet接口定义了5种方法:

  • init()
  • service()
  • destroy()
  • getServletConfig()
  • getServletInfo()

1.init()

在Servlet实例化后,Servlet容器会调用init()方法来初始化该对象,主要是为了让Servlet对象在处理客户请求前可以完成一些初始化工作,例如:建立数据库的连接,获取配置信息等。对于每一个Servlet实例,init()方法只能被调用一次。init()方法有一个类型为ServletConfig的参数,Servlet容器通过这个参数向Servlet传递配置信息。Servlet使用ServletConfig对象从Web应用程序的配置信息中获取以名-值对形式提供的初始化参数。另外,在Servlet中,还可以通过ServletConfig对象获取描述Servlet运行环境的ServletContext对象,使用该对象,Servlet可以和它的Servlet容器进行通信。

2.service()

容器调用service()方法来处理客户端的请求。要注意的是,在service()方法被容器调用之前,必须确保init()方法正确完成。容器会构造一个表示客户端请求信息的请求对象(类型为ServletRequest)和一个用于对客户端进行响应的响应对象(类型为ServletResponse)作为参数传递给service()。在service()方法中,Servlet对象通过ServletRequest对象得到客户端的相关信息和请求信息,在对请求进行处理后,调用ServletResponse对象的方法设置响应信息。

3.destroy

当容器检测到一个Servlet对象应该从服务中被移除的时候,容器会调用该对象的destroy()方法,以便让Servlet对象可以释放它所使用的资源,保存数据到持久存储设备中,例如将内存中的数据保存到数据库中,关闭数据库的连接等。当需要释放内存或者容器关闭时,容器就会调用Servlet对象的destroy()方法,在Servlet容器调用destroy()方法前,如果还有其他的线程正在service()方法中执行容器会等待这些线程执行完毕或者等待服务器设定的超时值到达。一旦Servlet对象的destroy()方法被调用,容器不回再把请求发送给该对象。如果需要改Servlet再次为客户端服务,容器将会重新产生一个Servlet对象来处理客户端的请求。在destroy()方法调用之后,容器会释放这个Servlet对象,在随后的时间内,该对象会被java的垃圾收集器所回收。

4.getServletInfo()

返回一个String类型的字符串,其中包括了关于Servlet的信息,例如,作者、版本和版权。该方法返回的应该是纯文本字符串,而不是任何类型的标记。

5.getServletConfig()

该方法返回容器调用init()方法时传递给Servlet对象的ServletConfig对象,ServletConfig对象包含了Servlet的初始化参数。

package com.mayikt.servlet;

import jakarta.servlet.*;
import jakarta.servlet.annotation.WebInitParam;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;

import java.io.IOException;
import java.io.PrintWriter;


@WebServlet(urlPatterns = "/servletConfig", initParams = {@WebInitParam(name = "p1", value = "mayikt")})
public class ServletConfigServlet implements Servlet {
    private ServletConfig servletConfig;

    @Override
    public void init(ServletConfig servletConfig) throws ServletException {
        this.servletConfig = servletConfig;
    }

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

    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        String value = getServletConfig().getInitParameter("p1");
        PrintWriter writer = servletResponse.getWriter();
        writer.println(value);
        writer.close();
    }

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

    @Override
    public void destroy() {

    }
}

8、servlet 体系结构

零基础学JavaWeb开发(十)之 servlet

HttpServlet 对的servlet接口包装 提供 get/post等方法

9、request与response对象

request与response对象

request:获取客户端发送数据给服务器端

response:返回对应的数据给客户端(浏览器)

http协议基于 请求(request)与响应的模型(response)

 

package com.mayikt.servlet;

import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import java.io.IOException;
import java.io.PrintWriter;


@WebServlet("/servletDemo05")
public class ServletDemo05 extends HttpServlet {
    /**
    * 获取到HttpServletRequest、HttpServletResponse对象
    *
    * @param req
    * @param resp
    * @throws ServletException
    * @throws IOException
    */
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // req 获取到客户端发送数据给服务器()
        // http://localhost:8081/mayikt_tomcat04_war_exploded/servletDemo05?userName=mayikt&userPwd=123
        String userName = req.getParameter("userName");//userName=mayikt
        String userPwd = req.getParameter("userPwd");//userPwd=123456
        PrintWriter writer = resp.getWriter();
        // 判断用户传递的  用户名称和密码 如果是为zhangsan  644064 则 登录成功
        if ("zhangsan".equals(userName) && "644064".equals(userPwd)) {
            // 服务器端处理完数据之后 返回对应的数据给客户端 告诉给客户端说 响应的是一个 html或者是文本
            resp.setHeader("Content-Type", "text/html;charset=UTF-8");
            writer.write("<html> <meta charset=\"utf-8\"/><body><h1>恭喜您登录成功,用户名称是:" + userName + "</h1></body></html>");
        } else {
            writer.write("<html><meta charset=\"utf-8\"/><body><h1>很遗憾密码错误</h1></body></html>");
        }
        // 关闭资源
        writer.close();
    }
}

request与response继承模型

ServletRequest —— 接口 java提供的请求对象根接口

HttpServletRequest —— 接口(继承ServletRequest) java提供的对http协议封装请求对象接口

org.apache.catalina.connnector.RequestFacade —— 类(Tomcat编写的,实现HttpServletRequest )

零基础学JavaWeb开发(十)之 servlet

request获取请求数据

http://localhost:8080/mayikt-tomcat04/servletDemo06

1. 请求行部分

String getMethod() // 获取请求方式

String getContextPath() // 获取项目访问路径 /mayikt-tomcat04

StringBuffer getRequestURL() // 获取 URL 统一资源定位符 http://localhost:8080/mayikt-tomcat04/servletDemo06

String getRequestURI() // 获取 URI 统一资源标识符 /mayikt-tomcat04/servletDemo06

String getQueryString() // 获取请求参数(Get 方式) username=mayikt&password=123

2.请求头部分

String getHeader(String name) // 根据请求头名称, 获取值

User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36

3.请求体部分 (Post 才有)

通过 流读取 来获取 Post请求的参数 userName=mayikt&password=123

ServletInputStream getInputStream() // 字节输入流

BufferedReader getReader() // 字符输入流 readLine();

request获取请求参数

Request对象里封装好了一个 Map集合,Map集合里放的就是所有的参数

Map<String,String[]> getParameterMap() // 返回这个 Map 集合

String[] getParameterValues(String name) // 根据 键名 获取值

String getParameter(String name) // 根据 键名 获取值

?age=18&age=22  :   key:age;vlaue:18/22

 

Map<String, String[]> map = req.getParameterMap();
for(String key : map.keySet()){
    System.out.print(key + ":");
    
    String[] values = map.get(key);
    for(String value : values){
        System.out.print(value + " ");
    }
    
    System.out.println();
}
package com.mayikt.servlet;

import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import java.io.BufferedReader;
import java.io.IOException;
import java.util.HashMap;


@WebServlet("/httpServletDemo06")
public class HttpServletDemo06 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        this.doPost(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 判断请求是get还是post请求
        String method = req.getMethod();
        String parameters = null;
        switch (method) {
            case "GET":
                parameters = req.getQueryString();
                break;
            case "POST":
                BufferedReader reader = req.getReader();
                parameters = reader.readLine();
                reader.close();
                break;
        }
        HashMap<String, String> parametersMap = new HashMap<>();
        String[] sp1 = parameters.split("&");
        for (int i = 0; i < sp1.length; i++) {
            String[] sp2 = sp1[i].split("=");
            String key = sp2[0];
            String value = sp2[1];
            parametersMap.put(key, value);
        }
        System.out.println(parametersMap);
    }
}
1

request请求转发

零基础学JavaWeb开发(十)之 servlet

请求转发:一种在服务器内部的资源跳转方式

1.通过request对象获取请求转发器对象 :

RequestDispatcher getRequestDispatcher(String path)

2.使用RequestDispatcher对象来进行转发:

forward(ServletRequest request, ServletResponse response)

RequestDispatcher requestDispatcher = request.getRequestDispatcher(“/requestDemo6”);

requestDispatcher.forward(request,response);

浏览器地址栏路径不发生变化;

只能转发到当前服务器内部资源中;

转发是一次请求;

1、request.setAttribute(“name”,value); 数据共享

有效范围是一个请求范围,不发送请求的界面无法获取到value的值,jsp界面获取使用EL表达式${num};

只能在一个request内有效,如果重定向客户端,将取不到值。

request在当次的请求的URL之间有效,比如,你在请求某个servlet,那么你提交的信息,可以使用request.getAttribute()方式获得,而当你再次跳转之后,这些信息将不存在。

 

import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import java.io.IOException;


@WebServlet("/httpServletDemo09")
public class HttpServletDemo09 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req, resp);
    }
    
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setAttribute("name", "mayikt");
        req.getRequestDispatcher("/httpServletDemo10").forward(req, resp);
    }
}


package com.mayikt.servlet;

import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import java.io.IOException;

@WebServlet("/httpServletDemo10")
public class HttpServletDemo10 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String name = (String) req.getAttribute("name");
        System.out.println(name);
        System.out.println("httpServletDemo10");
    }
}

response响应数据

response是Servlet.service方法的一个参数,类型为javax.servlet.http.HttpServletResponse。在客户端发出每个请求时,服务器都会创建一个response对象,并传入给Servlet.service()方法。response对象是用来对客户端进行响应的,这说明在service()方法中使用response对象可以完成对客户端的响应工作。

//设置服务端的编码

resp.setCharacterEncoding(“UTF-8”);

//通过设置响应头设置客户端(浏览器的编码)

resp.setHeader(“Content-type”,”text/html;utf-8″);

//这个方法可以同时设置客户端和服务端,因为它会调用setCharacterEncoding方法

resp.setContentType(“text/html;charset=utf-8”);

resp.setContentType(“text/html;charset=utf-8”);

响应格式分为3个部分

1.响应行:响应数据第一行 http协议版本1.1版本

200表示响应状态码 ok为 成功状态

2.响应头:第二行开始 格式 key value

3.响应体

response是响应对象,向客户端输出响应正文(响应体)可以使用response的响应流,repsonse一共提供了两个响应流对象:

PrintWriter out = response.getWriter():获取字符流;

ServletOutputStream out = response.getOutputStream():获取字节流;

如果响应正文内容为字符,那么使用response.getWriter(),如果响应内容是字节,例如下载时,那么可以使用response.getOutputStream()。

//设置错误的响应码

resp.setError(404,”未找到请求的资源!”);

//设置正确的响应码

resp.setStatus(200);

HttpServletResponse

ServletResponse

ServletResponse—— 接口 java提供的响应对象根接口

HttpServletResponse —— 接口(继承ServletResponse) java提供的对http协议封装响应对象接口

org.apache.catalina.connnector.ResponseFacade —— 类(Tomcat编写的,实现HttpServletResponse )

response重定向

重定向原理

当我们的客户端发送请求达到服务器端,我们的服务器端响应状态码302 ,同时在响应头中

设置重定向地址(resp.setHeader(“Location”,”www.mayikt.com”);) ;

客户端(浏览器)收到结果之后,在浏览器解析Location www.mayikt.com 在直接重定向到

www.mayikt.com

两次请求。

地址栏有发生变化的。

首先客户浏览器发送http请求,当web服务器接受后发送302状态码响应及对应新的location给客 户浏览器,客户浏览器发现是302响应,则自动再发送一个新的http请求,请求url是新的location 地址,服务器根据此请求寻找资源并发送给客户。

void sendRedirect(String location) 使用指定的重定向位置URL,向客户端发送临时重定向响应

resp.setStatus(302);
resp.setHeader(“Location”,”www.mayikt.com”);

1.重定向之后,浏览器地址栏的URL会发生改变

2.重定向过程中会将前面Request对象销毁,然后创建一个新的Request对象

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

重定向与转发区别

1.转发只能将请求转发给同一个web应用(项目工程)中的其他组件(servlet程序);重定向可以重定向到任意的地址,网络地址或是文件地址(跨项目文件夹 www.mayikt.com)

2.重定向访问结束后,浏览器地址栏URL发生变化,变成了重定向后的URL;转发则不变

重定向对浏览器的请求直接做出响应,结果就是告诉浏览器去重新发出另一个新的URL访问请求;请求转发在服务器端内部将请求转发给另一个资源,浏览器不知道服务器程序内部发生了转发过程

3.请求转发调用者与被调用者之间共享相同的请求对象,属于同一个请求和响应过程;重定向则是不同的请求和响应过程

零基础学JavaWeb开发(十)之 servlet

10、jdbc+servlet登录和注册

初始化数据库表结构

CREATE TABLE `mayikt_users` (
  `id` int NOT NULL AUTO_INCREMENT,
  `userName` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
  `userPwd` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8mb3;

jdbc+servlet用户注册

1.添加jar包

commons-lang3-3.4—-常用工具包

mysql-connector-java-8.0.13.jar —-mysql驱动包

servlet-api.jar —-servlet-api.jar

该jar上传 该位置— 点击下载jar包

文档:javaweb开发相关资料下载.note

链接:有道云笔记

2.mayikt jdbc工具类

package com.mayikt.utils;

import java.io.InputStream;
import java.sql.*;
import java.util.Properties;


public class MayiktJdbcUtils {
    /**
    * 1.需要将我们的构造方法私有化 ---工具类 不需要 new出来 是通过类名称.方法名称访问
    */
    private MayiktJdbcUtils() {
        
    }
    
    /**
    * 2.定义工具类 需要 声明 变量
    */
    private static String driverClass;
    private static String url;
    private static String user;
    private static String password;
    
    /**
    *3.使用静态代码快 来给我们声明好 jdbc变量赋值(读取config.properties)
    */
    static {
        try {
            // 1.读取config.properties  IO 路径 相对路径
            InputStream resourceAsStream = MayiktJdbcUtils.class.getClassLoader().
                getResourceAsStream("config.properties");
            // 2.赋值给我们声明好的变量
            Properties properties = new Properties();
            properties.load(resourceAsStream);
            driverClass = properties.getProperty("driverClass");
            url = properties.getProperty("url");
            user = properties.getProperty("user");
            password = properties.getProperty("password");
            // 3.注册驱动类
            Class.forName(driverClass);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    /**
    * 4.封装连接方法
    */
    public static Connection getConnection() throws SQLException {
        Connection connection = DriverManager.getConnection(url, user, password);
        return connection;
    }
    
    /**
    * 5.封装释放连接方法 (重载)
    */
    public static void closeConnection(ResultSet resultSet, Statement statement, Connection connection) {
        // 1.查询 释放连接 resultSet  statement connection
        try {
            if (resultSet != null)
                resultSet.close();
            if (statement != null)
                statement.close();
            if (connection != null)
                connection.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        
    }
    
    /**
    * 增删改---释放jdbc资源
    *
    * @param statement
    * @param connection
    */
    public static void closeConnection(Statement statement, Connection connection) {
        // 1.查询 释放连接 resultSet  statement connection
        closeConnection(null, statement, connection);
    }
    
    /**
    * 开启事务
    *
    * @param connection
    * @throws SQLException
    */
    public static void beginTransaction(Connection connection) throws SQLException {
        connection.setAutoCommit(false);
    }
    
    /**
    * 提交事务
    *
    * @param connection
    * @throws SQLException
    */
    public static void commitTransaction(Connection connection) throws SQLException {
        connection.commit();
    }
    
    /**
    * 回滚事务
    *
    * @param connection
    */
    public static void rollBackTransaction(Connection connection) {
        if (connection != null) {
            try {
                connection.rollback();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
    
    /**
    * 关闭事务
    *
    * @param connection
    */
    public static void endTransaction(Connection connection) {
        if (connection != null) {
            try {
                connection.setAutoCommit(true);
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
    
}

拷贝 config.properties

driverClass=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/mayikt?serverTimezone=UTC
user=root
password=root

3.编写注册 servlet

package com.mayikt.servlet;

import com.mayikt.utils.MayiktJdbcUtils;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;

import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.PreparedStatement;


@WebServlet("/register")
public class RegisterServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        PrintWriter writer = resp.getWriter();
        resp.setContentType("text/html;charset=utf-8");
        //1.获取参数
        String userName = req.getParameter("userName");
        if (StringUtils.isEmpty(userName)) {
            writer.print("userName不能为空!");
            return;
        }
        String userPwd = req.getParameter("userPwd");
        if (StringUtils.isEmpty(userPwd)) {
            writer.print("userPwd不能为空!");
            return;
        }
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        try {

            connection = MayiktJdbcUtils.getConnection();
            //2.验证用户名称和密码
            MayiktJdbcUtils.beginTransaction(connection);// 开启事务
            String insertSql = "INSERT INTO `mayikt`.`mayikt_users` (`id`, `userName`, `userPwd`) VALUES (null, ?,?); ";
            preparedStatement = connection.prepareStatement(insertSql);
            preparedStatement.setString(1, userName);
            preparedStatement.setString(2, userPwd);
            int insertResult = preparedStatement.executeUpdate();
            MayiktJdbcUtils.commitTransaction(connection);
            String result = insertResult > 0 ? "注册成功" : "注册失败";
            writer.println(result);
        } catch (Exception e) {
            e.printStackTrace();
            writer.println("error");
            // 回滚事务
            if (connection != null)
                MayiktJdbcUtils.rollBackTransaction(connection);
        } finally {
            if (writer != null) {
                writer.close();
            }
            MayiktJdbcUtils.closeConnection(null, preparedStatement, connection);
        }
    }
}

4.编写注册html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>用户注册</title>
</head>
<body>

<h1>用户注册</h1>
<form action="/mayikt_web_login_war_exploded/register" method="post">
    <!--name=mayikt&age=12 -->
    <span>用户名称:</span> <input type="text" name="userName"> <br>
    <span>密&nbsp;&nbsp;&nbsp;&nbsp;码:</span> <input type="text" name="userPwd" value=""><br>
    <input type="submit">
</form>
</body>
</html>

jdbc+servlet用户登录

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>用户登录</title>
</head>
<body>

<h1>用户登录</h1>
<form action="/mayikt_web_login_war_exploded/login" method="post">
    <!--name=mayikt&age=12 -->
    <span>名称:</span> <input type="text" name="userName"> <br>
    <span>密&nbsp;&nbsp;&nbsp;码:</span> <input type="text" name="userPwd" value=""><br>
    <input type="submit">
</form>
</body>
</html>

package com.mayikt.servlet;

import com.mayikt.utils.MayiktJdbcUtils;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;


@WebServlet("/login")
public class LoginServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1.获取参数
        String userName = req.getParameter("userName");
        String userPwd = req.getParameter("userPwd");
        PrintWriter writer = resp.getWriter();
        resp.setContentType("text/html;charset=utf-8");
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        try {
            //2.验证用户名称和密码
            connection = MayiktJdbcUtils.getConnection();
            String loginSql = "SELECT * FROM mayikt_users where userName=? and userPwd=? ";
            preparedStatement = connection.prepareStatement(loginSql);
            preparedStatement.setString(1, userName);
            preparedStatement.setString(2, userPwd);
            resultSet = preparedStatement.executeQuery();
            if (resultSet.next()) {
                String dbUserName = resultSet.getString(1);
                writer.println("恭喜" + userName + "登录成功");
            } else {
                writer.println("登录失败");
            }
        } catch (Exception e) {
            e.printStackTrace();
            writer.println("error");
            // 回滚事务
            if (connection != null)
                MayiktJdbcUtils.rollBackTransaction(connection);
        } finally {
            if (writer != null) {
                writer.close();
            }
            MayiktJdbcUtils.closeConnection(null, preparedStatement, connection);
        }
    }
}

常见问题

我们在使用tomcat 运行 web项目时 启动项目报错

java.lang.ClassNotFoundException: com.mysql.cj.jdbc.Driver

原因1:没有引入 mysql驱动jar包

原因2:tomcat 在运行过程中 会在lib目录中查找jar包 发现没有 就会报该错误。

但是我们在编译阶段是在项目中lib 查找jar包,编译阶段没有报错。

将该 jar包拷贝到 tomcat -lib 目录中即可

零基础学JavaWeb开发(十)之 servlet

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/81327.html

(0)
小半的头像小半

相关推荐

极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!