[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.xdnf.cn/news/20634.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

【Unity基础】认识Unity中的包

Unity中的包是一个核心概念&#xff0c;像Unity本身的功能的扩展&#xff0c;或者项目中资源的管理&#xff0c;都是通过包的形式来实现的。 一、什么是包&#xff1f; 一个包包含满足您项目各种需求的功能。这可以包括编辑器安装过程中附带的任何核心Unity功能&#xff0c;也…

elment-ui的折叠tree表单实现纯前端搜索,展开收起功能

好久没更新博客了~ 记录一下本次做的一个很扯的需求 纯前端去实现这个查询的功能,后台返回的是个数组对象,前端要给他包装成树结构先展示 之后参考代码路径src\views\goods\category\index.vue 需求描述: 搜索输入任何一个关键字,都会展开他的父级,两个栏目都包含了,那么两个父…

linux先创建文件夹后指定创建文件夹用户

1、创建文件夹&#xff0c;然后创建用户并指定用户目录&#xff0c;然后修改目录所有权给该目录 # 创建 /home/test 目录 mkdir /home/test # 设置权限&#xff08;确保有适当的读写权限&#xff09; chown root:root /home/test chmod 700 /home/test # 创建 xl 用户并指定家…

大模型(LLM)全参数微调有哪些技巧,常用的轻量级微调有哪些,微调策略应该如何选择?

大家好&#xff0c;我是微学AI&#xff0c;今天给大家介绍一下大模型(LLM)全参数微调有哪些技巧&#xff0c;常用的轻量级微调有哪些&#xff0c;微调策略应该如何选择&#xff1f;本文将从大模型(LLM)全参数微调技巧&#xff0c;常用的轻量级微调方法&#xff0c;微调策略应该…

蓝牙电话-如何自动切换手机SIM卡(预研方向)

蓝牙电话-如何自动切换手机SIM卡&#xff08;预研方向&#xff09; 一、前言 最近突然有客户问说&#xff0c;蓝牙电话的app既然已经能统计手机里面插了多少张卡&#xff0c;那能不能做双卡的SIM卡自动切换&#xff1f;即&#xff1a;设置一个呼叫策略和频率&#xff0c;当打…

【蓝桥杯C/C++】C语言和C++的常量概念与区别分析

博客主页&#xff1a; [小ᶻZ࿆] 本文专栏: 蓝桥杯C/C 文章目录 &#x1f4af;前言&#x1f4af;常量的概念和作用&#x1f4af;C语言中 const 的应用与限制#define 和 enum 的使用方法 &#x1f4af;C 中 const 的计算方法和处理&#x1f4af;代码实例和应用区别&#x1f…

全面解析亚马逊云服务器(AWS):功能、优势与使用指南

亚马逊云服务器&#xff08;AWS&#xff09;概述 亚马逊云服务器&#xff08;Amazon Web Services&#xff0c;简称AWS&#xff09;是全球领先的云计算平台&#xff0c;提供一系列强大且灵活的云服务&#xff0c;帮助企业和开发者通过云基础设施实现数据存储、计算、分析和机器…

“小浣熊家族AI办公助手”产品体验 — “人人都是数据分析师”

一、引言&#xff1a; 大家平时应该在工作中常常使用到Excel来做数据统计&#xff0c;比如临近过年时&#xff0c;公司一般会开各种复盘、年终、检讨、明年规划大会&#xff0c;势必需要准备一大堆的量化数据报表&#xff0c;用于会议上的数据汇报、分析工作&#xff0c;试想一…

C盘扩容(C盘右键无法扩展卷解决)超详细步骤!!!

目录 1、问题及需求2、解决办法方法2 1、问题及需求 今天一看C盘爆红了&#xff0c;但是D盘还剩很多空间&#xff0c;想要从D盘再分出来50G给C盘。 但是压缩了D盘&#xff0c;在C盘扩展卷&#xff0c;实现不了&#xff0c;因为不仅挨着。看下边的解决办法 2、解决办法 桌面上…

机器学习笔记 // 天气预报、股票价格以及历史轨迹(如摩尔定律)// 时间序列的常见属性

时间序列随处可见。你可能已经在天气预报、股票价格以及历史轨迹[如摩尔定律&#xff0c;见下图​]等事物中见过它们。摩尔定律预测微芯片上面的晶体管个数大约每两年会翻倍。几乎50年以来&#xff0c;它已经被证明对未来的计算能源和成本来说是一个准确的预测器。 许多时间序列…

mysql日志写满出现The table ‘xxxx_amazon_order’ is full

数仓发现写数据出现 SQL 错误 [1114] [HY000]: The table ‘xxxx_amazon_order’ is full 1.第一时间查看系统磁盘, 发现空间写满了 df -h因为mysql是使用docker部署的, Docker 的默认存储位置在 /var/lib/docker /var 目录默认是在根分区 (/dev/mapper/centos-root) 下的 …

(一)Ubuntu22.04服务器端部署Stable-Diffusion-webui AI绘画环境

一、说明 cup型号&#xff1a; Intel(R) Celeron(R) CPU G1610 2.60GHz 内存大小&#xff1a; 8G 显卡型号&#xff1a;NVIDIA P104-100 注意&#xff1a;系统睡眠问题 sudo systemctl mask sleep.target suspend.target hibernate.target hybrid-sleep.target 网卡设置 …

springboot:少量配置信息情形

发现无论怎么改都还是指向8001 所以换一种方法 通过 结果 代码 import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.web.server.ConfigurableWebServerFactory; import org.springframework.boot.web.server.WebServerFactoryCusto…

SpringBoot的快速入门

Maven Maven可以方便管理依赖的 Jar 包 IDEA 自带Maven&#xff0c;也可以选择自己安装 安装Maven:https://blog.csdn.net/qq_59636442/article/details/142314019 创建项目 通过Spring Initializr 快速创建项目&#xff1a;https://start.springboot.io/ 我的项目名叫blog&a…

2024中国高校计算机大赛 — 大数据挑战赛-赛后复盘

一、赛题描述 基于气象大数据的自动站实况联合预测 风光清洁能源的管理与气象关系密不可分&#xff0c;因为风能和太阳能的发电效率直接依赖于气象条件。风力发电需要精确的风速和风向预测&#xff0c;而太阳能发电则依赖于日照时间和云层覆盖情况的准确预报。优质的气象预测…

J.U.C - 深入解析ReentrantLock原理源码

文章目录 概述synchronized的缺陷1&#xff09;synchronized不能控制阻塞&#xff0c;不能灵活控制锁的释放。2&#xff09;在读多写少的场景中&#xff0c;效率低下。 独占锁ReentrantLock原理ReentrantLock概述AQS同步队列1. AQS实现原理2. 线程被唤醒时&#xff0c;AQS队列的…

基于Java+Springboot+Jpa+Mysql实现的在线网盘文件分享系统功能设计与实现二

一、前言介绍&#xff1a; 免费学习&#xff1a;猿来入此 1.1 项目摘要 在线网盘文件分享系统的课题背景主要源于现代社会对数字化信息存储和共享需求的日益增长。随着互联网的普及和技术的快速发展&#xff0c;人们越来越依赖电子设备来存储和传输各种类型的数据文件。然而…

DBSCAN聚类——基于密度的聚类算法(常用的聚类算法)

DBSCAN&#xff08;Density-Based Spatial Clustering of Applications with Noise&#xff09;简称密度聚类或密度基础聚类&#xff0c;是一种基于密度的聚类算法&#xff0c;也是一种常用的无监督学习算法&#xff0c;特别适用于形状不规则的聚类和含有噪声的数据集。主要用于…

C++:指针和引用

指针的基础 数据在内存当中是怎么样被存储的 数据在内存中的存储方式取决于数据的类型和计算机的体系结构 基本数据类型 整数类型&#xff1a;整数在内存中以二进制补码的形式存储。对于有符号整数&#xff0c;最高位为符号位&#xff0c;0 表示正数&#xff0c;1 表示负数。…

LabVIEW多通道面阵烟雾透过率测试系统

LabVIEW面阵烟雾透过率测试系统通过高精度多通道数据采集和实时处理技术&#xff0c;能够实现对固体推进剂烟雾的透过率进行精确测量。系统利用了LabVIEW的图形化编程环境及其丰富的设备驱动接口&#xff0c;有效提升了测试的自动化程度和数据处理的实时性。 项目背景&#xf…