JavaWeb 15.详解Servlet及其源码

news2024/10/8 18:23:25

所有受过的委屈,都在提醒你

要好好争气。

                                      —— 24.10.7

一、Servlet简介

1.动态资源和静态资源

静态资源

无需在程序运行时通过代码运行生成的资源,在程序运行之前就写好的资源,例如:html、css、js、img、音频文件和视频文件

动态资源

需要在程序运行时通过代码运行生成的资源,在程序运行之前无法确定的数据,运行时动态生成,例如:Servlet、Thymeleaf、……

动态资源指的不是视图上的动画效果或者是简单的人机交互效果


生活举例

去蛋糕店买蛋糕:

        静态资源:直接买柜台上的成品

        动态资源:预定蛋糕,要求现场制作


动/静态资源的响应过程


2.Servlet简介

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

不是所有的JAVA类都能用于处理客户端请求,能处理客户端请求并做出响应的一套技术标准就是Servlet

其主要功能在于交互式地浏览和修改数据,生成动态Web内容。

Servlet是运行在服务端的,所以Servlet必须在WEB项日中开发并在Tomcat这样的服务容器中运行


Servlet执行流程

① 浏览器向TomCat发送一个请求报文:请求行、请求头、请求体

② TomCat接受了请求报文,TomCat将请求报文信息转换成了一个HttpServletRequest对象,该对象中包含了请求中的所有信息:请求行、请求头、请求体

③ TomCat同时创建了一个HttpServletResponse对象,该对象用于承载要响应给客户端的信息,后面该对象会被转换成响应的报文:响应行、响应头、响应体

④ TomCat会根据请求定义一个servlet类,实现一个接口标准(implements Servlet)

⑤ TomCat根据请求中的资源路径找到对应的Servlet,将servlet实例化,调用service方法,同时将HttpServletRequest请求对象和HttpServletResponse响应对象传入

        1.从request对象中获取请求的所有信息(参数)

        2.根据参数生成要响应给客户端的数据

        3.将响应的数据放入response对象

⑥ TomCat将response对象转换成一个响应报文发送给客户端


Servlet作用

用来接收、处理客户端请求、响应给浏览器的动态资源。在整个Web应用中,Servlet主要负责接收处理请求、协同调度功能以及响应数据。我们可以把Servlet称为Web应用中的控制器

Servlet充当一个“中间商”的角色,将客户端请求接收下来传递给服务端,服务端处理完成后再将处理好的响应数据传递给Servlet,然后通过Servlet将服务端的响应数据传给客户端


二、Servlet开发流程

1.目标

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

2.开发流程

① 创建一个JavaWeb项目,点击Project Settings同时将tomcat添加为当前项目的依赖

② 添加web资源组件

点击Help——>Find Action——>Add Frameworks support

③ 创建小表单,建立html页面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<form method="get" action="userServlet">
    用户名:<input type="text" name="username"><br>
    <input type="submit" value="校验">
</form>

</body>
</html>

④ 重写service方法:继承HttpServlet,间接实现了service方法

传递了请求报文信息和响应报文信息

service(HttpServletRequest req,HttpServletResponse resp)

public class UserServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 1.从request对象中获取请求报文中的任何信息(username参数)
        //   根据参数名获取参数值,无论参数是在url?后,还是在请求体中
        String username = req.getParameter("username");

        // 2.处理业务的代码
        String res = "Yes";
        if("YYSHlcl".equals(username)){
            res = "No";
        }

        // 3.将要响应的数据放入response
        PrintWriter writer = resp.getWriter(); // 该方法返回的是一个向响应体中打印字符串的打印流
        writer.write(res);
    }
}

⑤ 在service方法中,定义业务处理代码

        String info = "Yes";
        if("YYSHlcl".equals(username)){
            info = "No";
        }

⑥ 在Web.xml文件中,配置Servlet对应的请求映射路径

<?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_6_0.xsd"
         version="6.0">
<!--
    1.配置Servlet类,并起一个别名
        servlet-name    用于关联请求的映射路径
        servlet-class   告诉Tomcat对应的要实例化的Servlet类
-->
    <servlet>
        <servlet-name>userServlet</servlet-name>
        <servlet-class>Servlet.UserServlet</servlet-class>
    </servlet>
    
    <servlet-mapping>
        <servlet-name>userServlet</servlet-name>
        <url-pattern>/userServlet</url-pattern>
    </servlet-mapping>

</web-app>


3.问题

① Servlet-api.jar导入问题

servlet-api 编码的时候需要,运行的时候,在服务器的环境中,由服务软件(Tomcat)提供
因此,我们的JAVAWEB项目中,在打包/构建的时候,是无需携带servlet-api的jar包

② Content-Type响应头的问题

MINE类型响应头        媒体类型,文件类型,响应的数据类型

MINE类型用于告诉客户端响应的数据是什么类型的数据,客户端以此类型决定用什么方式解析响应体


4.Servlet_url-pattern的一些特殊写法问题

url-pattern:pattern路径

        ① 精确匹配

                /servlet1

        ② 模糊匹配

                *  作为通配符,*在哪里,哪里就是模糊的

                /  匹配全部,不包含isp文件

                /*  来匹配全部,包含isp文件

                /a/*  匹配前缀,后缀模糊

                *.action  匹配后级,前缀模糊


三、Servlet_注解方式配置Servlet

1.@WebServlet注解源码

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

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;

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface WebServlet {
    String name() default "";

    String[] value() default {};

    String[] urlPatterns() default {};

    int loadOnStartup() default -1;

    WebInitParam[] initParams() default {};

    boolean asyncSupported() default false;

    String smallIcon() default "";

    String largeIcon() default "";

    String description() default "";

    String displayName() default "";
}


2.@WebServlet注解使用

// value 和 urlpatterns表示路径名,定义一个就够了
@WebServlet(name = "servlet1",value = "/s1")
public class Servlet1 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("Servlet1执行了");
    }
}

四、Servlet生命周期

1.生命周期简介

什么是Servlet的生命周期

应用程序中的对象不仅在空间上有层次结构的关系,在时间上也会因为处于程序运行过程中的不同阶段而表现出不同状态和不同行为。这就是对象的生命周期。

简单的叙述生命周期,就是对象在容器中从开始创建到销毁的过程。


Servlet容器

Servlet对象是Servlet容器创建的,生命周期方法都是由容器(Tomcat)调用的。开发人员要尽可能多的将精力放在业务逻辑的实现上。


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

1.实例化                                        构造器                第一次请求/服务启动        1次
2.初始化                                        init                      构造完毕                            1次
3.接收请求,处理请求,服务             service               每次请求                            多次
4.销毁                                            destroy               关闭服务                            1次


2.生命周期调试

package 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;

/*
    1.实例化                   构造器            第一次请求/服务启动
    2.初始化                    init            构造完毕
    3.接收请求,处理请求,服务      service          每次请求
    4.销毁                     destroy          关闭服务
 */

// 配置Servlet方式2:注解方式    配置Servlet方式1:xml文件配置信息
@WebServlet(value = "/ServletLifeCycle",loadOnStartup = 100)
public class ServletLifeCycle extends HttpServlet {
    public ServletLifeCycle() {
        System.out.println("构造器");
    }

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

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("服务");
    }

    @Override
    public void destroy(){
        System.out.println("destroy");
    }


}

配置Servlet

    <servlet>
        <servlet-name>servletLifeCycle</servlet-name>
        <servlet-class>Servlet.ServletLifeCycle</servlet-class>
        <load-on-startup>3</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>servletLifeCycle</servlet-name>
        <url-pattern>/servletLifeCycle</url-pattern>
    </servlet-mapping>

3.生命周期总结

1. 通过生命周期测试我们发现Servlet对象在容器中是单例的

2. 容器是可以处理并发的用户请求的,每个请求在容器中都会开启一个线程

3. 多个线程可能会使用相同的Servlet对象,所以在Servlet中,我们不要轻易定义一些容易经常发生修改的成员变量(加锁会降低性能),会引发线程安全问题

4. default-servlet 用于加载静态资源的servlet,默认随服务启动,默认启动序号为1

5. load-on-startup中定义的正整数表示实例化顺序,如果数字重复了,容器会自行解决实例化顺序问题,但是应该避免重复

6. Tomcat容器中,已经定义了一些随系统启动实例化的servlet,我们自定义的servlet的load-on-startup尽量不要占用数字1-5


五、Servlet继承结构

1.Servlet接口

void init(Servletconfig var1) throws ServletException;
// 初始化方法,构造完毕后,由tomcat自动调用完成初始化功能的方法

ServletConfig getServletConfig();
// 获得ServletConfig对象的方法

void service(ServletRequest var1,ServletResponse var2) throws ServletException, IOException;
// 接收用户请求,向用于响应信息的方法

String getServletInfo();
// 返回Servlet字符串形式描述信息的方法

void destroy();
// Servlet在回收前,由tomcat调用的销毁方法,往往用于做资源的释放工作

① void init(Servletconfig var1) throws ServletException;

初始化方法,构造完毕后,由tomcat自动调用完成初始化功能的方法

② ServletConfig getServletConfig();

获得ServletConfig对象的方法

③ void service(ServletRequest var1,ServletResponse var2) throws ServletException, IOException;

接收用户请求,向用于响应信息的方法

④ String getServletInfo();

返回Servlet字符串形式描述信息的方法

⑤ void destroy();

Servlet在回收前,由tomcat调用的销毁方法,往往用于做资源的释放工作


2.抽象类        GenericServlet

GenericServlet 抽象类是对Servlet接口一些固定功能的粗糙实现,以及对service方法的再次抽象声明,并定义了一些其他相关功能方法,侧重于除了service方法以外其他方法的处理

① private transient ServletConfig config;

初始化对象作为属性

② public GenericServlet(){}

构造器,为了满足继承而准备

⭐③ public void destroy(){}

将抽象方法重写为普通方法,在方法内部没有任何的实现代码,销毁方法的平庸实现

④ public String getInitParameter(String name)

获取初识参数的快捷方法

⑤ public Enumeration getInitParameterNames()

返回所有初始化参数名的方法

⭐⑥ public ServletConfig getServletConfig()

获取初识Servlet初始配置对象ServletConfig的方法

⑦ public ServletContext getServletContext()

获取上下文对ServletContext的方法

⑧ public String getServletInfo()

获取Servlet信息的平庸实现

⭐⑨ public void init(ServletConfig config) throws ServletException()

tomcat在调用init方法时,会读取配置信息进入一个Servletconfig对象并将该对象传入init方法初始化

⭐⑩ public void init() throws ServletException

重载的init初始化方法,我们定义重写初始化功能时对应的方法

⑪ public void log(String msg)         public void log(String message,Throwable t)

打印日志的方法及重载

⭐⑫ public abstract void service(ServletRequest req, ServletResponse res) throws ServletException, IOException;

服务方法再次抽象声明

⑬ public String getServletName()

获取ServletName的方法


3.抽象类        HttpServlet

abstract class HttpServlet extends GenericServlet

HttpServlet抽象类,除了基础的实现以外,增加了更多的基础功能,侧重于service方法的处理

     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 service(ServletRequest req, ServletResponse res) throws ServletException, 
IOException;

 对服务方法的实现

 在该方法中,将请求和响应对象转换成对应HTTP协议的HttpServletRequest和   HttpServletResponse对象

 调用重载的service方法


public void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException;

重载的service方法,被重写的service方法所调用

在该方法中,通过请求方式判断, 用具体的do***方法完成请求的处理。


protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws 
ServletException, IOException;

protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws 
ServletException, IOException;

protected void doHead(HttpServletRequest req, HttpServletResponse resp) throws 
ServletException, IOException;

protected void doPut(HttpServletRequest req, HttpServletResponse resp) throws 
ServletException, IOException;

protected void doDelete(HttpServletRequest req, HttpServletResponse resp) throws 
ServletException, IOException;

protected void doOptions(HttpServletRequest req, HttpServletResponse resp) throws 
ServletException, IOException;

protected void doTrace(HttpServletRequest req, HttpServletResponse resp) throws 
ServletException, IOException

 对应不同请求方式的处理方法

 除了doOptions和doTrace方法,其他的do*** 方法都在故意响应错误信息


4.自定义Servlet

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

要么重写service方法

要么重写doGet/doPost方法


5.掌握技能

继承HttpServlet,要么重写service方法; 要么重写doGet/doPost方法


六、ServletConfig和ServletContext

1.ServletConfig

ServletConfig是什么

为Servlet提供初始配置参数的一种对象,每个Servlet都有自己独立唯一的ServletConfig对象;

容器(Tomcat)会为每个Servlet实例化一个ServletConfig对象,通过Servlet的init方法传入给Servlet 作为属性;

Tomcat从 web.xml / 注解 中获取到初始配置参数,然后tomcat自动获取到配置信息,自动为每个Servlet实例化一个ServletConfig对象,再将这个ServletConfig对象传入Servlet作为属性

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

getServletName()        获取<servlet-name>HelloServlet</servlet-name>定义的Servlet名称

getServletContext()        获取ServletContext对象

getInitParameter()        获取配置Servlet设置的初始化参数,根据名字获取值

getInitParameterNames()        获取所有初始化参数名组成的Enumeration对象

package akarta.servlet;
import ava.util.Enumeration;
public interface ServletConfig {
    String getServletName();
    ServletContext getServletContext();
    String getInitParameter(String var1);
    Enumeration<String> getInitParameterNames();
}

2.ServletContext⭐

ServletContext是什么

ServletContext对象是单例

ServletContext对象有称呼为上下文对,或者叫应用域对象;

容器为每个app创建 一个独立的唯一的ServletContext对象;

ServletContext对象为所有的Servlet所共享

ServletContext可以为所有的Servlet提供初始配置参数;

ServletContext其他重要API

① 获取资源的磁盘路径

获得一个指向项目部署位置下的某个文件/目录的磁盘真实路径的API

String realPath = servletContext.getRealPath("资源在web目录中的路径");

例如我们的目标是需要获取项目中某个静态资源的路径,不是工程目录中的路径,而是部署目录中的路径;我们如果直接拷贝其在我们电脑中的完整路径的话其实是有问题的,因为如果该项目以后部署到公司服务器上的话,路径肯定是会发生改变的,所以我们需要使用代码动态获取资源的真实路径.只要使用了servletcontext动态获取资源的真实路径,那么无论项目的部署路径发生什么变化,都会动态获取项目运行时候的实际磁盘路径,所以就不会发生由于写死真实路径而导致项目部署位置改变引发的路径错误问题。 

② 获取项目的上下文路径

String contextPath = servletContext.getContextPath();

项目的部署名称,也叫项目的上下文路径,在部署进入tomcat时所使用的路径,该路径是可能发生变化的,通过该API动态获取项目真实的上下文路径,可以帮助我们解决一些后端页面渲染技术或者请求转发和响应重定向中的路径问题。

③ 域对象的相关API

域对象:一些用于在一些特定的范围内存储数据和传递数据的对象,不同的范围称为不同的“域”,不同的域对象代表不同的域,共享数据的范围也不同;

ServletContext代表应用,所以ServletContext域也叫作应用域,是webapp中最大的域,可以在本应用内实现数据的共享和传递;

webapp中的三大域对象,分别是应用域,会话域,请求域

三大域对象都具有的API如下:

void setAttribute(String key,Object value);                        向域中存储/修改数据

Object getAttribute(String key);                                         获得域中的数据

void removeAttribute(String key);                                      移除域中的数据


七、HttpServletRequest

1.简介

HttpServletRequest是什么

HttpServletRequest是一个接口,其父接口是ServletRequest;

HttpServletRequest是Tomcat将请求报文封装而来的对象,在Tomcat用service方法时传入;

HttpServletRequest代表客户端发来的请求,请求中的所有信息都可以通过该对象获得;


 2.常见API

获取请求行信息相关(请求方式,请求的url路径,协议及版本)

StringBuffer getRequestURL();                         获取客户端请求的url

String getRequestURI();                                    获取客户端请求项目中的具体资源

int getServerPort();                                            获取客户端发送请求时的端口

int getLocalPort();                                              获取本应用在所在容器的端口

int getRemotePort();                                          获取客户端程序端口

String getScheme();                                           获取请求协议

String getProtocol();                                           获得请求协议及版本号        

String getMethod();                                            获取请求方式

获得请求头信息相关:

String getHeader(String headerName);                根据头名称获取请求

Enumeration getHeaderNames();                         获取所有的请求头名字

String getContentType();                                       获取content-type请求头

获得请求参数相关:

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:

String getServletPath();                                        获取请求的Servlet的映射路径

ServletContext getServletContext();                     获取ServletContext对象

Cookie[] getCookies();                                          获取请求体中的所有cookie

HttpSession getSession();                                    获取Session对象        

void setCharacterEncoding(String encoding) ;     设置请求体字符集


八、HttpServletResponse

1.简介

HttpServletResponse是什么

HttpServletResponse是一个接口,其接口是ServletResponse;

HttpServletResponse是Tomcat预先创建的,在Tomcat调用service方法时传入;

HttpServletResponse代表对客户端的响应,该对象会被转换成响应的报文发送给客户端,通过该对象我们可以设置响应信息;


2.常见API

设置响应行相关

void setStatus(int code);                设置响应状态码

设置响应头相关

void setHeader(String headerName, String headerValue);        设置/修改响应头键值对

void setContentType(String contentType); 设置content-type响应头及响应集(设置MIME类型)

设置响应体相关

PrintWriter getWriter() throws IOException;                获得向响应体放入信息的输出流 ServletOutputStream getOutputStream() throws IOException;

获得向响应体放入信息输出流

void setContentLength(int length);        设置响应体的,其实就是在设置content-length响应头

其他API

void sendError(int code, String message) throws0Exception;

向客户端响应错误信息的方法,需要指定响应码和响应信息
void addCookie(Cookie cookie);                                          向响应体中增加cookie
void setCharacterEncoding(String encoding);                     设置响应体字符集


3.MIME类型

MIME类型,可以理解为文档类型,用户表示传递的数据是属于什么类型的文档;

浏览器可以根据MIME类型决定该用什么的方式解析接收到的响应体数据;

可以理解为:前后端交互数据时,对方发给对方的是 html/css/js/图片/声音/视频/... ...;

tomcat/conf/web.xml中配置了常见文件的拓展名和MIMIE类型的对应关系;

常见的MIME类型举例如下:

 文件拓展名                                                        MIME类型

.html                                                                   text/html

.css                                                                     text/css

.js                                                                 application/javascript

.json                                                                 application/json

.png /.jpeg /.jpg /...                                             image /jpeg

.mp3/.mpe/.mpeg/…                                           video /mp4

.m1v /.m1v /.m2v /.mpe /...                                 video/mpeg


九、请求转发和响应重定向

概述

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

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

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

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

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


请求转发

请求转发运行逻辑图 


请求转发特点

① 请求转发通过HttpServletRequest对象获取请求转发器实现;

② 请求转发是服务器内部的行为,对客户端是屏蔽的;

③ 客户端只发送了一次请求,客户端地址栏是不变的;

④ 服务端只产生了一对请求和响应对象,这一对请求和响应对象继续传递给下一个资源;

⑤ 因为全程只有一个HttpServletRequset对象,所以请求参数可以传递,请求域中的数据也可以传递;

⑥ 请求转发可以发给其他Servlet动态资源,也可以转发给一些静态资源以实现页面跳转;

⑦ 请求转发可以发给WEB-INF下受保护的资源;

⑧ 请求转发不能转发到本项目以外的外部资源; 


响应重定向

响应重定向运行逻辑图


响应重定向特点

① 响应重定向通过HttpServletResponse对象的sendRedirect方法实现;

② 响应重定向是服务端通过302响应码和路径,告诉客户端自己去寻找其他资源,是在服务端提示下的客户端的行为

③ 客户端至少发送了两次请求,客户端地址栏是要变化的;

④ 服务端产生了多对请求和响应对象,且请求和响应对象不会传递给下一个资源;

⑤ 因为全程产生了多个HttpServletRequset对象,所以请求参数不可以传递,请求域中的数据也不可以传递

⑥ 重定向可以是其他Servlet动态资源,也可以是一些静态资源以实现页面跳转;

⑦ 重定向目标资源不可以是WEB-INF下受保护的资源

⑧ 重定向目标资源可以是本项目以外的全部资源

结论:同样能够实现页面跳转,优先使用响应重定向


十、MVC架构模式

MVC模式简介

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

MVC提供了一套项目代码设计、分类、存放的一套设计思想

更加符合:① 高内聚低耦合 ② 开闭原则 

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

        1.存放和数据库对象的实体类以及一些用于存储非数据库表完整相关的VO对象

        2.存放一些对数据进行逻辑运算操作的一些业务处理代码

V:View 视图层,具体功能如下

        1.存放一些视图文件相关的代码 html css js等

        2.在前后端分离的项目中,后端已经没有视图文件,该层次已经行化成独立的前端项目

C:Controller 控制层,具体功能如下

        1.接收客户端请求,获得请求数据

        2.将准备好的数据响应给客户端


MVC模式下项目中的常见包

M:

        1.实体类包(pojo /entity /bean)        专门存放和数据库对应的实体类和一些VO(valueObject)对象

        2.数据库访问包(dao/mapper)        专门存放对数据库不同表格CURD方法封装的一些类

        3.服务包(service)        专门存放对数据进行业务逻辑预算的一些类

C:

        1.控制层包(controller)

V:

        1.web目录下的视图资源 html、css、js img等

        2.前端工程化后,在后端项目中已经不存在了

非前后端分离的MVC


十一、web乱码和路径问题总结

乱码问题

乱码问题产生的根本原因是什么?

① 数据的编码和解码使用的不是同一个字符集

② 使用了不支持某个语言文字的字符集


HTML乱码问题

设置项目文件的字符集要使用一个支持中文的字符集


Tomcat控制台乱码

将 tomcat /conf /loggin.properties 中所有的字符集UTF-8修改为GBK即可

sout 乱码问题,设置JVM 加载.class文件时使用UTF-8 字符集。


GET请求乱码

GET方式提交数的方式是将参数放到URL后面,如果使用的不是UTF-8,那么对参数进行URL编 码处理;

HTML中的 <meta charset='字符集'/> 影响了GET方式提交参数的URL编码;

当GET方式提交的参数URL编码和Tomcat的URI编码不一致时,就会出现乱码;

解决方式

方式1:设置GET方式提交的编码和Tomcat的URI默认解析编码一致即可。

方式2 :设置Tomcat的URI解析字符集和GET请求发送时所使用URL转码时的字符集一致即可,修改conf/server.xml中 Connecter 添加 URIEncoding="GBK"


POST方式请求乱码

form 表单的POST请求将数在请求体中进行发送;

请求体使用的字符受集到了 <meta charset='字符集'/> 的影响;

如果请求体的URL转码和Tomcat的请求体解析编码不一致,就容易出现乱码

解决方式

方式1 : 请求时,使用UTF-8 字符集提交请求体 (

方式2:后端在获取参数前,设置解析请求体使用的字符集和请求发送时使用的字符集一致


响应乱码问题 

浏览器在接收响应信息时,使用了不同的字符集或者是不支持中文的字符集就会出现乱码。

解决方式

方式1:手动设定浏览器对本次响应体解析时使用的字符集

        edge和 chrome浏览器没有提供直接的比较方便的入口,不方便

方式2:后端通过设置响应体的字符集和浏览器解析响应体的默认字符集一致

方式3::通过设置Content-Type响应头,告诉浏览器以指定的字符集解析响应体


路径问题

相对路径和绝对路径:

相对路径:

相对路径的规则是以当前资源所在的路径为出发点去寻找目标资源

相对路径不以 / 开头;

在file协议下,使用的是磁盘路径;

在http协议下,使用的是url路径;

相对路径中可以使用 ./ 表示当前资源所在路径,可以省略不写;

相对路径中可以使用 ../ 表示当前资源所在的上一层路径,需要时要手动添加;

缺点:目标资源路径收到当前资源路径的影响,不同的为止,相对路径写法不同

绝对路径:

绝对路径的规则是: 使用以一个固定的路径做出发点去寻找目标资源,和当前资源所在的路径没有关系;

绝对路径要以 / 开头;

绝对路径的写法中,不以当前资源的所在路径为出发点,所以不会出现 ./ 和../开头

不同的项目和不同的协议下,绝对路径的基础位置可能不同,要通过测试确定;

绝对路径的好处就是,无论当前资源位置在哪,寻找目标资源路径的写法都一致;

缺点:要补充项目的上下文,而上下文是可以改变的

应用场景:

        1. 前端代码中,href、src、action 等属性;

        2. 请求转发和重定向中的路径

不设置当前项目上下文路径

取消项目上下文路径后直接写 / + 绝对路径就好

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

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

相关文章

职场秘籍:面试加薪,竟然拥有不同的技巧!

假如你是一位测试主管&#xff0c;去评价一名测试工程师是否优秀&#xff0c;那么你将如何去判断呢&#xff1f;你最看重的是哪方面的能力呢&#xff1f; 对于这个问题&#xff0c;是不能一概而论的&#xff0c;要分为两种情况&#xff0c;情况不同&#xff0c;答案一定是不同…

高校新生报道管理系统使用SpringBootSSM框架开发

&#xff01;&#xff01;&#xff01;页面底部,文章结尾,加我好友,获取计算机毕设开发资料 目录 一、引言 二、相关技术介绍 三、系统需求分析 四、系统设计 五、关键技术实现 六、测试与优化 七、总结与展望 一、引言 当前高校新生报到过程中存在许多问题&#xff0c;…

从0到1:用Python构建你人生中的第一个人工智能AI模型

文章目录 摘要引言数据预处理&#xff1a;为模型打下坚实基础数据预处理的步骤Python示例代码说明&#xff1a;注意事项&#xff1a; 模型建立&#xff1a;选择合适的模型神经网络示例代码说明&#xff1a; 模型训练与测试训练示例代码说明&#xff1a; 解读模型结果性能指标 深…

原生小程序开发|小程序卡片(Widget) 开发指南

开发 Widget 代表应用的一个小程序卡片&#xff0c;负责小程序卡片的展示和交互。 小程序卡片(Widget) 的开发在智能小程序的基础上增加一个目录即可&#xff0c;用于存放小程序卡片(Widget)的代码。并在 project.tuya.json 中增加一个声明。 创建小程序卡片(Widget)项目 在 …

九、Drf序列化器

九、序列化器 9.1序列化 从数据库取QuerySet或数据对象转换成JSON 9.1.1序列化器的简易使用 #新建一张部门表 class Depart(models.Model):title=models.CharField(verbose_name=部门,max_length=32)order=models.IntegerField(verbose_name=顺序)count=models.IntegerFiel…

vscode中安装python的包

首先需要调出命令行。然后运行代码&#xff0c;找到你所需要的环境。 PS C:\Users\Administrator\AppData\Local\ESRI\conda\envs\arcgispro-env> conda env list # conda environments: #C:\ProgramData\Anaconda3 base * C:\Users\Administrator\.con…

【无人机设计与控制】无人机三维路径规划,对比蚁群算法,ACO_Astar_RRT算法

摘要 本文探讨了三种不同的无人机三维路径规划算法&#xff0c;即蚁群算法&#xff08;ACO&#xff09;、A算法&#xff08;Astar&#xff09;以及快速随机树算法&#xff08;RRT&#xff09;。通过仿真实验对比了各算法在不同环境下的性能&#xff0c;包括路径长度、计算效率…

软考越来越难了,2024年软考究竟还值不值得考?

最近不少同学沟通&#xff0c;聊到软考现在越来越难了&#xff0c;考了两三次都没过&#xff0c;也有不少新同学咨询软考考试的一些福利政策&#xff0c;投入大量的物力&#xff0c;财力&#xff0c;精力&#xff0c;那么到底软考值不值得考呢&#xff1f; 01 / 关于软考 软考…

【FlagScale】异构算力混合训练方案

背景以及必要性 算力需求的高峰&#xff1a;随着人工智能&#xff08;AI&#xff09;和生成内容&#xff08;AIGC&#xff09;的发展&#xff0c;对计算资源的需求急剧增加。尤其是参数规模达到数百亿的大模型训练&#xff0c;需要大量的计算资源。 算力市场供应紧张&#xff…

一键拯救废片!3个在线教程,实现光线重塑、表情迁移、模糊图像修复

每逢国庆「黄金周」&#xff0c;都是旅游业的高光时刻。根据研判&#xff0c;今年国庆假期全社会跨区域人员流动量将达到 19.4 亿人次&#xff0c;平均每天 2.77 亿人次。 与旅游业同步增长的还有摄影行业&#xff0c;旅拍带动的妆造、服饰租赁等相关环节发展火热&#xff0c;…

Linux安装Redis7.40

一、环境检查 1.1 查看是否已经安装了Redis应用 ps -ef |grep redis或者 whereis redis1.2 若已经安装了redis应用或者有遗留的Redis文件&#xff0c;进行移除或者启动即可。 二、下载&安装 2.1 找到对应的安装包资源&#xff0c;使用wget命令下载&#xff0c;这里安装…

小众交友软件有哪些?小众交友APP排行榜前十名推荐

在网络的广袤天地中&#xff0c;小众交友软件如隐藏的宝藏&#xff0c;散发着独特魅力。它们为人们提供别样的社交舞台&#xff0c;让孤独的灵魂有处可栖。今天&#xff0c;就让我们一同探寻那些小众交友软件的奇妙世界。 1. 咕哇找搭子小程序&#xff1a;这是一个实名制的找搭…

想要加密电脑?盘点2024年企业常用的10款电脑文件加密软件

在企业数据安全的时代背景下&#xff0c;文件加密已经成为保护企业核心信息、应对网络安全威胁的关键举措。无论是保护机密的商业数据&#xff0c;还是遵守数据隐私合规性要求&#xff0c;企业对文件加密软件的需求日益增长。本文将盘点2024年企业常用的10款电脑文件加密软件&a…

【Java 问题】基础——序列化

接上文 序列化 45.什么是序列化&#xff1f;什么是反序列化&#xff1f;46.说说有几种序列化方式&#xff1f; 45.什么是序列化&#xff1f;什么是反序列化&#xff1f; 什么是序列化&#xff0c;序列化就是把Java对象转为二进制流&#xff0c;方便存储和传输。 所以反序列化…

SOA是什么

SOA SOA 即 Service-Oriented Architecture&#xff08;面向服务的架构&#xff09;。 一、定义 SOA 是一种软件设计方法和架构理念&#xff0c;它将应用程序的不同功能单元&#xff08;称为服务&#xff09;通过定义良好的接口和契约联系起来。这些服务可以独立部署、独立运…

【JavaEE初阶】深入理解不同锁的意义,synchronized的加锁过程理解以及CAS的原子性实现(面试经典题);

前言 &#x1f31f;&#x1f31f;本期讲解关于锁的相关知识了解&#xff0c;这里涉及到高频面试题哦~~~ &#x1f308;上期博客在这里&#xff1a;【JavaEE初阶】深入理解线程池的概念以及Java标准库提供的方法参数分析-CSDN博客 &#x1f308;感兴趣的小伙伴看一看小编主页&am…

(笔记)第三期书生·浦语大模型实战营(十一卷王场)–书生基础岛第6关---OpenCompass 评测 InternLM-1.8B 实践

学员闯关手册&#xff1a;https://aicarrier.feishu.cn/wiki/ZcgkwqteZi9s4ZkYr0Gcayg1n1g?open_in_browsertrue 课程视频&#xff1a;https://www.bilibili.com/video/BV1RM4m1279j/ 课程文档&#xff1a; https://github.com/InternLM/Tutorial/blob/camp3/docs/L1/OpenComp…

嵌入式设备硬件和软件安全设计

1. 引言 哪个领域的网络安全实施记录最差&#xff1f; 既不是 PKI/数字证书&#xff0c;也不是 密钥管理&#xff0c;也不是 OAuth。很可能是嵌入式设备和物联网 领域。 总的来说&#xff0c;这似乎是一个梦想&#xff0c;但如果可设计出“设计安全”的系统&#xff0c;而不…

转行大模型开发,能不能挽救职业生涯?

大模型算是当之无愧最火的一个方向了&#xff0c;算是新时代的风口。有小伙伴觉得&#xff0c;既然是新领域、新方向&#xff0c;那么&#xff0c;人才需求肯定比较大&#xff0c;相应的人才缺乏&#xff0c;竞争也会更少&#xff0c;那转行去做大模型是不是一个更好的选择呢&a…

硬盘数据恢复的方法有哪几种?9种妙招速览

在当今数字化时代&#xff0c;硬盘数据的安全至关重要。然而&#xff0c;数据丢失的情况时有发生&#xff0c;掌握硬盘数据恢复方法显得尤为重要。本文将详细介绍几种有效的硬盘数据恢复方法&#xff0c;帮助用户在遇到数据丢失问题时&#xff0c;能够迅速采取措施&#xff0c;…