JAVAWeb中的Servlet学习
一 Servlet简介
1.1动态资源和静态资源
静态资源
- 无需在程序运行时通过代码运行生成的资源,在程序运行之前就写好的资源.例如:html css js img ,音频文件和视频文件
动态资源
- 需要在程序运行时通过代码运行生成的资源,在程序运行之前无法确定的数据,运行时动态生成,例如Servlet,Thymeleaf …。
- 动态资源指的不是视图上的动画效果或者是简单的人机交互效果
1.2Servlet简介
Servlet(serverapplet)是运行在服务端(tomcat)的java小程序,是sun公司提供的一套定义动态资源规范;从代码上将Servlet就是一个接口。
- 用来接收、处理客户端请求、响应给浏览器的动态资源。在整个Web应用中,Servlet主要负责接收处理请求、协同调度功能以及响应数据。我们可以把Servlet称为web应用中的控制器。
- 不是所有的JAVA类都能用于处理客户端请求,能处理客户端请求并做出响应的一套技术标准就是Servlet
- Servlet是运行在服务端的,所以Servlet必须在WEB项目中开发且在Tomcat这样的服务容器中运行
请求响应HttpServletRequest和HttpServletResponse之间的对对应关系
二 Servlet开发流程
2.1 目标
校验注册信息。
2.2 开发过程
1 创建javaWEB项目,同时将tomcat添加当前项目依赖
2 重写service方法,service(HttpServletRequest req, HttpServletResponse resp)
3 在service方法中,定义业务处理代码
4 在web。xml中,配置Servlet对应的请求映射路径
2.3 servlet-api.jar 导入问题
servlet-api 编码的时候需要,运行的时候在服务器的环境中,由服务器(Tomcat)提供,因此我们的JAVAWEB项目中,在打包/构建的时候,是无需携带servlet-api的jar包
2.4 Content-Type响应头的问题
MIME类型响应头 媒体类型,文件类型,响应的数据类型
MIME类型用于告诉客户端响应的数据是什么类型的数据,客户端以此类型决定用什么方式解析响应体
2.5 Servlet_url-pattern的一些特殊写法问题
<!-- 一个servlet-name可以对应多个url-pattern一个servlet标签可以对应多个servlet-mapping标签url-pattern1 精确匹配/s12 模糊匹配*作为通配符/ 匹配全部,不包含jsp文件/* 匹配全部,包含jsp文件/a/* 匹配前缀,后缀模糊/*.action 匹配后缀,前缀模糊
--><servlet><servlet-name>servlet1</servlet-name><servlet-class>com.zhg.servlet.Servlet1</servlet-class></servlet><servlet-mapping><servlet-name>servlet1</servlet-name><url-pattern>/s1</url-pattern><url-pattern>/s2</url-pattern></servlet-mapping><servlet-mapping><servlet-name>servlet1</servlet-name><url-pattern>/s3</url-pattern></servlet-mapping>
2.6 Servlet 注解方式配置
@WebServlet("/s1")
public class UserServlet extends HttpServlet
三 Servlet的声明周期
3.1 生命周期简介
什么是Servlet的生命周期
- 应用程序中的对象不仅在空间上有层次结构的关系,在时间上也会因为处于程序运行过程中的不同阶段而表现出不同状态和不同行为–这就是对象的生命周期。
- 简单的叙述生命周期,就是对象在容器中从开始创建到销毁的过程。
Servlet容器
- Servlet对象是Servlet容器创建的,生命周期方法都是由容器(目前我们使用的是Tomcat)调用的。这一点和我们之前所编写的代码有很大不同。在今后的学习中我们会看到,越来越多的对象交给容器或框架来创建,越来越多的方法由容器或框架来调用,开发人员要尽可能多的将精力放在业务逻辑的实现上。
Servlet主要的生命周期执行特点
生命周期 | 对应方法 | 执行时机 | 执行次数 |
---|---|---|---|
构造对象 | 构造器 | 第一次请求或容器启动 | 1 |
初始化 | init() | 构造完毕后 | 1 |
处理服务 | service(HttpServletRequest req, HttpServletResponse resp) | 每次请求 | 多次 |
销毁 | destory() | 容器关闭 | 1 |
/*** 1实例化 构造器* 2初始化 init* 3接受请求,处理请求 service* 4销毁 destroy** Servlet在Tomcat中是单例的* Servlet的成员变脸在多个线程之中是共享的* 不建议在service方法中修改成员变量 在并发请求时,会引发线程安全问题** defaultServlet 默认servlet 静态资源由defaultServlet处理*/
@WebServlet("/servletifeCycle")
public class ServletifeCycle extends HttpServlet {public ServletifeCycle() {System.out.println("new ");}@Overridepublic void init(ServletConfig config) throws ServletException {System.out.println("init");}@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {System.out.println("service");}@Overridepublic void destroy() {System.out.println("destroy");}
}
四 Servlet继承结构
4.1 顶级的Servlet接口
/* Servlet继承结构
* 1顶级的Servlet接口
* public interface Servlet {
* //初始化方法,构造完毕后,由Tomcat自动调用完成初始化功能的方法
* void init(ServletConfig var1) throws ServletException;
*
* //获得ServletConfig对象的方法
* ServletConfig getServletConfig();
*
* //接受用户请求,响应信息
* void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;
*
* //返回Servlet字符串描述的信息
* String getServletInfo();
*
* //Servlet在回收前,由TOmcat调用的销毁方法,往往用于资源的释放
* void destroy();
* }
*/
4.2 抽象的类 GenericServlet
/*2 抽象的类 GenericServlet 侧重service方法意外的其他方法的基础处理
* public abstract class GenericServlet implements Servlet{
*
* private transient ServletConfig config;
*
* public void destroy() {
* //将抽象方法,重写为普通方法,在方法内部没有任何的实现代码
* }
*
* // tomcat在调用init方法时,会读取配置信息进入一个ServletConfig对象并将该对象传入init方法
* public void init(ServletConfig config) throws ServletException {
* //将config对象存储为当前的属性
* this.config = config;
* //调用重载的无参的init
* this.init();
* }
*
* //重载的初始化方法,我们重新初始化方法时对应的方法
* public void init() throws ServletException {
* }
*
* //返回ServletConfig的方法
* public ServletConfig getServletConfig() {
* return this.config;
* }
*
* // 再次抽象声明service方法
* public abstract void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;
* }
*/
4.3 HttpServlet
/* 3 抽象类 侧重service方法的处理
* public abstract class HttpServlet extends GenericServlet{
*
*
* 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"));
* }
*
* //调用重载的service
* this.service(request, response);
* }
*
* protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
* //获取请求的方式
* String method = req.getMethod();
* //更具请求方式,调用对应的do方法
* if (method.equals("GET")) {
* long 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")) {
* long 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[1];
* errArgs[0] = method;
* errMsg = MessageFormat.format(errMsg, errArgs);
* resp.sendError(501, errMsg);
* }
*
* }
*
* //
* protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
* String msg = lStrings.getString("http.method_get_not_supported");
* //故意响应请求方式不允许的信息
* this.sendMethodNotAllowed(req, resp, msg);
* }
*
* //
* private void sendMethodNotAllowed(HttpServletRequest req, HttpServletResponse resp, String msg) throws IOException {
* String protocol = req.getProtocol();
* if (protocol.length() != 0 && !protocol.endsWith("0.9") && !protocol.endsWith("1.0")) {
* resp.sendError(405, msg);//故意响应405请求方式不允许的信息
* } else {
* resp.sendError(400, msg);//故意响应400请求方式不允许的信息
* }
*
* }
* }
*/
4.4 自定义Servlet
/* 4 自定义Servlet
*
* class Servlet extends HttpServlet{
*
* @Override
* protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
* //接受用户请求信息
*
* //做出响应
* }
* }
* 1 部分程序员推荐在servlet中重写do...方法处理请求 理由:service方法中可能做了一些处理,如果我们直接重写service的话,弗雷service方法处理功能则失效
* 2 目前直接重写service也没有什么问题
* 3 使用SpringMvc框架后,无需继承重写HttpServlet方法,处理请求的方法也无需do*** service
* 4 如果doGet 和doPost方法中,实现方式一样,可以一个方法直接调用另一个方法
*/
五 ServletConfig
5.1 ServletConsig是什么
- 为Servlet提供初始配置参数的一种对象,每个Servlet都有自己独立唯一的ServletConfig对象
- 容器会为每个Servlet实例化一个ServletConfig对象,并通过Servlet生命周期的init方法传入给Servlet作为属性
5.2 ServletConfig为Servlet提供配置参数
配置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"><servlet><servlet-name>servlet2</servlet-name><servlet-class>com.zhg.servlet.Servlet2</servlet-class><!--配置servlet的初始参数--><init-param><param-name>key1</param-name><param-value>value1</param-value></init-param></servlet><servlet-mapping><servlet-name>servlet2</servlet-name><url-pattern>/servlet2</url-pattern></servlet-mapping>
</web-app>
定义Servlet
public class Servlet2 extends HttpServlet {@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {ServletConfig servletConfig = getServletConfig();//获取初始配置信息//更具参数名获取参数值String key1 = servletConfig.getInitParameter("key1");System.out.println(key1);//获取所有的初始参数的名字Enumeration<String> initParameterNames = servletConfig.getInitParameterNames();//initParameterNames.hasMoreElements() 判断有没有下一个参数,如果有返回truewhile (initParameterNames.hasMoreElements()){//1获取下一个参数名 2右边向下移动String name = initParameterNames.nextElement();String value = servletConfig.getInitParameter(name);System.out.println(name+"-->"+value);}}
}
注解方式配置
@WebServlet(urlPatterns = "/servlet2",initParams = {@WebInitParam(name = "key1",value = "value1"),@WebInitParam(name = "key2",value = "value2")}
)
public class Servlet2 extends HttpServlet
六 ServletContext
6.1 ServletContext是什么
- ServletContext对象有称呼为上下文对象,或者叫应用域对象
- 容器会为每个app创建一个独立的唯一的ServletContext对象
- ServletContext对象为所有的Servlet所共享
- ServletContext可以为所有的Servlet提供初始配置参数
6.2 Servlet怎么使用
-
配置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_6_0.xsd"version="6.0"><context-param><param-name>encoding</param-name><param-value>UTF-8</param-value></context-param><context-param><param-name>admin</param-name><param-value>pwd</param-value></context-param></web-app>
-
在Servlet中获取ServletContext并获取参数
@WebServlet("/servlet3")
public class Servlet3 extends HttpServlet {@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//获取ServletContextServletContext servletContext1 = getServletContext();ServletContext servletContext2 = getServletConfig().getServletContext();ServletContext servletContext3 = req.getServletContext();//验证三个ServletContext是否是同一个对象System.out.println(servletContext1 == servletContext2);System.out.println(servletContext1 == servletContext3);String encoding = servletContext1.getInitParameter("encoding");System.out.println(encoding);Enumeration<String> initParameterNames = servletContext1.getInitParameterNames();while (initParameterNames.hasMoreElements()) {String name = initParameterNames.nextElement();String value = servletContext1.getInitParameter(name);System.out.println(name + "-->" + value);}}
}
6.3ServletContext其他重要API
获取其他资源的真实路径
String realPath = servletContext.getRealPath(“资源web目录中的路径”)
获取项目的上下文路径
String contextPath = servletContext.getContextPath();
域对象的相关API
- 域对象:一些用于存储数据和传递数据的对象,传递数据不同的范围,我们称之为不同的域;不同的域对象代表不同的域,共享数据的范围也不同
- ServletContext代表应用,所以ServletContext域也叫作应用域,是webapp中最大的域,可以在本应用内实现数据的共享和传递
- webapp中的三大域对象,分别是应用域,会话域,请求域
API | 功能解释 |
---|---|
void setAttribute(String var1, Object var2); | 向域中存储/修改数据 |
Object getAttribute(String var1); | 获得域中的数据 |
void removeAttribute(String var1); | 移除域中的数据 |
七 HttpServletRequest
7.1 HttpServletRequest简介
HttpServletRequest是什么
- HttpServletRequest是一个接口,其父接口是ServletRequest
- HttpServletRequest是Tomcat将请求报文转换封装而来的对象,在Tomcat调用service方法时传入
- HttpServletRequest代表客户端发来的请求,所有请求中的信息都可以通过该对象获得
7.2 HttpServletRequest常见API
HttpServletRequest怎么用
-
获取请求行信息相关
API 功能解释 StringBuffer getRequestURL(); 获取客户端请求的url String getRequestURI(); 获取客户端请求项目中的具体资源 int getServerPort(); 获取客户端发送请求时的端口 int getLocalPort(); 获取本应用在所在容器的端口 int getRemotePort(); 获取客户端程序的端口 String getScheme(); 获取请求协议 String getProtocol(); 获取请求协议及版本号 string getMethod(); 获取请求方式 -
获取请求头信息相关
API | 功能解释 |
---|---|
String getHeader(String headerName); | 根据头名称获取请求头 |
Enumeration getHeaderNames0; | 获取所有的请求头名字 |
String getContentType(); | 获取content-type请求头 |
-
获得请求参数相关
API 功能解释 String getParameter(String parameterName); 根据请求参数名获取请求单个参数值 String[] getParameterValues(String parameterName); 根据请求参数名获取请求多个参数值数组 Enumeration getParameterNames0; 获取所有请求参数名 Map<String, String[> getParameterMap(); 获取所有请求参数的键值对集合 BufferedReader getReader( )throws lOException; 获取读取请求体的字符输入流 ServletInputStream getInputStream() throws IOException; 获取读取请求体的字节输入流 int getContentLength(); 获得请求体长度的字节数 -
其他API
API 功能解释 String getServletPath(); 获取请求的Servlet的映射路径 ServletContext getServletContext(); 获取ServletContext对象 Cookie[] getCookies(); 获取请求中的所有cookie HttpSession getSession(); 获取Session对象 void setCharacterEncoding(String encoding); 设置请求体字符集
@WebServlet("/servlet5")
public class Servlet5 extends HttpServlet {@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//行相关 GET/POST uri http/1.1System.out.println(req.getMethod());//获取请求方式 GETSystem.out.println(req.getScheme());//获取协议 httpSystem.out.println(req.getProtocol());//获取协议及版本 HTTP/1.1System.out.println(req.getRequestURI());//获取请求路径 项目内的资源路径 /demo2/servlet5System.out.println(req.getRequestURL());//获取请求路径 项目内资源的完整路径 http://localhost:8080/demo2/servlet5/*URI 统一资源标识符 interface URI{} 资源定位的要求和规范URL 统一资源定位符 class URL implements URI{} http协议下,一个具体的资源路径*/System.out.println(req.getLocalPort()); //获取服务器端口号System.out.println(req.getServerPort()); //获取客户端发送请求时的端口号System.out.println(req.getRemotePort()); //获取客户端软件的端口号//头相关//根据名字单独获取头信息System.out.println(req.getHeader("User-Agent"));Enumeration<String> headerNames = req.getHeaderNames();//获取所有的头信息while (headerNames.hasMoreElements()){String name = headerNames.nextElement();String value = req.getHeader(name);System.out.println(name+"-->"+value);}}
}
@WebServlet("/servlet6")
public class Servlet6 extends HttpServlet {@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//获取键值对形式的参数//根据参数名获取单个参数String username = req.getParameter("username");System.out.println(username);System.out.println("-----------------------------");//根据参数名获取多个参数值String[] hobbies = req.getParameterValues("hobby");System.out.println(Arrays.toString(hobbies));System.out.println("-----------------------------");//获取所有参数名Enumeration<String> parameterNames = req.getParameterNames();while (parameterNames.hasMoreElements()){String name = parameterNames.nextElement();String[] values = req.getParameterValues(name);System.out.println(name+"-->"+Arrays.toString(values));}System.out.println("-----------------------------");//获取所有参数的map集合 key=参数名 value=参数值Map<String, String[]> parameterMap = req.getParameterMap();for (Map.Entry<String, String[]> entry : parameterMap.entrySet()) {String key = entry.getKey();String[] values = entry.getValue();System.out.println(key+"-->"+Arrays.toString(values));}/*** 以上API用于获取key=value形式的参数** 获得请求体中非键值对数据 JSON串 文件** 获取一个从请求体中读取字符的字符输入流* BufferedReader reader = req.getReader(); JSON串** 获得一个从请求中读取二进制数据字节的输入流* ServletInputStream inputStream = req.getInputStream(); 文件*/String servletPath = req.getServletPath();System.out.println(servletPath);}
}
八 HttpServletResponse
8.1 HttpServletResponse简介
HttpServletResponse是什么
- HttpServletResponse是一个接口,其父接口是ServletResponse
- HttpServletResponse是Tomcat预先创建的,在Tomcat调用service方法时传入
- HttpServletResponse代表对客户端的响应,该对象会被转换成响应的报文发送给客户端,通过该对象我们可以设置响应信息
8.2 HttpServletResponse常见API
HttpServletResponse怎么用
-
设置响应行相关
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 lOException; 获得向响应体放入信息的字节输出流 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类型 |
---|---|
.html | text/html |
.css | text/css |
.js | application/javascript |
.png/.jpeg/… | image/jpeg |
.mp3/.mpe/.mpeg/… | audio/mpeg |
.mp4 | video/mp4 |
.m1v/.m2v/.mpe/… | video/mpeg |
@WebServlet("/servlet7")
public class Servlet7 extends HttpServlet {@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//设置响应头相关的API HTTP/1.1 200/404/405/500/...resp.setStatus(200);String info = "<h1>hello world</h1>";//设置响应头相关的API
// resp.setHeader("aaa","valuea");
// resp.setHeader("Content-Type","text/html");
// resp.setHeader("Content-Length","1234");resp.setContentType("text/html");resp.setContentLength(info.getBytes().length);//设置响应体内容API// 获得一个响应体中输入文本字符输出流PrintWriter writer = resp.getWriter();writer.write(info);}
}
九请求转发和响应重定向
9.1 概述
什么是请求转发和响应重定向
- 请求转发和响应重定向是web应用中间接访问项目资源的两种手段,也是Servlet控制页面跳转的两种手段。
- 请求转发通过HttpServletRequest实现,响应重定向通过HttpServletResponse实现
9.2 请求转发
请求转发运行逻辑图
请求转发特点
- 请求转发通过HttpServletRequest对象获取请求转发器实现
- 请求转发是服务器内部的行为,对客户端是屏蔽的
- 客户端只发送了一次请求,客户端地址栏不变
- 服务端只产生了一对请求和响应对象,这一对请求和响应对象会继续传递给下一个资源
- 因为全程只有一个HttpServletRequset对象,所以请求参数可以传递,请求域中的数据也可以传递
- 请求转发可以转发给其他Servlet动态资源,也可以转发给一些静态资源以实现页面跳转
- 请求转发可以转发给WEB-INF下受保护的资源
@WebServlet("/servlet8")
public class Servlet8 extends HttpServlet {/*** 1 请求转发是通过HttpServletRequest对象来完成* 2 请求转发是服务器内部转发,对客户端是屏蔽的* 3 客户端只产生了一次请求,服务端只产生了一对req 和 res* 4 浏览器地址栏不会发生改变* 5 请求的参数是可以继续传递的* 6 目标资源可以是servlet动态资源 也可以是html静态资源* 7目标资源可以是WEB-INF下的受保护资源* 8 目标资源不可以是本项目的外部资源**/@Overridepublic void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {System.out.println("servlet8");System.out.println(req.getParameter("key"));//转发到servlet9req.getRequestDispatcher("/servlet9").forward(req,res);}
}
@WebServlet("/servlet9")
public class Servlet9 extends HttpServlet {@Overridepublic void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {System.out.println("servlet9");System.out.println(req.getParameter("key"));}
}
9.3 响应重定向
响应重定向运行逻辑图
响应重定向特点
- 响应重定向通过HttpServletResponse对象的sendRedired方法实现
- 响应重定向是服务端通过302响应码和路径,告诉客户端自己去找其他资源,是在服务端提示下的客户端的行为
- 客户端至少发送了两次请求,客户端地址栏是要变化的
- 服务端产生了多对请求和响应对象,且请求和响应对象不会传递给下一个资源
因为全程产生了多个HttpServletRequset对象,所以请求参数不可以传递,请求域中的数据也不可以传递 - 重定向可以是其他Servlet动态资源,也可以是一些静态资源以实现页面跳转
- 重定向不可以到WEB-INF下受保护的资源
- 重定向可以到本项目以外的外部资源
@WebServlet("/servlet10")
public class Servlet10 extends HttpServlet {/*1 重定向是通过HttpServletResponse对象实现2 响应重定向是在服务端提示下,客户端的行为3 客户端的地址栏是变化的4 请求产生多次 后端就会有多个 req resp 此时请求中的参数不能自动传递5 目标资源可以是试图资源6 目标资源不可以WEB-INF下的资源7 目标资源可以是本项目的外部资源*/@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//接受用户请求System.out.println("Servlet10 service");//响应重定向 设置响应状态码为302 同时设置响应头Locationresp.sendRedirect("servlet11");}
}
@WebServlet("/servlet11")
public class Servlet11 extends HttpServlet {@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {System.out.println("Servlet11 service");}
}
十 乱码和路径问题
10.1 乱码问题
乱码问题产生的根本原因是什么
- 数据的编码和解码使用的不是同一个字符集
- 使用了不支持某个语言文字的字符集
各个字符集的兼容性
10.1.1 HTML乱码问题
设置项目文件的字符集要使用一个支持中文的字符集
试图文件通过来告诉浏览器通过什么字符集来解析当前文档
10.1.2 Tomcat控制台乱码
在tomcat10.1 版本中,修改tomcat/conf/loggin.properties中,所有的UTF-为GBK即可
sout乱码问题,设置JVM加载.class文件时使用UTF-8字符集
10.1.3 请求乱码问题
10.1.3.1 GET请求乱码
GET请求方式乱码分析
GET方式提交参数的方式是将参数放到URL后面,如果使用的不是UTF-8,那么会对参数进行URL编码处理
- HTML中的影响了GET方式提交参数的URL编码
- tomcat10.1.7的的URI编码默认为UTF-8
- 当GET方式提交的参数URL编码和tomcat10.1默认的URl编码不一致时,就会出现乱码
GET请求方式乱码演示
-
浏览器解析的文档的
-
GET方式提交时,会对数据进行URL编码处理,是将GBK转码为“百分号码”
-
tomcat10.1.7默认使用UTF-8对URI进行解析,造成前后端使用的字符集不一致,出现乱码
GET请求方式乱码解决
方式1:设置GET方式提交的编码和Tomcat的URI默认解析编码一致
<meta charset="UTF-8">
方式2:方式2:设置Tomcat的URI解析字符集和GET请求发送时所使用URL转码时的字符集一致即可,修改conf/serverxml中Connecter添加URIEncoding=““GBK””(不推荐)
10.1.3.2 POST方式请求乱码
POST请求方式乱码分析
- POST请求将参数放在请求体中进行发送
- 请求体使用的字符集受到了<meta charset=““字符集””/>的影响
- Tomcat10.1默认使用UTF-8字符集对请求体进行解析
- 如果请求体的URL转码和Tomcat的请求体解析编码不一致,就容易出现乱码
POST请求方式乱码演示
- POST请求请求体受到了的影响
- 请求体中,将GBK数据进行URL编码
- tomcat10 默认UTF-8为请求体的解码字符集
POST请求方式乱码解决
-
方式1:请求时,使用UTF-8字符集提交请求体
-
-
方式2:后端获取参数前,设置解析请求体使用的字符集和请求发送时使用的字符集一致
10.1.3.3 响应乱码问题
响应乱码分析
- 在Tomcat10.1中,向响应体中放入的数据默认使用了工程编码UTF-8
- 浏览器在接收响应信息时,使用了不同的字符集或者是不支持中文的字符集就会出现乱码
演示
-
服务端通过response对象向响应体添加数据
-
浏览器接收数据解析乱码
响应乱码解决
- 方式1:手动设定浏览器对本次响应体解析时使用的字符集(不推荐) edge和chrome浏览器没有提供直接的比较方便的入口,不方便
- 方式2:后端通过设置响应体的字符集和浏览器解析响应体的默认字符集一致(不推荐)
- 方式3:通过设置content-type响应头,告诉浏览器以指定的字符集解析响应体(推荐)
10.2 路径问题
相对路径和绝对路径
-
相对路径
。相对路径的规则是:以当前资源所在的路径为出发点去寻找目标资源
。相对路径不以/开头
。在file协议下,使用的是磁盘路径
。在http协议下,使用的是url路径
。相对路径中可以使用./表示当前资源所在路径,可以省略不写
。相对路径中可以使用…/表示当前资源所在路径的上一层路径,需要时要手动添加
- 绝对路径
。绝对路径的规则是:使用以一个固定的路径做出出发点去寻找目标资源,和当前资源所在的路径没有关系。
。绝对路径要以/开头
。绝对路径的写法中,不以当前资源的所在路径为出发点,所以不会出现./和…/
。不同的项目和不同的协议下,绝对路径的基础位置可能不同,要通过测试确定
。绝对路径的好处就是:无论当前资源位置在哪,寻找目标资源路径的写法都一致
10.2.1 前段路径问题
前端项目结构
10.2.1.1 相对路径情况分析
相对路径情况1:web/index.html中引入web/static/img/logo.png
-
访问路径index.html中的url为:http://localhost:8080/demo2/index.html
-
当前资源为 :index.html
-
当前资源的所在路径为: http://localhost:8080/demo2/
-
要获取的目标资源url为:http://localhost:8080/demo2/static/img/logo.png
-
index.html中定义的 :< img src=“static/img/logo.png”/>
-
寻找方式就是在当前资源所在路径 (http://localhost:8080/demo2/)后拼接src属性值(static/img/logo.png),正好是目标资源正常获取的url(http://localhost:8080/demo2/static/img/logo.png)
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>Title</title> </head> <body> <!--引入图片1 相对路径以当前资源的所在路径为出发点去找目标资源语法: 不以/开头./表示当前资源的路径../表示当前资源的上一层路径2 绝对路径--><img src="static/img/logo.png"></body> </html>
相对路径情况2:web/page/a/test.html中引入web/static/img/logo.png
- 访问test.html的url为 : http://localhost:8080/demo2/page/a/test.html
- 当前资源为 : test.html
- 当前资源的所在路径为 : http://localhost:8080/demo2/page/a
- 要获取的目标资源url为 : http://localhost:8080/demo2/static/img/logo.png
- test.html中定义的了 :
<img src="../../static/img/logo.png"/>
- 寻找方式就是在当前资源所在路径(http://localhost:8080/demo2/page/a)后拼接src属性值(…/…/static/img/logo.png),其中 …/可以抵消一层路径,正好是目标资源正常获取的url(http://localhost:8080/demo2/static/img/logo.png)
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body><!-- ../代表上一层路径 --><img src="../../static/img/logo.png">
</body>
</html>
相对路径情况3:web/WEB-INF/views/view1.html中引入web/static/img/logo.png
- view1.html在WEB-INF下,需要通过Servlet请求转发获得
@WebServlet("/view1Servlet")
public class View1Servlet extends HttpServlet {@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {RequestDispatcher requestDispatcher = req.getRequestDispatcher("WEB-INF/views/view1.html");requestDispatcher.forward(req,resp);}
}
- 访问view1.html的url为 : http://localhost:8080/demo2/view1Servlet
- 当前资源为 : view1Servlet
- 当前资源的所在路径为 : http://localhost:8080/demo2/
- 要获取的目标资源url为 : http://localhost:8080/demo2/static/img/logo.png
- view1.html中定义的了 :
<img src="static/img/logo.png"/>
- 寻找方式就是在当前资源所在路径(http://localhost:8080/demo2/)后拼接src属性值(static/img/logo.png),正好是目标资源正常获取的url(http://localhost:8080/demo2/static/img/logo.png)
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body><img src="static/img/logo.png">
</body>
</html>
10.2.1.2 绝对路径情况分析
绝对路径情况1:web/index.html中引入web/static/img/logo.png
- 访问路径index.html的url为: http://localhost:8080/demo2/index.html
- 绝对路径的基准路径为:http://localhost:8080
- 要获取的目标资源url为:http://localhost:8080/demo2/static/img/logo.png
- index.html中定义的:< img src=“/demo2/static/img/logo.png” />
- 寻找方式就是在基准路径(http://localhost:8080)后面拼接src属性值(/demo2/static/img/logo.png),得到的正式目标资源访问的正确路径
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
<!--引入图片1 相对路径以当前资源的所在路径为出发点去找目标资源语法: 不以/开头./表示当前资源的路径../表示当前资源的上一层路径2 绝对路径--><img src="/demo2/static/img/logo.png"></body>
</html>
绝对路径情况2:web/page/a/test.html中引入web/static/img/log.png
- 访问路径index.html的url为: http://localhost:8080/demo2/page/a/test.html
- 绝对路径的基准路径为:http://localhost:8080
- 要获取的目标资源url为:http://localhost:8080/demo2/static/img/logo.png
- index.html中定义的:< img src=“/demo2/static/img/logo.png” />
- 寻找方式就是在基准路径(http://localhost:8080)后面拼接src属性值(/demo2/static/img/logo.png),得到的正式目标资源访问的正确路径
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
<img src="/demo2/static/img/logo.png"></body>
</html>
绝对路径情况3:webWEB-INF/views/view1.html中引入web/static/img/log.png
-
view1.html在WEB-INF下,需要通过Servlet请求转发获得
@WebServlet("/view1Servlet") public class View1Servlet extends HttpServlet {@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//请求转发到req.getRequestDispatcher("WEB-INF/views/view1.html").forward(req,resp);} }
-
访问view1.html的url为:http://localhost:8080/demo2/view1Servlet
-
绝对路径的基准路径为:http://localhost:8080
-
要获取的目标资源url为:http://localhost:8080/demo2/static/img/logo.png
-
view1.html中定义的: < img src=“/demo2/static/img/logo.png” />
-
寻找方式就是在基准路径(http://localhost:8080)后面拼接src属性值(/static/img/logo.png),得到的正是目标资源访问的正确路径
base标签的使用
base标签定义页面相对路径公共前缀
- base 标签定义在head标签中,用于定义相对路径的公共前缀
- base 标签定义的公共前缀只在相对路径上有效,绝对路径中无效
- 如果相对路径开头有 ./ 或者…/修饰,则base标签对该路径同样无效
index.html 和a/b/c/test.html 以及view1Servlet 中的路径处理
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title><!--定义相对路径的公共前缀,将相对路径转化成了绝对路径--><base href="/demo2/">
</head>
<body><img src="static/img/logo.png">
</body>
</html>
10.2.1.4 缺省项目上下文路径
项目上下文路径变化问题
- 通过 base标签虽然解决了相对路径转绝对路径问题,但是base中定义的是项目的上下文路径
- 项目的上下文路径是可以随意变化的
- 一旦项目的上下文路径发生变化,所有base标签中的路径都需要改
解决方案
- 将项目的上下文路径进行缺省设置,设置为 /,所有的绝对路径中就不必填写项目的上下文了,直接就是/开头即可
10.2.2 重定向中的路径问题
目标 :由/x/y/z/servletA重定向到a/b/c/test.html
@WebServlet("/x/y/z/servletA")
public class ServletA extends HttpServlet {@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {}
}
10.2.2.1相对路径写法
- 访问ServletA的url为 : http://localhost:8080/demo2/x/y/z/servletA
- 当前资源为 : servletA
- 当前资源的所在路径为 : http://localhost:8080/demo2/x/x/z/
- 要获取的目标资源url为 : http://localhost:8080/demo2/a/b/c/test.html
- ServletA重定向的路径 : …/…/…/a/b/c/test/html
- 寻找方式就是在当前资源所在路径(http://localhost:8080/demo2/x/y/z/)后拼接(…/…/…/a/b/c/test/html),形成(http://localhost:8080/demo2/x/y/z/…/…/…/a/b/c/test/html)每个…/抵消一层目录,正好是目标资源正常获取的url(http://localhost:8080/demo2/a/b/c/test/html)
@WebServlet("/x/y/z/servletA")
public class ServletA extends HttpServlet {@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// 相对路径重定向到test.htmlresp.sendRedirect("../../../a/b/c/test.html");}
}
10.2.2.2绝对路径写法
-
访问ServletA的url为 : http://localhost:8080/demo2/x/y/z/servletA
-
绝对路径的基准路径为 : http://localhost:8080
-
要获取的目标资源url为 : http://localhost:8080/demo2/a/b/c/test.html
-
ServletA重定向的路径 : /demo2/a/b/c/test.html
-
寻找方式就是在基准路径(http://localhost:8080)后面拼接(/demo2/a/b/c/test.html),得到( http://localhost:8080/demo2/a/b/c/test.html)正是目标资源访问的正确路径
-
绝对路径中需要填写项目上下文路径,但是上下文路径是变换的
- 可以通过 ServletContext的getContextPath()获取上下文路径
- 可以将项目上下文路径定义为 / 缺省路径,那么路径中直接以/开头即可
//绝对路径中,要写项目上下文路径 //resp.sendRedirect("/demo2/a/b/c/test.html"); // 通过ServletContext对象动态获取项目上下文路径 //resp.sendRedirect(getServletContext().getContextPath()+"/a/b/c/test.html"); // 缺省项目上下文路径时,直接以/开头即可 resp.sendRedirect("/a/b/c/test.html");
10.2.3 请求转发中的路径问题
目标 :由x/y/servletB请求转发到a/b/c/test.html
@WebServlet("/x/y/servletB")
public class ServletB extends HttpServlet {@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {}
}
10.2.3.1 相对路径写法
-
访问ServletB的url为 : http://localhost:8080/demo2/x/y/servletB
-
当前资源为 : servletB
-
当前资源的所在路径为 : http://localhost:8080/demo2/x/x/
-
要获取的目标资源url为 : http://localhost:8080/demo2/a/b/c/test.html
-
ServletA请求转发路径 : …/…/a/b/c/test/html
-
寻找方式就是在当前资源所在路径(http://localhost:8080/demo2/x/y/)后拼接(…/…/a/b/c/test/html),形成(http://localhost:8080/demo2/x/y/…/…/a/b/c/test/html)每个…/抵消一层目录,正好是目标资源正常获取的url(http://localhost:8080/demo2/a/b/c/test/html)
@WebServlet("/x/y/servletB") public class ServletB extends HttpServlet {@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {RequestDispatcher requestDispatcher = req.getRequestDispatcher("../../a/b/c/test.html");requestDispatcher.forward(req,resp);} }
10.2.3.2绝对路径写法
-
请求转发只能转发到项目内部的资源,其绝对路径无需添加项目上下文路径
-
请求转发绝对路径的基准路径相当于http://localhost:8080/demo2
-
在项目上下文路径为缺省值时,也无需改变,直接以/开头即可
@WebServlet("/x/y/servletB") public class ServletB extends HttpServlet {@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {RequestDispatcher requestDispatcher = req.getRequestDispatcher("/a/b/c/test.html");requestDispatcher.forward(req,resp);} }
10.2.3.3目标资源内相对路径处理
-
此时需要注意,请求转发是服务器行为,浏览器不知道,地址栏不变化,相当于我们访问test.html的路径为http://localhost:8080/demo2/x/y/servletB
-
那么此时 test.html资源的所在路径就是http://localhost:8080/demo2/x/y/所以test.html中相对路径要基于该路径编写,如果使用绝对路径则不用考虑
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>Title</title> </head> <body><!--当前资源路径是 http://localhost:8080/demo2/x/y/servletB当前资源所在路径是 http://localhost:8080/demo2/x/y/目标资源路径=所在资源路径+src属性值 http://localhost:8080/demo2/x/y/../../static/img/logo.pnghttp://localhost:8080/demo2/static/img/logo.png得到目标路径正是目标资源的访问路径 --> <img src="../../static/img/logo.png"> </body> </html>
MVC架构模式
MVC(Model View Controller)是软件工程中的一种**
软件架构模式
,它把软件系统分为模型
、视图
和控制器
**三个基本部分。用一种业务逻辑、数据、界面显示分离的方法组织代码,将业务逻辑聚集到一个部件里面,在改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑。
-
M:Model 模型层,具体功能如下
- 存放和数据库对象的实体类以及一些用于存储非数据库表完整相关的VO对象
- 存放一些对数据进行逻辑运算操作的的一些业务处理代码
-
V:View 视图层,具体功能如下
- 存放一些视图文件相关的代码 html css js等
- 在前后端分离的项目中,后端已经没有视图文件,该层次已经衍化成独立的前端项目
-
C:Controller 控制层,具体功能如下
- 接收客户端请求,获得请求数据
- 将准备好的数据响应给客户端
MVC模式下,项目中的常见包
-
M:
- 实体类包(pojo /entity /bean) 专门存放和数据库对应的实体类和一些VO对象
- 数据库访问包(dao/mapper) 专门存放对数据库不同表格CURD方法封装的一些类
- 服务包(service) 专门存放对数据进行业务逻辑运算的一些类
-
C:
- 控制层包(controller)
-
V:
- web目录下的视图资源 html css js img 等
- 前端工程化后,在后端项目中已经不存在了
非前后端分离的MVC
前后端分离的MVC
相关文章:
JAVAWeb中的Servlet学习
一 Servlet简介 1.1动态资源和静态资源 静态资源 无需在程序运行时通过代码运行生成的资源,在程序运行之前就写好的资源.例如:html css js img ,音频文件和视频文件 动态资源 需要在程序运行时通过代码运行生成的资源,在程序运行之前无法确定的数据,运行时动态生成,例如Servle…...
【Linux】多线程
目录 线程 线程和进程的关系 虚拟地址与物理地址的映射(三级映射) 编辑 线程的使用 线程安全 临界资源和临界区 互斥锁 同步与互斥 互斥锁的使用 锁的初始化 加锁与解锁 信号量 信号与信号量的区别 信号量的使用 Lock_guard与unique_lock …...
如何使用Python库连接Redis
1、redis-py 库封装一个 Redis 工具类可以帮助我们简化 Redis 的操作并提高代码的复用性和可维护性。 安装redis pip install redisimport redis import logginglogging.basicConfig(levellogging.INFO) logger logging.getLogger(__name__)class RedisUtils:def __init__(s…...
mybatis一对多的查询怎么查?
1.问题描述 我有一个班级,班级里有很多学生,我需要一个查询把班级和学生信息查出来,怎么查? 这里有个问题,就是我班级的命名和学生的命名可能重了。 例如: class Gradle{ private String id; private …...
[C++]友元函数和友元类
1. 友元函数 1.1 友元函数的概念 友元函数是一个非成员函数,它被类声明为“友元”,从而能够访问类的私有成员和保护成员。正常情况下,类的外部函数是不能访问类的私有成员的,而友元函数打破了这一限制。 class MyClass { priva…...
实战:MyBatis适配多种数据库:MySQL、Oracle、PostGresql等
概叙 很多时候,一套代码要适配多种数据库,主流的三种库:MySQL、Oracle、PostGresql,刚好mybatis支持这种扩展,如下图所示,在一个“namespace”,判断唯一的标志是iddatabaseId,刚好写…...
2024年天津市职业院校技能大赛高职组 “信息安全管理与评估”样题第三阶段
(四)第三阶段竞小组(赛项)目(300分) 第三阶段竞赛内容是:网络安全渗透(夺旗挑战赛CTF) 本模块要求参赛者作为攻击方,运用所学的信息收集、漏洞发现、漏洞利用等渗透测试技…...
游戏引擎学习第36天
仓库 :https://gitee.com/mrxiao_com/2d_game 回顾之前的内容 在这个程序中,目标是通过手动编写代码来从头开始制作一个完整的游戏。整个过程不使用任何库或现成的游戏引擎,这样做的目的是为了能够全面了解游戏执行的每一个细节。开发过程中࿰…...
数仓技术hive与oracle对比(一)
准备 包括软硬件环境、数据、测试数据三方面的准备内容。 环境 虚拟机软件virtualbox7,同样的虚拟机配置:内存2G、cpu一核,物理主机同一台macbookpro(13-2020款),所以硬盘IO读写速度一致。 综上&#x…...
LeetCode题集-5 - 最长回文子串(一)
题目:给你一个字符串 s,找到 s 中最长的回文子串。 这一题作为中等难度,常规解法对于大多数人应该都没有难度。但是其中也有超难的解决办法,下面我们就一起由易到难,循序渐进地来解这道题。 01、暴力破解法 对于大多…...
A3026 Java+jsp+servlet+mysql高校学生请假管理系统
高校学生请假管理系统 1.摘要2. 绪论3.功能结构4.界面展示5.源码获取 1.摘要 高校学生请假管理系统 摘要:随着计算机的发展与不断进步,各个领域都出现了新的技术,曾经各种规模之间的竞争已经发展成为技术之间的竞争,管理和人才之…...
LDO低压差线性稳压器
1. 简介 LDO 是 “Low Dropout Regulator” 的缩写,中文称为“低压差线性稳压器”。LDO 稳压器是一种用于电压调节的电子设备,它的主要特点是输出电压和输入电压之间的压差非常低。这种特性使得 LDO 在许多应用场景中非常有用,特别是在需要高…...
Angular由一个bug说起之十一:排序之后无法展开 Row
问题现象 在使用 Material Table 时,排序功能触发了一个奇怪的 Bug:表格的 Row 无法展开。最终排查发现,问题的根源在于 trackBy 的错误使用。trackBy 方法接受两个参数:index(数据索引)和 row(…...
wlanapi.dll丢失怎么办?有没有什么靠谱的修复wlanapi.dll方法
在遇到各种系统文件错误当中,其中之一就是“wlanapi.dll文件丢失”的问题。这种问题通常发生在Windows操作系统上,特别是当系统试图执行与无线网络相关的任务时。wlanapi.dll是一个重要的系统文件,它负责处理Windows无线网络服务的许多功能。…...
redis安装和使用教程【保姆级】
1.下载 通过网盘分享的文件:redis 链接: https://pan.baidu.com/s/1Tu1KZkf33YJFdul8s6SzqQ?pwd8888 提取码: 8888 2.启动 进入根目录,使用redis-server redis.windows.conf命令启行启动Redis服务, 如下图所示为启动成功,默认…...
Github 2024-12-01 开源项目月报 Top20
根据Github Trendings的统计,本月(2024-12-01统计)共有20个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Python项目10TypeScript项目9Go项目2HTML项目1Shell项目1Jupyter Notebook项目1屏幕截图转代码应用 创建周期:114 天开发语言:TypeScript, Py…...
C总结(C语言知识点,深化重难点)
C语言 1.使用C语言的7个步骤2.ASCII码3.提高程序可读性的机巧4.如何使用多种整形5.打印多种整形6.课移植类型:stdint.h和inttypes.h7.浮点数常量8.浮点值的上溢和下溢9.使用数据类型11.常量和C预处理器12.转换说明的意义12.1转换不匹配13.副作用和序列点14.数组简介…...
[Collection与数据结构] 位图与布隆过滤器
🌸个人主页:https://blog.csdn.net/2301_80050796?spm1000.2115.3001.5343 🏵️热门专栏: 🧊 Java基本语法(97平均质量分)https://blog.csdn.net/2301_80050796/category_12615970.html?spm1001.2014.3001.5482 🍕 Collection与…...
Redis与缓存
目录 缓存 缓存优缺点 缓存更新策略 超时剔除 先删缓存再更新数据库 旁路缓存(先更新数据库,再删缓存) 先更新数据库,再更新缓存 读写穿透 编辑 异步缓存写入模式 缓存常见问题 缓存穿透 缓存雪崩 缓存击穿 缓存 在业务开发…...
Ubuntu Linux 文件、目录权限问题(五)
本文为Ubuntu Linux操作系统- 第五弹 此文是在上期文件目录的内容操作基础上接着讲权限问题 上期回顾:Ubuntu Linux 目录和文件的内容操作 文件访问者身份与文件访问权限 Linux文件结构 所有者(属主)所属组(属组)其他…...
AI 名人堂:Jeff Dean
Jeff Dean,谷歌的高级研究员和人工智能领域的领军人物,以其在大规模分布式计算系统和人工智能系统的杰出贡献而闻名。 谷歌AI掌门人 TensorFlow项目负责人 美国工程院院士 2AGI.NET AI 名人堂 AI 名人堂:Jeff DeanAI 名人堂:Je…...
基础排序算法详解:冒泡排序、选择排序与插入排序
引言 上一章,我们聊到了排序的基本概念和常见算法的分类。这一次,我们从基础开始,深入剖析三种常见的O(n) 排序算法:冒泡排序、选择排序 和 插入排序。 它们是学习排序算法的入门神器,不仅实现简单,还能帮…...
Flink如何基于数据版本使用最新离线数据
业务场景 假设批量有一张商户表,表字段中有商户名称和商户分类两个字段。 批量需要将最新的商户名称和分类的映射关系推到hbase供实时使用。 原实现方案 a.原方案内容 为解决批量晚批问题,批量推送hbase表时一份数据产生两类rowkey:T-1和…...
什么是反向代理?作用、原理和实例详解
🚀 什么是反向代理?作用、原理和实例详解 在现代的网络架构中,反向代理(Reverse Proxy)无处不在。无论是负载均衡、加速缓存,还是WebSocket 支持,反向代理都是必不可少的工具。 这篇文章将带您…...
国产GPU中,VLLM0.5.0发布Qwen2.5-14B-Instruct-GPTQ-Int8模型,请求返回结果乱码
概述 国产GPU: DCU Z100 推理框架: vllm0.5.0 docker容器化部署 运行如下代码: python -m vllm.entrypoints.openai.api_server --model /app/models/Qwen2.5-14B-Instruct-GPTQ-Int8 --served-model-name qwen-gptq --trust-remote-code --enforce…...
Stable Diffusion本地部署:从零开始的完整指南
1、引言 Stable Diffusion是计算机视觉领域的一个生成式大模型,能够进行文生图(txt2img)和图生图(img2img)等图像生成任务。它利用深度学习技术,特别是RealisticVision v2.0模型,能够创造出接近…...
隐式神经网络实现低光照图像增强
✨✨ 欢迎大家来访Srlua的博文(づ ̄3 ̄)づ╭❤~✨✨ 🌟🌟 欢迎各位亲爱的读者,感谢你们抽出宝贵的时间来阅读我的文章。 我是Srlua小谢,在这里我会分享我的知识和经验。&am…...
Flutter动画(三)内建显式动画Widget
常见的内建显式动画Widget: ListenableBuilder: AnimatedBuilder AnimatedWidget AlignTransition DecoratedBoxTransition DefaultTextStyleTransition PositionedTransition RelativePositionedTransition RotationTransition ScaleTransiti…...
springSecurity自定义登陆接口和JWT认证过滤器
下面我会根据该流程图去自定义接口: 我们需要做的任务有: 登陆:1、通过ProviderManager的方法进行认证,生成jwt;2、把用户信息存入redis;3、自定义UserDetailsService实现到数据库查询数据的方法。 校验&a…...
Spring Boot日志:从Logger到@Slf4j的探秘
写在前面 Hello大家好,今日是2024年的第一天,祝大家元旦快乐?? 2024第一篇文章从SpringBoot日志开始 文章目录 一、前言二、日志有什么用?三、日志怎么用?四、自定义日志打印 ?? 常见日志框架说明4.1 在程序中得到?志对象【…...
使用 LabVIEW 与 PLC 通信的方式
要将 PLC 与 LabVIEW 或其他 NI 产品进行通信,首先需要明确 PLC 支持的通信协议和接口类型。NI 提供了多种方案,包括 OPC 服务器、Modbus、Ethernet/IP 和其他工业通信协议。下面将详细介绍这些方法,并进行比较分析,帮助你选择最适…...
python录制鼠标键盘操作循环播放
依赖 pip install pynput 程序: from pynput import mouse, keyboard import time import threading# 用于存储录制的鼠标和键盘事件 mouse_events [] keyboard_events []# 定义事件处理函数# 处理鼠标事件 def on_move(x, y):mouse_events.append((move, x, y))def on_cl…...
开发者如何使用GCC提升开发效率Opencv操作
看此篇前请先阅读 https://blog.csdn.net/qq_20330595/article/details/144134160?spm=1001.2014.3001.5502 https://blog.csdn.net/qq_20330595/article/details/144134160?spm=1001.2014.3001.5502 https://blog.csdn.net/qq_20330595/article/details/144216351?spm=1001…...
异常与文件
目录 1.异常 1.1.概念 1.2.常见异常 1.3.异常处理方式 1.3.1.try except 1.3.2.try except else 1.3.3.try except else finally 2.文件 2.1.文件分类 ps:python 程序的数据保存在哪里? 2.2.常见的文件类型 2.3.python 操作文件的函数 2.3.1.读取文件…...
【C语言】完成程序设计填空
文章目录 1、请阅读下面的程序,在空白处填写正确的代码,要求各在一行从头开始输出m和n的值。2、求100~599之间的所有水仙花数,即各位数字的立方和恰好等于该数本身的数。3、以下程序的功能是:将值为三位正整数的变量x中的数值按照个位、十位、百位的顺序 拆分并输出。请填空…...
西湖大学:LLM零样本推理任务校准
📖标题:Task Calibration: Calibrating Large Language Models on Inference Tasks 🌐来源:arXiv, 2410.18764 🌟摘要 🔸大型语言模型(LLM)在推理任务上表现出令人印象深刻的零样本…...
windows下Qt5自动编译配置QtMqtt环境(11)
文章目录 [toc]1、概述2、准备1.1 下载源码1.2 配置环境1.3 解释原理 3、编译4、验证5、参考6、视频 更多精彩内容👉内容导航 👈👉Qt网络编程 👈 1、概述 Qt默认是不包含mqtt库的,如果需要使用到mqtt库就只能自己编译配…...
每天五分钟深度学习:神经网络的前向传播的计算(多样本)
本文重点 前面我们学习了单样本的前向传播,本文我们学习多样本的前向传播,我们先来回忆一下,神经网络的单样本的前向传播的向量化的方式: m个样本依次进行前向传播 这里我们说明一下符号: 我们使用(m)表示第m个样本,用[m]表示神经网络的第m层 a[2](i) 表示第i个样本计…...
基于 NXP S32K312+FS23 的汽车通用评估板方案
S32K3 系列是 NXP 推出的面向汽车电子和工业应用的微控制器,基于 ARMCortex-M7 内核,支持单核、双核和锁步内核配置。S32K3 系列具有内核、内存和外设数量方面的可扩展性,符合 ISO26262 标准,能达到 ASIL B/D 安全等级,…...
11进阶篇:专业课论文阅读方向指南(2025版)
文章目录 第一个检索式:图情档核心期刊(北大 + CSSCI)发文情况研究方法类关键词研究主题类关键词论文阅读建议第二个检索式:川大公共管理学院在核心期刊(北大 + CSSCI)的发文情况研究方法类关键词研究主题类关键词特点关键词与2024年972(现815)两道题目的映射情况815信…...
Qt之第三方库QXlsx使用(三)
Qt开发 系列文章 - QXlsx(三) 目录 前言 一、Qt开源库 二、QXlsx 1.QXlsx介绍 2.QXlsx下载 3.QXlsx移植 4.修改项目文件.pro 三、使用技巧 1.写入数据 2.读出数据 总结 前言 Qt第三方控件库是指非Qt官方提供的、用于扩展Qt应用程序功能的控件…...
第145场双周赛: 使数组的值全部为 K 的最少操作次数、破解锁的最少时间 Ⅰ、使两个整数相等的位数操作、统计最小公倍数图中的连通块数目
Q1、使数组的值全部为 K 的最少操作次数 1、题目描述 给你一个整数数组 nums 和一个整数 k 。 如果一个数组中所有 严格大于 h 的整数值都 相等 ,那么我们称整数 h 是 合法的 。 比方说,如果 nums [10, 8, 10, 8] ,那么 h 9 是一个 合法…...
AJAX三、XHR,基本使用,查询参数,数据提交,promise的三种状态,封装-简易axios-获取省份列表 / 获取地区列表 / 注册用户,天气预报
一、XMLHttpRequest基本使用 XMLHttpRequest(XHR)对象用于与服务器交互。 二、XMLHttpRequest-查询参数 语法: 用 & 符号分隔的键/值对列表 三、XMLHttpRequest-数据提交 核心步骤 : 1. 请求头 设置 Content-Type 2. 请求体 携带 符合要求 的数…...
Android期末复习题
1.如何搭建Android开发环境? 答案:搭建Android开发环境需要以下几个步骤: (1)下载和安装JDK (2)配置PATH环境变量 (3)下载和安装Android Studio (4)创建A…...
《蓝桥杯比赛规划》
一、比赛简介 蓝桥杯全国软件和信息技术专业人才大赛是一项具有较高影响力的编程竞赛,旨在促进软件和信息技术领域专业技术人才的培养,提升高校毕业生的就业竞争力。比赛涵盖了多个编程语言和专业方向,包括 C/C、Java、Python 等。 二、目标…...
三、Zookeeper
Zookeeper 三、Zookeeper3.1什么是zookeeper?3.2为什么需要zookeeper3.3Zookeeper基本运行流程3.4Zookeeper数据模型3.5Zookeeper主要角色3.6Zookeeper工作原理3.7Zookeeper节点数据操作流程三、Zookeeper 3.1什么是zookeeper? ZooKeeper是一个分布式的,开放源码的分布式应…...
Wireshark数据抓包分析之传输层协议(TCP协议)
根据实验环境,本实验的步骤如下: 1.在测试环境使用发包工具和Wireshark抓取TCP三次握手和四次断开的数据包。 2.详细分析TCP协议的三次握手以及四次断开。 任务描述:安装发包工具,并配置TCP客户端,服务端࿰…...
用ai做机器视觉的事情
cnn(卷积神经网络)是典型的ai算法。 我们已经cnn实现像机器视觉中形状匹配的功能,因为使用了roi抠图匹配,所以就叫做roicnn,以区分整图匹配。下面是roicnn笔记总结: 20241022,roicnn搞定&…...
LLM - 开源视觉多模态 LLaVA-CoT(o1) 深度推理模型 测试与源码 教程
欢迎关注我的CSDN:https://spike.blog.csdn.net/ 本文地址:https://spike.blog.csdn.net/article/details/144304351 免责声明:本文来源于个人知识与公开资料,仅用于学术交流,欢迎讨论,不支持转载。 LLaVA-…...
qtcanpool 知 10:包管理雏形
文章目录 前言痛点转机雏形实践后语 前言 曾听闻:C/Qt 没有包管理器,开发起来太不方便。这是一个有过 node.js 开发经验的人对 Qt 的吐槽。 确实,像 python、golang、node.js 这些编程语言都有包管理器,给用户带来了极佳的开发体…...