当前位置: 首页 > news >正文

Servlet 与 MVC

主要内容

  • Servlet 重点

  • MVC 重点

  • Filter 重点

章节目标

  • 掌握 Servlet 的作用

  • 掌握 Servlet 的生命周期

  • 掌握 JSP 的本质

  • 掌握 MVC 的设计思想

  • 掌握 Filter 的作用及使用场景

第一节 Servlet

1. Servlet 概念

Servlet 是在服务器上运行的能够对客户端请求进行处理,并返回处理结果的程序

2. Servlet 体系结构

2.1 Servlet 接口
//Servlet对象的初始化,Servlet 对象初始化后才能处理请求,由 Servlet 容器调用
public void init(ServletConfig config) throws ServletException;
//获取Servlet配置信息
public ServletConfig getServletConfig();
//处理客户端的请求,由 Servlet 容器调用
public void service(ServletRequest req, ServletResponse res)throws ServletException, IOException;
//返回有关 Servlet 的信息,比如作者、版本和版权
public String getServletInfo();
//销毁Servlet,由 Servlet 容器调用
public void destroy();
2.2 ServletConfig 接口
//获取Servlet的实例名称
public String getServletName();
//返回正在执行的Servlet所在的上下文对象
public ServletContext getServletContext();
//获取Servlet中给定名称的初始化参数
public String getInitParameter(String name);
//获取Servlet中所有的初始化参数
public Enumeration<String> getInitParameterNames();
2.3 Servlet 案例
  • 编写Servlet

    package com.qf.jsp.servlet;import javax.servlet.*;
    import java.io.IOException;
    import java.util.Enumeration;public class LoginServlet implements Servlet {private ServletConfig servletConfig;@Overridepublic void init(ServletConfig config) throws ServletException {this.servletConfig = config;String servletName = config.getServletName();System.out.println("Servlet 实例的名称:" + servletName);//获取Servlet中所有的初始化参数Enumeration<String> initParameterNames = config.getInitParameterNames();while (initParameterNames.hasMoreElements()) {String initParameterName = initParameterNames.nextElement();//获取Servlet中给定名称的初始化参数String initParameterValue = config.getInitParameter(initParameterName);System.out.println("Servlet 初始化参数 " + initParameterName + ":" + initParameterValue);}}@Overridepublic ServletConfig getServletConfig() {return servletConfig;}@Overridepublic void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {System.out.println("Servlet 处理请求");}@Overridepublic String getServletInfo() {return "Login Servlet";}@Overridepublic void destroy() {System.out.println("Servlet 销毁");}
    }
  • 配置 web.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaeehttp://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"version="4.0"><display-name>ServletApp</display-name><!--Servlet 实例配置--><servlet><!-- Servlet 实例的名称--><servlet-name>loginServlet</servlet-name><!--Servlet 的类型--><servlet-class>com.qf.jsp.servlet.LoginServlet</servlet-class><init-param><!--初始化参数的名称--><param-name>characterEncoding</param-name><!--初始化参数的值--><param-value>UTF-8</param-value></init-param></servlet><!--Servlet 实例与请求地址的映射配置--><servlet-mapping><!-- Servlet 实例的名称--><servlet-name>loginServlet</servlet-name><!-- Servlet 匹配的请求地址--><url-pattern>/login</url-pattern></servlet-mapping><!--session 配置--><session-config><!--超时时间配置--><session-timeout>30</session-timeout></session-config>
    </web-app>
  • 获取初始化参数信息

    @Override
    public void init(ServletConfig config) throws ServletException {this.servletConfig = config;String servletName = config.getServletName();System.out.println("Servlet 实例的名称:" + servletName);//获取Servlet中所有的初始化参数Enumeration<String> initParameterNames = config.getInitParameterNames();while (initParameterNames.hasMoreElements()){String initParameterName = initParameterNames.nextElement();//获取Servlet中给定名称的初始化参数String initParameterValue = config.getInitParameter(initParameterName);System.out.println("Servlet 初始化参数 " + initParameterName + ":" + initParameterValue);}
    }
  • 编写 index.jsp

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <!DOCTYPE HTML>
    <html><head><title>登录页面</title></head><body><form action="login" method="post"><div><input type="text" name="username"></div><div><input type="password" name="password"></div><div><input type="submit" value="登录"></div></form></body>
    </html>
  • 启动服务器,进行登录操作,查看控制台信息

控制台打印信息中并没有打印 "Servlet 销毁" 信息,由此可以得出:Servlet 处理完了请求后,并没有销毁。

  • 关闭服务器,查看控制台信息

由此可以得出:在 Tomcat 关闭之前,Servlet 被销毁

  • 结论

Servlet 在第一次接收请求时,由容器(如 Tomcat)创建实例,紧接着就由容器调用该 Servlet 的 init 方法完成初始化,然后由容器调用该 Servlet 的 service 方法进行请求处理,请求处理完成后,Servlet 并不会消亡, 而是跟随容器共存亡,在容器关闭之前,由容器调用 Servlet 的 destroy方法进行销毁

  • JSP 本质

package org.apache.jsp;import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;public final class index_jsp extends org.apache.jasper.runtime.HttpJspBaseimplements org.apache.jasper.runtime.JspSourceDependent,org.apache.jasper.runtime.JspSourceImports {
}

由此可以得出:JSP 的本质就是Servlet,只是 JSP 注重的是页面内容的展示,而Servlet注重的是业务逻辑的处理。

3. 请求处理与响应

3.1 体系结构

3.2 请求接口
  • ServletRequest 接口常用方法

//从请求中获取给定属性名对应的属性值
Object getAttribute(String attributeName);
//将给定的属性值以给定的属性名存储在请求中
void setAttribute(String attributeName, Object attributeVaue);
//从请求中将给定的属性名移除
void removeAttribute(String attributeName);
//获取请求中存储的所有属性名
Enumeration<String> getAttributeNames();
//从请求中获取给定参数名对应的参数值(参数值是单个数据)
String getParameter(String parameterName);
//从请求中获取给定参数名对应的参数值(参数值是多个数据)
String[] getParameterValues(String parameterName);
//从请求中获取所有的参数名
Enumeration<String> getParameterNames();
//从请求中获取所有的参数名和参数值形成的映射
Map<String, String[]> getParameterMap();
//从请求中获取字符集编码
String getCharacterEncoding();
//设置请求的字符集编码
void setCharacterEncoding(String charset) throws UnsupportedEncodingException;
//从请求中获取字符流,该字符流只能读取请求体中的数据信息,与下面的 getInputStream 方法只能二选一
BufferedReader getReader() throws IOException;
//从请求中获取字节流,该字节流只能读取请求体中的数据信息
ServletInputStream getInputStream() throws IOException;
//从请求中获取当前Servlet所在的上下文对象
ServletContext getServletContext();
//从请求中获取请求转发的对象
RequestDispatcher getRequestDispatcher(String path);
  • 用法

@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {System.out.println("请求的字符集编码需要在读取请求信息之前进行设置,否则,设置的字符集编码格式将不生效");System.out.println("请求字符集编码:" + servletRequest.getCharacterEncoding());servletRequest.setCharacterEncoding("UTF-8");System.out.println("请求字符集编码:" + servletRequest.getCharacterEncoding());BufferedReader reader = servletRequest.getReader();System.out.println("开始读取请求参数信息");String line;while ((line = reader.readLine()) != null){System.out.println(line);}System.out.println("请求参数信息读取完毕");System.out.println("================");System.out.println("开始获取请求中存储的数据");Enumeration<String> attributeNames = servletRequest.getAttributeNames();while (attributeNames.hasMoreElements()){String attributeName = attributeNames.nextElement();Object attributeValue = servletRequest.getAttribute(attributeName);System.out.println(attributeName + " => " + attributeValue);}System.out.println("请求中存储的数据获取完毕");System.out.println("================");System.out.println("方式一:开始获取请求参数信息");Enumeration<String> parameterNames = servletRequest.getParameterNames();while (parameterNames.hasMoreElements()){String parameterName = parameterNames.nextElement();String parameterValue = servletRequest.getParameter(parameterName);System.out.println(parameterName + " => " + parameterValue);}System.out.println("方式一:请求参数信息获取完毕");System.out.println("================");System.out.println("方式二:开始获取请求参数信息");Map<String, String[]> parameterMap = servletRequest.getParameterMap();parameterMap.forEach((k, values) -> System.out.println(k + " => " + Arrays.toString(values)));System.out.println("方式二:请求参数信息获取完毕");System.out.println("请求所使用的上下文路径:" + servletRequest.getServletContext().getContextPath());
}
  • POST请求测试

  • GET 请求测试

  • 结论

使用GET方式发送的请求,只能通过getParameter 方法获取;使用POST方式发送的请求,只能使用流来获取。这是因为使用GET方式发送的请求,参数在URL地址中,解析这些参数的时候将其存放在一个Map集合中,因此可以直接获取。而POS方式发送的请求,参数在请求体中,这部分内容只能通过流来读取,然后再进行处理。

3.3 响应接口
  • ServletResponse 接口常用方法

//获取响应的字符集编码
String getCharacterEncoding();
//设置响应的字符集编码
void setCharacterEncoding(String charset);
//获取响应的内容类型
String getContentType();
//设置响应的内容类型
void setContentType(String contentType);
//获取输出流,主要用于下载文件
ServletOutputStream getOutputStream() throws IOException;
//获取打印流,主要用于向页面传输信息
PrintWriter getWriter() throws IOException;
  • 用法(在 service 方法最后追加如下代码)

System.out.println();
System.out.println();
System.out.println("===========================================");
System.out.println("响应的字符集编码:" + servletResponse.getCharacterEncoding());
servletResponse.setCharacterEncoding("UTF-8");
System.out.println("响应的字符集编码:" + servletResponse.getCharacterEncoding());
System.out.println("响应的内容类型:" + servletResponse.getContentType());
servletResponse.setContentType("text/html;charset=utf-8");
System.out.println("响应的内容类型:" + servletResponse.getContentType());
PrintWriter writer = servletResponse.getWriter();
writer.print("登录请求已处理");
writer.flush();
writer.close();
  • 测试

3.4 HTTP 请求和响应
  • HttpServletRequest 接口常用方法

    //从请求中获取Cookie信息
    Cookie[] getCookies();
    //从请求中获取给定请求头名称对应的属性值
    String getHeader(String headerName);
    //从请求中获取所有的请求头名称
    Enumeration<String> getHeaderNames();
    //获取请求的方式:GET、POST、PUT、DELETE等
    String getMethod();
    //从请求中获取上下文路径
    String getContextPath();
    //从请求中获取session
    HttpSession getSession();
    //获取请求地址
    String getRequestURI();
  • HttpServletResponse 接口常用方法

//添加客户端存储的Cookie信息
void addCookie(Cookie cookie);
//返回错误状态及错误信息
void sendError(int status, String errorMsg) throws IOException;
//返回错误状态
void sendError(int status) throws IOException;
//重定向至新的资源
void sendRedirect(String redirectURL) throws IOException;
//设置响应头信息
void setHeader(String headerName, String headerValue);
//添加响应头信息
void addHeader(String headerName, String headerValue);
//设置响应状态
void setStatus(int status);
  • HttpServlet常用方法(支持 HTTP 协议的 Servlet)

//对父类抽象方法的实现,该方法是对HTTP协议的交互信息的实现,调用的是下面的 service 方法
void service(ServletRequest req,ServletResponse res);
//HTTP协议的交互信息的实现,该方法主要针对不同的请求方式进行处理。GET请求会调用 doGet 方法处理,
//POST请求会调用 doPost 处理, PUT请求会调用 doPut 方法处理, DELETE请求会调用 doDelete 方法处理 
void service(HttpServletRequest  req, HttpServletResponseres);
//GET请求处理
void doGet(HttpServletRequestreq,HttpServletResponse res);
//POST请求处理
void doPost(HttpServletRequestreq,HttpServletResponse res);
//PUT请求处理
void doPut(HttpServletRequestreq,HttpServletResponse res);
//DELETE请求处理
void doDelete(HttpServletRequestreq,HttpServletResponse res);
  • 用法

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.Map;public class RegisterServlet extends HttpServlet {@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {System.out.println("开始获取请求头信息");Enumeration<String> headerNames = req.getHeaderNames();while (headerNames.hasMoreElements()){String headerName = headerNames.nextElement();String headerValue = req.getHeader(headerName);System.out.println(headerName + " => " + headerValue);}System.out.println("请求头信息获取完毕");System.out.println("请求方式:" + req.getMethod());System.out.println("请求地址:" + req.getRequestURI());System.out.println("请求的上下文路径:" + req.getContextPath());System.out.println("==================");System.out.println("开始读取请求参数");Map<String, String[]> parameterMap = req.getParameterMap();parameterMap.forEach((k, values) -> System.out.println(k + "=>" + Arrays.toString(values)));System.out.println("请求参数读取完毕");System.out.println();System.out.println();System.out.println("=========================");System.out.println("响应开始");resp.setContentType("text/html;charset=utf-8");PrintWriter writer = resp.getWriter();writer.print("注册请求已经处理");writer.flush();writer.close();}
}
<!-- register.jsp -->
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE HTML>
<html><head><title>注册页面</title></head><body><form action="createUser" method="post"><div><input type="text" name="username"></div><div><input type="password" name="password"></div><div><input type="submit" value="注册"></div></form></body>
</html>
<!-- web.xml 中添加如下配置 -->
<servlet><servlet-name>registerServlet</servlet-name><servlet-class>com.qf.jsp.servlet.RegisterServlet</servlet-class>
</servlet><servlet-mapping><servlet-name>registerServlet</servlet-name><url-pattern>/createUser</url-pattern>
</servlet-mapping>
  • 测试

查看控制台信息

3.5 Servlet 交互流程

4. ServletContext

4.1 常用方法
//获取上下文路径
String getContextPath();
//获取给定相对路径对应的绝对路径
String getRealPath(String path);
//获取上下文初始化参数中给定参数名对应的参数值
String getInitParameter(String parameterName);
//获取上下文初始化参数中所有的参数名
Enumeration<String> getInitParameterNames();
//获取上下文存储的数据中给定属性名对应的属性值
Object getAttribute(String attributeName);
//获取上下文存储的数据中所有的属性名
Enumeration<String> getAttributeNames();
//将给定的属性值使用给定的属性名存储在上下文中
void setAttribute(String attributeName, Object attributeValue);
//从上下文存储的数据中将给定的属性名移出
void removeAttribute(String attributeName);
4.2 用法
  • 配置 web.xml

    <context-param><param-name>characterEncoding</param-name><param-value>UFT-8</param-value>
    </context-param>
  • 修改 RegisterServlet

@Override
public void init(ServletConfig config) throws ServletException {System.out.println("开始读取上下文参数信息");ServletContext servletContext = config.getServletContext();Enumeration<String> initParameterNames = servletContext.getInitParameterNames();while (initParameterNames.hasMoreElements()){String initParameterName = initParameterNames.nextElement();String initParameterValue = servletContext.getInitParameter(initParameterName);System.out.println( initParameterName + " => " + initParameterValue);}
}
  • 测试

查看控制台信息

第二节 MVC

1. 什么是 MVC

模型-视图-控制器(MVC模式)是一种非常经典的软件架构模式,在UI框架和UI设计思路中扮演着非常重要的角色。从设计模式的角度来看,MVC模式是一种复合模式,它将多个设计模式在一种解决方案中结合起来,用来解决许多设计问题。MVC模式把用户界面交互分拆到不同的三种角色中,使应用程序被分成三个核心部件:Model(模型)、View(视图)、Control(控制器)

  • 模型:模型持有所有的数据、状态和程序逻辑。模型独立于视图和控制器。

  • 视图:用来呈现模型。视图通常直接从模型中取得它需要显示的状态与数据。对于相同的信息可以有多个不同的显示形式或视图。

  • 控制器:位于视图和模型中间,负责接受用户的输入,将输入进行解析并反馈给模型

MVC模式将它们分离以提高系统的灵活性和复用性,不使用MVC模式,用户界面设计往往将这些对象混在一起。MVC模式实现了模型和视图的分离,使得其具有以下优点:

  • 一个模型提供不同的多个视图表现形式,也能够为一个模型创建新的视图而无须重写模型。一旦模型的数据发生变化,模型将通知有关的视图,每个视图相应地刷新自己。

  • 模型可复用。因为模型是独立于视图的,所以可以把一个模型独立地移植到新的平台工作。

  • 提高开发效率。在开发界面显示部分时,仅仅需要考虑的是如何布局一个好的用户界面;开发模型时,仅仅要考虑的是业务逻辑和数据维护,这样能使开发者专注于某一方面的开发,提高开发效率。

2. JSP 中的 MVC

在 JSP 中 Servlet 扮演的是控制器, JSP 页面扮演的是视图,Java Bean 扮演的是模型。

案例: 将用户信息呈现在页面上

  • 编写视图 user.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>显示用户信息</title>
</head>
<body><a href="showUserInfo">显示用户信息</a>
</body>
</html>
  • 编写模型 User

package com.qf.jsp.pojo;public class User {private String username;private String name;private String sex;private int age;public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getSex() {return sex;}public void setSex(String sex) {this.sex = sex;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}@Overridepublic String toString() {return "User{" +"username='" + username + '\'' +", name='" + name + '\'' +", sex='" + sex + '\'' +", age=" + age +'}';}
}
  • 编写控制器 UserInfoServlet

package com.qf.jsp.servlet;import com.qf.jsp.pojo.User;import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;public class UserInfoServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {User user = new User();user.setUsername("admin");user.setName("管理员");user.setSex("男");user.setAge(20);resp.setContentType("text/html;charset=utf-8");resp.setCharacterEncoding("UTF-8");PrintWriter writer = resp.getWriter();//告知视图需要展示的模型writer.print(user.toString());writer.flush();writer.close();}
}
  • 配置 web.xml

<servlet><servlet-name>userInfoServlet</servlet-name><servlet-class>com.qf.jsp.servlet.UserInfoServlet</servlet-class>
</servlet><servlet-mapping><servlet-name>userInfoServlet</servlet-name><url-pattern>/showUserInfo</url-pattern>
</servlet-mapping>

第三节 过滤器

1. 什么是过滤器

过滤器的概念过滤器是一个服务器端的组件,可以拦截客户端的请求和响应信息并对这些信息进行过滤。

2. 过滤器体系结构

  • 启动服务器,访问 user.jsp,然后测试

2.1 Filter接口
//过滤器初始化
default void init(FilterConfig filterConfig) throws ServletException {
}
//过滤操作,与协议无关
void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException;
//过滤器销毁
default void destroy() {
}
2.2 FilterConfig 接口
//获取过滤器实例的名称
String getFilterName();
//获取Servlet上下文
ServletContext getServletContext();
//从过滤器初始化配置中获取给定属性名对应的属性值
String getInitParameter(String parameterName);
//获取过滤器初始化配置中所有的属性名
Enumeration<String> getInitParameterNames();
2.3 案例

使用过滤器完成中文乱码处理

  • 编写过滤器 CharacterEncodingFilter

package com.qf.jsp.filter;import javax.servlet.*;
import java.io.IOException;public class CharacterEncodingFilter implements Filter {private String characterEncoding;@Overridepublic void init(FilterConfig config) throws ServletException {System.out.println("过滤器初始化");this.characterEncoding = config.getInitParameter("characterEncoding");}@Overridepublic void doFilter(ServletRequest request,ServletResponse response,FilterChain chain)throws IOException, ServletException {System.out.println("过滤器过滤操作");request.setCharacterEncoding(characterEncoding);response.setCharacterEncoding(characterEncoding);//让过滤器链中的其他过滤器执行,这行代码必不可少,否则,无法进入后面的Servlet执行chain.doFilter(request, response);}@Overridepublic void destroy() {System.out.println("过滤器销毁");}
}
  • 在 web.xml 中配置过滤器

<filter><filter-name>characterEncodingFilter</filter-name><filter-class>com.qf.jsp.filter.CharacterEncodingFilter</filter-class><init-param><param-name>characterEncoding</param-name><param-value>UTF-8</param-value></init-param>
</filter><filter-mapping><filter-name>characterEncodingFilter</filter-name><!-- * 标识通配符,匹配所有--><url-pattern>/*</url-pattern>
</filter-mapping>
  • 测试

  • 结论

2.4 HttpFilter 抽象类
//重写无协议过滤器操作,调用下面支持HTTP协议请求过滤操作的方法
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {}
//HTTP协议请求过滤操作的方法
protected void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {}
2.5 案例

使用过滤器完成登录超时处理

  • 编写过滤器

package com.qf.jsp.filter;import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;public class TimeoutFilter extends HttpFilter {@Overrideprotected void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {HttpSession session = request.getSession();Object username = session.getAttribute("username");//session中没有数据了,说明session已经过期了,当前的session是一个新的sessionif(username == null){//首页的地址 就是上下文路径String homePageUrl = request.getContextPath();if("".equalsIgnoreCase(homePageUrl)){//上下文路径为空字符串时给一条斜杠即可homePageUrl = "/";}response.sendRedirect(homePageUrl);} else {//让过滤器链中的其他过滤器执行,这行代码必不可少,否则,无法进入后面的Servlet执行chain.doFilter(request, response);}}
}
  • 在 web.xml 中配置过滤器

<filter><filter-name>timeoutFilter</filter-name><filter-class>com.qf.jsp.filter.TimeoutFilter</filter-class>
</filter><filter-mapping><filter-name>timeoutFilter</filter-name><!-- * 标识通配符,匹配所有--><url-pattern>/*</url-pattern>
</filter-mapping>
2.6 Filter 交互流程

相关文章:

Servlet 与 MVC

主要内容 Servlet 重点 MVC 重点 Filter 重点 章节目标 掌握 Servlet 的作用 掌握 Servlet 的生命周期 掌握 JSP 的本质 掌握 MVC 的设计思想 掌握 Filter 的作用及使用场景 第一节 Servlet 1. Servlet 概念 Servlet 是在服务器上运行的能够对客户端请求进行处理&a…...

基于单片机的感应自动门控制器的设计

摘要 现如今自动化、信息化程度越来越高&#xff0c; 单片机的应用领域也越来越广&#xff0c; 成为人们生活不可或缺的一部分。随省社会的发展、科技的进步以及人们生活水平的逐步提高&#xff0c;各种方便千生活的自动控制系统开始进入了人们的生活&#xff0c;以单片机为核…...

兄弟HL-1208黑白激光打印机清零方法

兄弟HL-1208黑白激光打印机基本参数&#xff1a; 产品类型&#xff1a;黑白激光打印机&#xff08;定位类型家用&#xff09; 最大打印幅面&#xff1a;A4 最高分辨率&#xff1a;600600dpi 黑白打印速度&#xff1a;20ppm 内存标配&#xff1a;1MB&#xff0c;最大&#…...

第二百八十八回

文章目录 1. 概念介绍2. 使用方法2.1 实现步骤2.2 具体细节 3. 示例代码4. 内容总结 我们在上一章回中介绍了"如何获取文件类型"相关的内容&#xff0c;本章回中将介绍如何播放视频.闲话休提&#xff0c;让我们一起Talk Flutter吧。 1. 概念介绍 播放视频是我们常用…...

【日常学习笔记】gtest

https://zhuanlan.zhihu.com/p/369466622 int Factorial(int n) {int result 1;for (int i 1; i < n; i) {result * i;}return result; }TEST(TestSuiteName, TestName) 第一个参数可以表示为一个对某一个函数进行测试&#xff0c;第二个参数表示对这个函数测试时的分的几…...

go-zero配置DB的redis缓存

配置定义&#xff1a; # cat internal/config/config.go package configimport ("github.com/zeromicro/go-zero/rest""github.com/zeromicro/go-zero/core/stores/cache" )type Config struct {rest.RestConfCacheRedis cache.CacheConf }对应的配置文件…...

物理服务器

物理服务器 物理服务器是一种独立的、非虚拟化的计算机设备&#xff0c;它通常被用作高性能应用、数据库、存储和网络等关键业务应用的运行平台。物理服务器可以提供更高的处理能力、更好的安全性和可靠性&#xff0c;但需要用户自行维护和管理。 物理服务器的形式多种多样&…...

3.3 实验三:以太网链路聚合实验

HCIA-Datacom实验指导手册&#xff1a;3.3 实验三&#xff1a;以太网链路聚合实验 一、实验介绍&#xff1a;二、实验拓扑&#xff1a;三、实验目的&#xff1a;四、配置步骤&#xff1a;步骤 1 掌握使用手动模式配置链路聚合的方法步骤 2 掌握使用静态 LACP 模式配置链路聚合的…...

php mysql字段默认值使用问题

前提是使用了事务&#xff0c;在第一个阶段 是A表操作保存&#xff0c;第二阶段操作B表&#xff0c;操作B表的时候使用了A表的一个字段&#xff0c;这个字段在第一阶段没有设置值&#xff0c;保存的时候使用字段默认值。 【这种情况 最好是在第一阶段 把后面要使用的字段设置好…...

【linux】Debian防火墙

Debian系统默认没有安装防火墙&#xff0c;但用户可以根据需要自行选择并安装一个防火墙以增强系统安全性。 一、查看Debian 桌面系统的防火墙是否关闭 在Debian及其他基于Linux的桌面系统中&#xff0c;防火墙功能通常是由iptables或nftables规则集控制的&#xff0c;而ufw&…...

2022年至2023年广东省职业院校技能大赛高职组“信息安全管理与评估”赛项样题

2022 年至 2023 年广东省职业院校技能大赛高职组“信息安全管理与评估”赛项样题 一、 第一阶段竞赛项目试题 本文件为信息安全管理与评估项目竞赛第一阶段试题&#xff0c;第一阶段内容包 括&#xff1a;网络平台搭建、网络安全设备配置与防护。 本阶段比赛时间为 180 分钟…...

CC++内存管理【非常详细,对新手友好】

文章目录 一、程序内存划分1.基础知识2. 堆栈的区别3. 题目练手 二、C语言中动态内存管理方式三、C中动态内存管理方式1. new/delete操作内置类型2. new/delete操作自定义类型 四、operator new和operator delete函数1. 汇编查看编译器底层调用2. 透过源码分析两个全局函数 五、…...

022-安全开发-PHP应用留言板功能超全局变量数据库操作第三方插件引用

022-安全开发-PHP应用&留言板功能&超全局变量&数据库操作&第三方插件引用 #知识点&#xff1a; 1、PHP留言板前后端功能实现 2、数据库创建&架构&增删改查 3、内置超全局变量&HTML&JS混编 4、第三方应用插件&传参&对象调用 演示案例&a…...

大白话解析LevelDB 3: SST Compaction

SST Compaction 文章目录 SST Compaction什么是Compact SST什么时候触发Compact SST第一处 读取 Key 的时候第二处 使用迭代器遍历数据库时第三处 写入 Key 时第四处 刚打开数据库时 如何进行Compact SST计算Compaction范围进行Compaction创建一个迭代器用于读取Compaction范围…...

【Python】02快速上手爬虫案例二:搞定验证码

文章目录 前言1、不要相信什么验证码的库2、以古诗文网为例&#xff0c;获取验证码1&#xff09;code_result.py2&#xff09;gsw.py 前言 提示&#xff1a;以古诗文网为例&#xff0c;获取验证码&#xff1a; 登录&#xff1a;https://so.gushiwen.cn/user/login.aspx 1、不…...

C# 中的接口

简介 官方说明&#xff1a;接口定义协定。 实现该协定的任何 class 或 struct 必须提供接口中定义的成员的实现。 接口可为成员定义默认实现。 它还可以定义 static 成员&#xff0c;以便提供常见功能的单个实现。 从 C# 11 开始&#xff0c;接口可以定义 static abstract 或 …...

一篇文章带你了解C++中隐含的this指针

文章目录 一、this指针的引出二、this指针的特性【面试题】 一、this指针的引出 我们先来定义一个日期类Date&#xff0c;下面这段代码执行的结果是什么呢&#xff1f; class Date { public:void Init(int year, int month, int day){_year year;_month month;_day day;}v…...

shardinig-JDBC二开-支持sharding-jdbc的配置文件接入到nacos

代码在 https://gitee.com/lbmb/mb-live-app 中 【mb-live-framework】 模块里面的【mb-live-framework-datasource-stater】 如果喜欢 希望大家给给star 项目还在持续更新中。 背景介绍&#xff1a; 因为近期在自己写一套直播项目。使用到了sharding-jdbc来做分库分表的组件…...

a-table自定义展开图标

原文来自&#xff1a;vue 修改ant中table表格的展开图标 树形表格expandIcon自定义图标 <template #expandIcon"props"><span v-if"props.record.children?.length > 0"><divv-if"props.expanded"style"display: inline…...

Kubernetes Ingress暴露应用的工作流程

文章目录 一、Igress是什么二、安装Igress Controller三、Service NodePort模式暴露Ingress Controller四、创建ingress 进行访问查看ingress controller生成的规则(两种类型通用) 五、HostNetwork模式暴露Ingress Controller总结&#xff1a; 一、Igress是什么 一般负载均衡器…...

Redis应用(1)缓存(1.2)------Redis三种缓存问题

三者出现的根本原因是&#xff1a;Redis缓存命中率下降&#xff0c;请求直接打到DB上了。 一、 缓存穿透&#xff1a; 1、定义&#xff1a; 缓存穿透是指客户端请求的数据在缓存中和数据库中都不存在&#xff0c;这样缓存永远不会生效&#xff0c;这些请求都会打到数据库。…...

安全 专题

[实践总结] 日志注入问题&#xff08;log4j2&#xff09; [实践总结] Java 防止SQL注入的四种方案 [实践总结] 如何防护 order by 导致的SQL注入 [实践总结] 限制正则表达式匹配次数/时间 防止DoS攻击 [实践总结] java XML解析防止外部实体注入 [Ref] yaml.load的漏洞利用…...

自然语言处理-文本对分类或回归

我们研究了自然语言推断。它属于文本对分类&#xff0c;这是一种对文本进行分类的应用类型。 以一对文本作为输入但输出连续值&#xff0c;语义文本相似度是一个流行的“文本对回归”任务。 这项任务评估句子的语义相似度。例如&#xff0c;在语义文本相似度基准数据集&#x…...

以梦为码,CodeArts Snap 缩短我与算法的距离

背景 最近一直在体验华为云的 CodeArts Snap&#xff0c;逐渐掌握了使用方法&#xff0c;代码自动生成的准确程度大大提高了。 自从上次跟着 CodeArts Snap 学习用 Python 编程&#xff0c;逐渐喜欢上了 Python。 我还给 CodeArts Snap 起了一个花名&#xff1a; 最佳智能学…...

SpringMVC-HttpMessageConverter 报文信息转化器

文章目录 HttpMessageConverter一、概念二、RequestBody三、RequestEntity四、 ResponseBody1.返回JSON格式的字符串 五、RestController六、ResponseEntity HttpMessageConverter 一、概念 报文信息转化器&#xff0c;将请求报文转化为Java对象&#xff0c;或将Java对象转化…...

[AG32VF407]国产MCU+FPGA 使用I2C测试陀螺仪MPU6050

视频讲解 [AG32VF407]国产MCUFPGA 使用I2C测试陀螺仪MPU6050 实验过程 查看原理图中定义的I2C的管脚&#xff0c;PB0和PB1 在board.ve中定义的引脚功能 I2C0_SDA PIN_36 I2C0_SCL PIN_35新建工程 测试代码 #include "board.h"#define MIN_IRQ_PRIORITY 1 #define …...

ES 可扩展、高可靠、使用场景等常见问题

ElasticSearch的常见问题 什么是ElasticSearch ElasticSearch是一款非常强大的、基于Lucene的开源搜索及分析引擎&#xff1b;它是一个实时的分布式搜索分析引擎&#xff0c;它能让你以前所未有的速度和规模&#xff0c;去探索你的数据。 它被用作全文检索、结构化搜索、分析…...

<网络安全>《4 网络安全产品之web应用防护系统》

1 基本概念 1.1 WAF Web应用防护系统&#xff08;也称为&#xff1a;网站应用级入侵防御系统。英文&#xff1a;Web Application Firewall&#xff0c;简称&#xff1a;WAF&#xff09;。一般作为网关设备&#xff0c;防护Web、Webmail服务器等。 1.2 本质 WAF的本质是Web应…...

如何解决Flutter应用程序的兼容性问题

随着移动应用开发领域的不断发展&#xff0c;Flutter作为一种跨平台框架&#xff0c;受到了越来越多开发者的青睐。要确保Flutter应用程序能够在不同的设备和操作系统上稳定运行&#xff0c;并提供一致的用户体验&#xff0c;我们需要重视应用程序的兼容性问题。下面将简单的介…...

详解Mockito

详解Mockito 1. Mockito简介 在我们的编程世界中&#xff0c;测试是一个非常重要的环节&#xff0c;它能帮助我们确保代码的质量和稳定性。而在众多的测试方法中&#xff0c;Mock测试是一种非常有效的手段。 1.1 什么是 Mock 测试 Mock测试&#xff0c;顾名思义&#xff0c;…...