[JavaWeb] 尚硅谷JavaWeb课程笔记

1 Tomcat服务器

Tomcat目录结构

  • bin:该目录下存放的是二进制可执行文件,如果是安装版,那么这个目录下会有两个exe文件:tomcat10.exe、tomcat10w.exe,前者是在控制台下启动Tomcat,后者是弹出GUI窗口启动Tomcat;如果是解压版,那么会有startup.bat和shutdown.bat文件,startup.bat用来启动Tomcat,但需要先配置JAVA_HOME环境变量才能启动,shutdawn.bat用来停止Tomcat;
  • conf:这是一个非常非常重要的目录,这个目录下有四个最为重要的文件:

    • server.xml:配置整个服务器信息。例如修改端口号。默认HTTP请求的端口号是:8080

    • tomcat-users.xml:存储tomcat用户的文件,这里保存的是tomcat的用户名及密码,以及用户的角色信息。可以按着该文件中的注释信息添加tomcat用户,然后就可以在Tomcat主页中进入Tomcat Manager页面了;

      <tomcat-users xmlns="http://tomcat.apache.org/xml"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://tomcat.apache.org/xml tomcat-users.xsd"version="1.0">	<role rolename="admin-gui"/><role rolename="admin-script"/><role rolename="manager-gui"/><role rolename="manager-script"/><role rolename="manager-jmx"/><role rolename="manager-status"/><user 	username="admin" password="admin" roles="admin-gui,admin-script,manager-gui,manager-script,manager-jmx,manager-status"/>
      </tomcat-users>
      

      web.xml:部署描述符文件,这个文件中注册了很多MIME类型,即文档类型。这些MIME类型是客户端与服务器之间说明文档类型的,如用户请求一个html网页,那么服务器还会告诉客户端浏览器响应的文档是text/html类型的,这就是一个MIME类型。客户端浏览器通过这个MIME类型就知道如何处理它了。当然是在浏览器中显示这个html文件了。但如果服务器响应的是一个exe文件,那么浏览器就不可能显示它,而是应该弹出下载窗口才对。MIME就是用来说明文档的内容是什么类型的!

    • context.xml:对所有应用的统一配置,通常我们不会去配置它。

  • lib:Tomcat的类库,里面是一大堆jar文件。如果需要添加Tomcat依赖的jar文件,可以把它放到这个目录中,当然也可以把应用依赖的jar文件放到这个目录中,这个目录中的jar所有项目都可以共享之,但这样你的应用放到其他Tomcat下时就不能再共享这个目录下的jar包了,所以建议只把Tomcat需要的jar包放到这个目录下;

  • logs:这个目录中都是日志文件,记录了Tomcat启动和关闭的信息,如果启动Tomcat时有错误,那么异常也会记录在日志文件中。

  • temp:存放Tomcat的临时文件,这个目录下的东西可以在停止Tomcat后删除!

  • webapps:存放web项目的目录,其中每个文件夹都是一个项目;如果这个目录下已经存在了目录,那么都是tomcat自带的项目。其中ROOT是一个特殊的项目,在地址栏中访问:http://127.0.0.1:8080,没有给出项目目录时,对应的就是ROOT项目.http://localhost:8080/examples,进入示例项目。其中examples"就是项目名,即文件夹的名字。

  • work:运行时生成的文件,最终运行的文件都在这里。通过webapps中的项目生成的!可以把这个目录下的内容删除,再次运行时会生再次生成work目录。当客户端用户访问一个JSP文件时,Tomcat会通过JSP生成Java文件,然后再编译Java文件生成class文件,生成的java和class文件都会存放到这个目录下。

  • LICENSE:许可证。

  • NOTICE:说明文件。

WEB项目的标准结构

一个标准的可以用于发布的WEB项目标准结构如下:

在这里插入图片描述

  • app 本应用根目录

    • static 非必要目录,约定俗成的名字,一般在此处放静态资源 ( css js img)

      • WEB-INF 必要目录,必须叫WEB-INF,受保护的资源目录,浏览器通过url不可以直接访问的目录
        • classes 必要目录,src下源代码,配置文件,编译后会在该目录下,web项目中如果没有源码,则该目录不会出现
        • lib 必要目录,项目依赖的jar编译后会出现在该目录下,web项目要是没有依赖任何jar,则该目录不会出现
        • web.xml 必要文件,web项目的基本配置文件. 较新的版本中可以没有该文件,但是学习过程中还是需要该文件
    • index.html 非必要文件,index.html/index.htm/index.jsp为默认的欢迎页

url的组成部分和项目中资源的对应关系:

在这里插入图片描述

2 Servlet

Servlet (server applet) 是运行在服务端(tomcat)的Java小程序,是sun公司提供一套定义动态资源规范; 从代码层面上来讲Servlet就是一个接口

  • 用来接收、处理客户端请求、响应给浏览器的动态资源。在整个Web应用中,Servlet主要负责接收处理请求、协同调度功能以及响应数据。我们可以把Servlet称为Web应用中的控制器
  • 不是所有的JAVA类都能用于处理客户端请求,能处理客户端请求并做出响应的一套技术标准就是Servlet
  • Servlet是运行在服务端的,所以 Servlet必须在WEB项目中开发且在Tomcat这样的服务容器中运行

Servlet开发流程

校验注册时,用户名是否被占用. 通过客户端向一个Servlet发送请求,携带username,如果用户名是’atguigu’,则向客户端响应 NO,如果是其他,响应YES

步骤1 开发一个web类型的module

  • 过程参照之前

步骤2 开发一个UserServlet

public class UserServlet  extends HttpServlet {@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// 获取请求中的参数String username = req.getParameter("username");if("atguigu".equals(username)){//通过响应对象响应信息resp.getWriter().write("NO");}else{resp.getWriter().write("YES");}}
}
  • 自定义一个类,要继承HttpServlet类
  • 重写service方法,该方法主要就是用于处理用户请求的服务方法
  • HttpServletRequest 代表请求对象,是有请求报文经过tomcat转换而来的,通过该对象可以获取请求中的信息
  • HttpServletResponse 代表响应对象,该对象会被tomcat转换为响应的报文,通过该对象可以设置响应中的信息
  • Servlet对象的生命周期(创建,初始化,处理服务,销毁)是由tomcat管理的,无需我们自己new
  • HttpServletRequest HttpServletResponse 两个对象也是有tomcat负责转换,在调用service方法时传入给我们用的

步骤3 在web.xml为UseServlet配置请求的映射路径

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd"version="5.0"><servlet><!--给UserServlet起一个别名--><servlet-name>userServlet</servlet-name><servlet-class>com.atguigu.servlet.UserServlet</servlet-class></servlet><servlet-mapping><!--关联别名和映射路径--><servlet-name>userServlet</servlet-name><!--可以为一个Servlet匹配多个不同的映射路径,但是不同的Servlet不能使用相同的url-pattern--><url-pattern>/userServlet</url-pattern><!-- <url-pattern>/userServlet2</url-pattern>--><!--/        表示通配所有资源,不包括jsp文件/*       表示通配所有资源,包括jsp文件/a/*     匹配所有以a前缀的映射路径*.action 匹配所有以action为后缀的映射路径--><!-- <url-pattern>/*</url-pattern>--></servlet-mapping></web-app>
  • Servlet并不是文件系统中实际存在的文件或者目录,所以为了能够请求到该资源,我们需要为其配置映射路径
  • servlet的请求映射路径配置在web.xml中
  • servlet-name作为servlet的别名,可以自己随意定义,见名知意就好
  • url-pattern标签用于定义Servlet的请求映射路径
  • 一个servlet可以对应多个不同的url-pattern
  • 多个servlet不能使用相同的url-pattern
  • url-pattern中可以使用一些通配写法
    • / 表示通配所有资源,不包括jsp文件
    • /* 表示通配所有资源,包括jsp文件
    • /a/* 匹配所有以a前缀的映射路径
    • *.action 匹配所有以action为后缀的映射路径

Servlet注解方式配置

@WebServlet注解的源码阅读


package jakarta.servlet.annotation;import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;/*** @since Servlet 3.0*/
@Target({ ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface WebServlet {/*** The name of the servlet* 相当于 servlet-name* @return the name of the servlet*/String name() default "";/*** The URL patterns of the servlet* 如果只配置一个url-pattern ,则通过该属性即可,和urlPatterns属性互斥* @return the URL patterns of the servlet*/String[] value() default {};/*** The URL patterns of the servlet* 如果要配置多个url-pattern ,需要通过该属性,和value属性互斥* @return the URL patterns of the servlet*/String[] urlPatterns() default {};/*** The load-on-startup order of the servlet* 配置Servlet是否在项目加载时实例化* @return the load-on-startup order of the servlet*/int loadOnStartup() default -1;/*** The init parameters of the servlet* 配置初始化参数* @return the init parameters of the servlet*/WebInitParam[] initParams() default {};/*** Declares whether the servlet supports asynchronous operation mode.** @return {@code true} if the servlet supports asynchronous operation mode* @see jakarta.servlet.ServletRequest#startAsync* @see jakarta.servlet.ServletRequest#startAsync( jakarta.servlet.ServletRequest,jakarta.servlet.ServletResponse)*/boolean asyncSupported() default false;/*** The small-icon of the servlet** @return the small-icon of the servlet*/String smallIcon() default "";/*** The large-icon of the servlet** @return the large-icon of the servlet*/String largeIcon() default "";/*** The description of the servlet** @return the description of the servlet*/String description() default "";/*** The display name of the servlet** @return the display name of the servlet*/String displayName() default "";}

@WebServlet注解使用

使用@WebServlet注解替换Servlet配置

@WebServlet(name = "userServlet",//value = "/user",urlPatterns = {"/userServlet1","/userServlet2","/userServlet"},initParams = {@WebInitParam(name = "encoding",value = "UTF-8")},loadOnStartup = 6
)
public class UserServlet  extends HttpServlet {@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {String encoding = getServletConfig().getInitParameter("encoding");System.out.println(encoding);// 获取请求中的参数String username = req.getParameter("username");if("atguigu".equals(username)){//通过响应对象响应信息resp.getWriter().write("NO");}else{resp.getWriter().write("YES");}}
}

3 Servlet生命周期

什么是Servlet的生命周期?

  • 应用程序中的对象不仅在空间上有层次结构的关系,在时间上也会因为处于程序运行过程中的不同阶段而表现出不同状态和不同行为——这就是对象的生命周期。
  • 简单的叙述生命周期,就是对象在容器中从开始创建到销毁的过程。

Servlet容器

Servlet对象是Servlet容器创建的,生命周期方法都是由容器(目前我们使用的是Tomcat)调用的。这一点和我们之前所编写的代码有很大不同。在今后的学习中我们会看到,越来越多的对象交给容器或框架来创建,越来越多的方法由容器或框架来调用,开发人员要尽可能多的将精力放在业务逻辑的实现上

Servlet主要的生命周期执行特点

生命周期对应方法执行时机执行次数
构造对象构造器第一次请求或者容器启动1
初始化init()构造完毕后1
处理服务service(HttpServletRequest req,HttpServletResponse resp)每次请求多次
销毁destory()容器关闭1

生命周期总结

  1. 通过生命周期测试我们发现Servlet对象在容器中是单例的
  2. 容器是可以处理并发的用户请求的,每个请求在容器中都会开启一个线程
  3. 多个线程可能会使用相同的Servlet对象,所以在Servlet中,我们不要轻易定义一些容易经常发生修改的成员变量
  4. load-on-startup中定义的正整数表示实例化顺序,如果数字重复了,容器会自行解决实例化顺序问题,但是应该避免重复
  5. Tomcat容器中,已经定义了一些随系统启动实例化的servlet,我们自定义的servlet的load-on-startup尽量不要占用数字1-5

4 Servlet继承结构

Servlet 接口

public interface Servlet {void init(ServletConfig var1) throws ServletException;ServletConfig getServletConfig();void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;String getServletInfo();void destroy();
}
  • Servlet 规范接口,所有的Servlet必须实现
    • public void init(ServletConfig config) throws ServletException;
      • 初始化方法,容器在构造servlet对象后,自动调用的方法,容器负责实例化一个ServletConfig对象,并在调用该方法时传入
      • ServletConfig对象可以为Servlet 提供初始化参数
    • public ServletConfig getServletConfig();
      • 获取ServletConfig对象的方法,后续可以通过该对象获取Servlet初始化参数
    • public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException;
      • 处理请求并做出响应的服务方法,每次请求产生时由容器调用
      • 容器创建一个ServletRequest对象和ServletResponse对象,容器在调用service方法时,传入这两个对象
    • public String getServletInfo();
      • 获取ServletInfo信息的方法
    • public void destroy();
      • Servlet实例在销毁之前调用的方法

GenericServlet 抽象类

public abstract class GenericServlet implements Servlet, ServletConfig, Serializable {private static final long serialVersionUID = 1L;// 初始化配置对象作为属性private transient ServletConfig config;// 构造器,为了满足继承而准备public GenericServlet() {}// 销毁方法的平庸实现public void destroy() {}// 获取初始参数的快捷方法public String getInitParameter(String name) {return this.getServletConfig().getInitParameter(name);}// 返回所有初始化参数名的方法public Enumeration<String> getInitParameterNames() {return this.getServletConfig().getInitParameterNames();}// 获取初始Servlet初始配置对象ServletConfig的方法public ServletConfig getServletConfig() {return this.config;}// 获取上下文对象ServletContext的方法public ServletContext getServletContext() {return this.getServletConfig().getServletContext();}// 获取Servlet信息的平庸实现public String getServletInfo() {return "";}// 初始化方法的实现,并在此调用了init的重载方法public void init(ServletConfig config) throws ServletException {this.config = config;this.init();}// 重载init方法,为了让我们自己定义初始化功能的方法public void init() throws ServletException {}// 打印日志的方法及重载public void log(String message) {ServletContext var10000 = this.getServletContext();String var10001 = this.getServletName();var10000.log(var10001 + ": " + message);}public void log(String message, Throwable t) {this.getServletContext().log(this.getServletName() + ": " + message, t);}// 服务方法再次声明public abstract void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;// 获取ServletName的方法public String getServletName() {return this.config.getServletName();}
}

HttpServlet 抽象类

public abstract class HttpServlet extends GenericServlet {// 用于定义常见请求方式名常量值private static final String METHOD_DELETE = "DELETE";private static final String METHOD_HEAD = "HEAD";private static final String METHOD_GET = "GET";private static final String METHOD_OPTIONS = "OPTIONS";private static final String METHOD_POST = "POST";private static final String METHOD_PUT = "PUT";private static final String METHOD_TRACE = "TRACE";// 构造器,用于处理继承public HttpServlet() {}public void init(ServletConfig config) throws ServletException {super.init(config);this.cachedUseLegacyDoHead = Boolean.parseBoolean(config.getInitParameter("jakarta.servlet.http.legacyDoHead"));}protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {String msg = lStrings.getString("http.method_get_not_supported");this.sendMethodNotAllowed(req, resp, msg);}protected long getLastModified(HttpServletRequest req) {return -1L;}protected void doHead(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {if (!DispatcherType.INCLUDE.equals(req.getDispatcherType()) && this.cachedUseLegacyDoHead) {NoBodyResponse response = new NoBodyResponse(resp);this.doGet(req, response);if (req.isAsyncStarted()) {req.getAsyncContext().addListener(new NoBodyAsyncContextListener(response));} else {response.setContentLength();}} else {this.doGet(req, resp);}}protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {String msg = lStrings.getString("http.method_post_not_supported");this.sendMethodNotAllowed(req, resp, msg);}protected void doPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {String msg = lStrings.getString("http.method_put_not_supported");this.sendMethodNotAllowed(req, resp, msg);}protected void doDelete(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {String msg = lStrings.getString("http.method_delete_not_supported");this.sendMethodNotAllowed(req, resp, msg);}protected void doOptions(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {String allow = this.getCachedAllowHeaderValue();if (HttpServlet.TomcatHack.getAllowTrace(req)) {if (allow.length() == 0) {allow = "TRACE";} else {allow = allow + ", TRACE";}}resp.setHeader("Allow", allow);}protected void doTrace(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {String CRLF = "\r\n";StringBuilder buffer = (new StringBuilder("TRACE ")).append(req.getRequestURI()).append(' ').append(req.getProtocol());Enumeration<String> reqHeaderNames = req.getHeaderNames();while(true) {String headerName;do {if (!reqHeaderNames.hasMoreElements()) {buffer.append(CRLF);int responseLength = buffer.length();resp.setContentType("message/http");resp.setContentLength(responseLength);ServletOutputStream out = resp.getOutputStream();out.print(buffer.toString());out.close();return;}headerName = (String)reqHeaderNames.nextElement();} while(this.isSensitiveHeader(headerName));Enumeration<String> headerValues = req.getHeaders(headerName);while(headerValues.hasMoreElements()) {String headerValue = (String)headerValues.nextElement();buffer.append(CRLF).append(headerName).append(": ").append(headerValue);}}}// 重载的service方法,被重写的service方法所调用,在该方法中,通过请求方式判断,调用具体的do***方法完成请求的处理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);}}// 对服务方法的实现 在该方法中,将请求和响应对象转换成对应HTTP协议HttpServletRequest HttpServletResponse对象 调用重载的service方法public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {HttpServletRequest request;HttpServletResponse response;try {request = (HttpServletRequest)req;response = (HttpServletResponse)res;} catch (ClassCastException var6) {throw new ServletException(lStrings.getString("http.non_http"));}this.service(request, response);}
}

自定义Servlet

在这里插入图片描述

自定义Servlet中,必须要对处理请求的方法进行重写

  • 要么重写service方法
  • 要么重写doGet/doPost方法

5 ServletConfig和ServletContext

ServletConfig的使用

ServletConfig是什么

  • 为Servlet提供初始配置参数的一种对象,每个Servlet都有自己独立唯一的ServletConfig对象
  • 容器会为每个Servlet实例化一个ServletConfig对象,并通过Servlet生命周期的init方法传入给Servlet作为属性

在这里插入图片描述

ServletConfig是一个接口,定义了如下API

package jakarta.servlet;
import java.util.Enumeration;
public interface ServletConfig {String getServletName();ServletContext getServletContext();String getInitParameter(String var1);Enumeration<String> getInitParameterNames();
}
方法名作用
getServletName()获取<servlet-name>HelloServlet</servlet-name>定义的Servlet名称
getServletContext()获取ServletContext对象
getInitParameter()获取配置Servlet时设置的『初始化参数』,根据名字获取值
getInitParameterNames()获取所有初始化参数名组成的Enumeration对象

使用方法

  • 定义Servlet
public class ServletA extends HttpServlet {@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {ServletConfig servletConfig = this.getServletConfig();// 根据参数名获取单个参数String value = servletConfig.getInitParameter("param1");System.out.println("param1:"+value);// 获取所有参数名Enumeration<String> parameterNames = servletConfig.getInitParameterNames();// 迭代并获取参数名while (parameterNames.hasMoreElements()) {String paramaterName = parameterNames.nextElement();System.out.println(paramaterName+":"+servletConfig.getInitParameter(paramaterName));}}
}public class ServletB extends HttpServlet {@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {ServletConfig servletConfig = this.getServletConfig();// 根据参数名获取单个参数String value = servletConfig.getInitParameter("param1");System.out.println("param1:"+value);// 获取所有参数名Enumeration<String> parameterNames = servletConfig.getInitParameterNames();// 迭代并获取参数名while (parameterNames.hasMoreElements()) {String paramaterName = parameterNames.nextElement();System.out.println(paramaterName+":"+servletConfig.getInitParameter(paramaterName));}}
}
  • 配置Servlet
  <servlet><servlet-name>ServletA</servlet-name><servlet-class>com.atguigu.servlet.ServletA</servlet-class><!--配置ServletA的初始参数--><init-param><param-name>param1</param-name><param-value>value1</param-value></init-param><init-param><param-name>param2</param-name><param-value>value2</param-value></init-param></servlet><servlet><servlet-name>ServletB</servlet-name><servlet-class>com.atguigu.servlet.ServletB</servlet-class><!--配置ServletB的初始参数--><init-param><param-name>param3</param-name><param-value>value3</param-value></init-param><init-param><param-name>param4</param-name><param-value>value4</param-value></init-param></servlet><servlet-mapping><servlet-name>ServletA</servlet-name><url-pattern>/servletA</url-pattern></servlet-mapping><servlet-mapping><servlet-name>ServletB</servlet-name><url-pattern>/servletB</url-pattern></servlet-mapping>

ServletContext的使用

ServletContext是什么

  • ServletContext对象有称呼为上下文对象,或者叫应用域对象(后面统一讲解域对象)
  • 容器会为每个app创建一个独立的唯一的ServletContext对象
  • ServletContext对象为所有的Servlet所共享
  • ServletContext可以为所有的Servlet提供初始配置参数

在这里插入图片描述

ServletContext怎么用

  • 配置ServletContext参数
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd"version="5.0"><context-param><param-name>paramA</param-name><param-value>valueA</param-value></context-param><context-param><param-name>paramB</param-name><param-value>valueB</param-value></context-param>
</web-app>
  • 在Servlet中获取ServletContext并获取参数
package com.atguigu.servlet;import jakarta.servlet.ServletConfig;
import jakarta.servlet.ServletContext;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;import java.io.IOException;
import java.util.Enumeration;public class ServletA extends HttpServlet {@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// 从ServletContext中获取为所有的Servlet准备的参数ServletContext servletContext = this.getServletContext();String valueA = servletContext.getInitParameter("paramA");System.out.println("paramA:"+valueA);// 获取所有参数名Enumeration<String> initParameterNames = servletContext.getInitParameterNames();// 迭代并获取参数名while (initParameterNames.hasMoreElements()) {String paramaterName = initParameterNames.nextElement();System.out.println(paramaterName+":"+servletContext.getInitParameter(paramaterName));}}
}

6 HttpServletRequest和HttpServletResponse

HttpServletRequest简介

  • HttpServletRequest是一个接口,其父接口是ServletRequest
  • HttpServletRequest是Tomcat将请求报文转换封装而来的对象,在Tomcat调用service方法时传入
  • HttpServletRequest代表客户端发来的请求,所有请求中的信息都可以通过该对象获得

HttpServletRequest常见API

  • 获取请求行信息相关(方式,请求的url,协议及版本)
API功能解释
StringBuffer getRequestURL();获取客户端请求的url
String getRequestURI();获取客户端请求项目中的具体资源
int getServerPort();获取客户端发送请求时的端口
int getLocalPort();获取本应用在所在容器的端口
int getRemotePort();获取客户端程序的端口
String getScheme();获取请求协议
String getProtocol();获取请求协议及版本号
String getMethod();获取请求方式
  • 获得请求头信息相关
API功能解释
String getHeader(String headerName);根据头名称获取请求头
Enumeration getHeaderNames();获取所有的请求头名字
String getContentType();获取content-type请求头
  • 获得请求参数相关
API功能解释
String getParameter(String parameterName);根据请求参数名获取请求单个参数值
String[] getParameterValues(String parameterName);根据请求参数名获取请求多个参数值数组
Enumeration getParameterNames();获取所有请求参数名
Map<String, String[]> getParameterMap();获取所有请求参数的键值对集合
BufferedReader getReader() throws IOException;获取读取请求体的字符输入流
ServletInputStream getInputStream() throws IOException;获取读取请求体的字节输入流
int getContentLength();获得请求体长度的字节数
  • 其他API
API功能解释
String getServletPath();获取请求的Servlet的映射路径
ServletContext getServletContext();获取ServletContext对象
Cookie[] getCookies();获取请求中的所有cookie
HttpSession getSession();获取Session对象
void setCharacterEncoding(String encoding) ;设置请求体字符集

HttpServletResponse简介

  • HttpServletResponse是一个接口,其父接口是ServletResponse
  • HttpServletResponse是Tomcat预先创建的,在Tomcat调用service方法时传入
  • HttpServletResponse代表对客户端的响应,该对象会被转换成响应的报文发送给客户端,通过该对象我们可以设置响应信息

HttpServletResponse的常见API

  • 设置响应行相关
API功能解释
void setStatus(int code);设置响应状态码
  • 设置响应头相关
API功能解释
void setHeader(String headerName, String headerValue);设置/修改响应头键值对
void setContentType(String contentType);设置content-type响应头及响应字符集(设置MIME类型)
  • 设置响应体相关
API功能解释
PrintWriter getWriter() throws IOException;获得向响应体放入信息的字符输出流
ServletOutputStream getOutputStream() throws IOException;获得向响应体放入信息的字节输出流
void setContentLength(int length);设置响应体的字节长度,其实就是在设置content-length响应头
  • 其他API
API功能解释
void sendError(int code, String message) throws IOException;向客户端响应错误信息的方法,需要指定响应码和响应信息
void addCookie(Cookie cookie);向响应体中增加cookie
void setCharacterEncoding(String encoding);设置响应体字符集

MIME类型

  • MIME类型,可以理解为文档类型,用户表示传递的数据是属于什么类型的文档
  • 浏览器可以根据MIME类型决定该用什么样的方式解析接收到的响应体数据
  • 可以这样理解: 前后端交互数据时,告诉对方发给对方的是 html/css/js/图片/声音/视频/… …
  • tomcat/conf/web.xml中配置了常见文件的拓展名和MIMIE类型的对应关系
  • 常见的MIME类型举例如下
文件拓展名MIME类型
.htmltext/html
.csstext/css
.jsapplication/javascript
.png /.jpeg/.jpg/… …image/jpeg
.mp3/.mpe/.mpeg/ … …audio/mpeg
.mp4video/mp4
.m1v/.m1v/.m2v/.mpe/… …video/mpeg

7 请求转发和响应重定向

概述

什么是请求转发和响应重定向

  • 请求转发和响应重定向是web应用中间接访问项目资源的两种手段,也是Servlet控制页面跳转的两种手段

  • 请求转发通过HttpServletRequest实现,响应重定向通过HttpServletResponse实现

  • 请求转发生活举例: 张三找李四借钱,李四没有,李四找王五,让王五借给张三

  • 响应重定向生活举例:张三找李四借钱,李四没有,李四让张三去找王五,张三自己再去找王五借钱

请求转发

请求转发运行逻辑图

在这里插入图片描述

请求转发特点(背诵)

  • 请求转发通过HttpServletRequest对象获取请求转发器实现
  • 请求转发是服务器内部的行为,对客户端是屏蔽的
  • 客户端只发送了一次请求,客户端地址栏不变
  • 服务端只产生了一对请求和响应对象,这一对请求和响应对象会继续传递给下一个资源
  • 因为全程只有一个HttpServletRequset对象,所以请求参数可以传递,请求域中的数据也可以传递
  • 请求转发可以转发给其他Servlet动态资源,也可以转发给一些静态资源以实现页面跳转
  • 请求转发可以转发给WEB-INF下受保护的资源
  • 请求转发不能转发到本项目以外的外部资源

测试代码

ServletA

@WebServlet("/servletA")
public class ServletA extends HttpServlet {@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//  获取请求转发器//  转发给servlet  okRequestDispatcher  requestDispatcher = req.getRequestDispatcher("servletB");//  转发给一个视图资源 ok//RequestDispatcher requestDispatcher = req.getRequestDispatcher("welcome.html");//  转发给WEB-INF下的资源  ok//RequestDispatcher requestDispatcher = req.getRequestDispatcher("WEB-INF/views/view1.html");//  转发给外部资源   no//RequestDispatcher requestDispatcher = req.getRequestDispatcher("http://www.atguigu.com");//  获取请求参数String username = req.getParameter("username");System.out.println(username);//  向请求域中添加数据req.setAttribute("reqKey","requestMessage");//  做出转发动作requestDispatcher.forward(req,resp);}
}
  • ServletB
@WebServlet("/servletB")
public class ServletB extends HttpServlet {@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// 获取请求参数String username = req.getParameter("username");System.out.println(username);// 获取请求域中的数据String reqMessage = (String)req.getAttribute("reqKey");System.out.println(reqMessage);// 做出响应resp.getWriter().write("servletB response");        }
}

ServletA将请求转发给ServletB了。

响应重定向

响应重定向运行逻辑图

在这里插入图片描述

响应重定向特点(背诵)

  • 响应重定向通过HttpServletResponse对象的sendRedirect方法实现
  • 响应重定向是服务端通过302响应码和路径,告诉客户端自己去找其他资源,是在服务端提示下的,客户端的行为
  • 客户端至少发送了两次请求,客户端地址栏是要变化的
  • 服务端产生了多对请求和响应对象,且请求和响应对象不会传递给下一个资源
  • 因为全程产生了多个HttpServletRequset对象,所以请求参数不可以传递,请求域中的数据也不可以传递
  • 重定向可以是其他Servlet动态资源,也可以是一些静态资源以实现页面跳转
  • 重定向不可以到给WEB-INF下受保护的资源
  • 重定向可以到本项目以外的外部资源

响应重定向测试代码

  • ServletA
@WebServlet("/servletA")
public class ServletA extends HttpServlet {@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//  获取请求参数String username = req.getParameter("username");System.out.println(username);//  向请求域中添加数据req.setAttribute("reqKey","requestMessage");//  响应重定向// 重定向到servlet动态资源 OKresp.sendRedirect("servletB");// 重定向到视图静态资源 OK//resp.sendRedirect("welcome.html");// 重定向到WEB-INF下的资源 NO//resp.sendRedirect("WEB-INF/views/view1");// 重定向到外部资源//resp.sendRedirect("http://www.atguigu.com");}
}
  • ServletB
@WebServlet("/servletB")
public class ServletB extends HttpServlet {@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// 获取请求参数String username = req.getParameter("username");System.out.println(username);// 获取请求域中的数据String reqMessage = (String)req.getAttribute("reqKey");System.out.println(reqMessage);// 做出响应resp.getWriter().write("servletB response");}
}

8 MVC架构模式

MVC(Model View Controller)是软件工程中的一种**软件架构模式,它把软件系统分为模型视图控制器**三个基本部分。用一种业务逻辑、数据、界面显示分离的方法组织代码,将业务逻辑聚集到一个部件里面,在改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑。

  • M:Model 模型层,具体功能如下

    1. 存放和数据库对象的实体类以及一些用于存储非数据库表完整相关的VO对象
    2. 存放一些对数据进行逻辑运算操作的的一些业务处理代码
  • V:View 视图层,具体功能如下

    1. 存放一些视图文件相关的代码 html css js等
    2. 在前后端分离的项目中,后端已经没有视图文件,该层次已经衍化成独立的前端项目
  • C:Controller 控制层,具体功能如下

    1. 接收客户端请求,获得请求数据
    2. 将准备好的数据响应给客户端

MVC模式下,项目中的常见包

  • M:

    1. 实体类包(pojo /entity /bean) 专门存放和数据库对应的实体类和一些VO对象
    2. 数据库访问包(dao/mapper) 专门存放对数据库不同表格CURD方法封装的一些类
    3. 服务包(service) 专门存放对数据进行业务逻辑运算的一些类
  • C:

    1. 控制层包(controller)
  • V:

    1. web目录下的视图资源 html css js img 等
    2. 前端工程化后,在后端项目中已经不存在了

非前后端分离的MVC

在这里插入图片描述

前后端分离的MVC

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/475009.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

集群聊天服务器(12)nginx负载均衡器

目录 负载均衡器nginx负载均衡器优势 如何解决集群聊天服务器跨服务器通信问题&#xff1f;nginx的TCP负载均衡配置nginx配置 负载均衡器 目前最多只能支持2w台客户机进行同时聊天 所以要引入集群&#xff0c;多服务器。 但是客户连哪一台服务器呢&#xff1f;客户并不知道哪一…

基于YOLOv8深度学习的智慧交通事故评级检测系统研究与实现(PyQt5界面+数据集+训练代码)

本文研究并实现了一种基于YOLOv8深度学习模型的智慧交通事故评级检测系统&#xff0c;旨在解决传统交通事故检测过程中效率低、误报率高等问题。该系统通过深度学习技术的应用&#xff0c;结合交通事故图像的分析&#xff0c;能够实现对事故的精准识别和评级&#xff0c;进而为…

基于Java Springboot出租车管理网站

一、作品包含 源码数据库设计文档万字PPT全套环境和工具资源部署教程 二、项目技术 前端技术&#xff1a;Html、Css、Js、Vue、Element-ui 数据库&#xff1a;MySQL 后端技术&#xff1a;Java、Spring Boot、MyBatis 三、运行环境 开发工具&#xff1a;IDEA/eclipse 数据…

iOS 18 导航栏插入动画会导致背景短暂变白的解决

问题现象 在最新的 iOS 18 系统中,如果我们执行导航栏的插入动画,可能会造成导航栏背景短暂地变为白色: 如上图所示:我们分别向主视图和 Sheet 弹出视图的导航栏插入了消息,并应用了动画效果。可以看到,前者的导航栏背景会在消息插入那一霎那“变白”,而后者则没有任何…

[Go]-sync.map使用详解

sync.Map是 Go 语言中在并发环境下使用的安全映射类型。 一、为什么需要sync.Map 在 Go 语言中&#xff0c;普通的map不是并发安全的。当多个 goroutine 同时读写一个普通map时&#xff0c;可能会导致程序出现未定义的行为&#xff0c;比如数据竞争、程序崩溃等。而sync.Map则…

Ubuntu22.04安装CH343驱动并创建udev规则

驱动说明 Linux系统提供CH34*系列 USB UART 设备配合使用的默认 CDC-ACM 驱动程序。驱动程序文件名为CDC-ACM。CDC-ACM 驱动程序控制特定设备的能力有限。此通用驱动程序不了解特定设备协议。因此&#xff0c;设备制造商可以创建能够访问设备特定功能集&#xff08;例如硬件流…

Stable Diffusion经典应用场景

&#x1f33a;系列文章推荐&#x1f33a; 扩散模型系列文章正在持续的更新&#xff0c;更新节奏如下&#xff0c;先更新SD模型讲解&#xff0c;再更新相关的微调方法文章&#xff0c;敬请期待&#xff01;&#xff01;&#xff01;&#xff08;本文及其之前的文章均已更新&…

MATLAB常见数学运算函数

MATLAB中含有许多有用的函数,可以随时调用。 a b s abs abs函数 a b s abs abs函数在MATLAB中可以求绝对值,也可以求复数的模长:c e i l ceil ceil函数 向正无穷四舍五入(如果有小数,就向正方向进一)f l o o r floor floor函数 向负无穷四舍五入(如果有小数,就向负方向…

学习与理解LabVIEW中的格式化写入(Format into String)函数

有例子会更容易学习与理解LabVIEW中的函数 这是函数的基本介绍&#xff0c;下面我将以例子的方式介绍该函数&#xff1a; 初始字符串将会和已经填充好的格式化字符串拼接在一起&#xff0c;组成结果字符串&#xff0c;初始字符串在前。 应用&#xff1a; 可以用在执行SQL语句或…

Ubuntu22.04.2 k8s部署

k8s介绍 简单介绍 通俗易懂的解释&#xff1a; Kubernetes&#xff08;也被称为 K8s&#xff09;就像是一个大管家&#xff0c;帮你管理你的云计算服务。想象一下&#xff0c;你有很多个小程序&#xff08;我们称之为“容器”&#xff09;&#xff0c;每个都在做不同的事情&…

oracle导入线上数据的全步骤

多租户架构允许oracle数据库成为一个多租户的容器数据库&#xff0c;也就是CDB&#xff0c;container database&#xff0c;与之相对应的&#xff0c;则是插入到这个容器里面的可插拔式数据库&#xff0c;pluggable database 一个CDB可以包含0&#xff0c;1或者多个用户创建的…

【机器学习】在泊松分布中,当λ值较大时,其近似正态分布的误差如何评估?

在泊松分布中&#xff0c;当参数 λ 较大时&#xff0c;其近似正态分布的有效性可以通过 中心极限定理 和误差分析来理解和评估。以下内容结合理论推导和实际案例展开说明&#xff1a; 1. 泊松分布的定义 泊松分布是用于建模单位时间或单位空间内随机事件发生次数的概率分布&a…

快速搭建Android开发环境:Docker部署docker-android并实现远程连接

目录 前言 1. 虚拟化环境检查 2. Android 模拟器部署 3. Ubuntu安装Cpolar 4. 配置公网地址 5. 远程访问 小结 6. 固定Cpolar公网地址 7. 固定地址访问 作者简介&#xff1a; 懒大王敲代码&#xff0c;计算机专业应届生 今天给大家聊聊快速搭建Android开发环境&#x…

使用 SMB 协议从win10电脑访问同网段ubuntu电脑文件

​​​​​​1.在 Ubuntu 上设置共享文件夹 在终端中运行以下命令安装 Samba&#xff1a; sudo apt update sudo apt install samba 编辑 Samba 配置文件&#xff1a; sudo nano /etc/samba/smb.conf 在文件末尾添加以下内容&#xff08;假设要共享 用户dy下的Downloads目录&…

Android WMS概览

WMS&#xff08;WindowManagerService&#xff09;是 Android 系统的核心服务&#xff0c;负责管理应用和系统的窗口&#xff0c;包括窗口的创建、销毁、布局、层级管理、输入事件分发以及动画显示等。它通过协调 InputManager 和 SurfaceFlinger 实现触摸事件处理和窗口渲染&a…

25.<Spring博客系统②(实现JWT令牌登录接口+强制登录+获取用户信息+获取作者信息)>

PS&#xff1a;带删除线的方法 可以使用但是不建议使用&#xff08;方法提供方说的&#xff09; 加上Deprecated注解。就代表这个方法可以使用&#xff0c;但是不建议使用。也就会带删除线了 前言 对于用户登录。 我们之前的做法都是 1.用户登录&#xff0c;后端验证用户名和密…

《Python编程实训快速上手》第七天--文件与文件路径

该章节将使用Python在硬盘上创建、读取和保存文件 一、文件与文件路径 1、Windows中使用\以及macOS和Linux中使用/ 使用pathlib模块中的Path()函数进行文件名和目录的拼接,返回文件路径字符串 from pathlib import Path print(Path("spam","bacon",&qu…

Oracle RAC仲裁交换机的小科普

一、Oracle RAC仲裁交换机的主要功能 Oracle RAC仲裁交换机是用于Oracle Real Application Clusters&#xff08;真实应用集群&#xff0c;简称RAC&#xff09;环境中的一种网络设备。它主要用于在集群节点之间进行通信&#xff0c;以确保集群的高可用性和故障切换能力。以下是…

Leetcode 快乐数

算法思想&#xff1a; 这段代码的目的是判断一个正整数是否是 快乐数&#xff08;Happy Number&#xff09;。根据题目要求&#xff0c;快乐数定义如下&#xff1a; 对于一个正整数&#xff0c;不断将它每个位上的数字替换为这些数字平方和。重复这个过程&#xff0c;如果最终…

使用 Vue 和 Create-Vue 构建工程化前端项目

目录 前言1. 工程化的意义与 Vue 的生态支持2. 搭建 Vue 工程化项目2.1 环境准备2.2 使用 create-vue 创建项目2.2.1 初始化项目2.2.2 安装依赖2.2.3 本地运行 3. Vue 项目的目录结构解析4. Vue 开发流程详解4.1 项目入口与根组件4.1.1 main.js 的作用4.1.2 App.vue 的结构 4.2…