SpringMVC学习记录

SpringMVC简介与配置

SpringMVC是一种基于Java实现MCV模型的轻量级Web框架,我们该如何使用呢?
首先在Maven中添加坐标

 	<dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>4.0.1</version>
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>4.3.3.RELEASE</version>
    </dependency>

随后我们创建一个SpringMVC的配置文件,该文件只负责声明这是SpringMVC的配置,并扫描对应的controller层。

package configs;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
//创建SpringMVC的配置文件,加载需要的Bean
@ComponentScan("controller")
public class SpringMvcConfig {
}

在配置完后如何让Tomcat启动时加载呢,我们先前加载Spring的方式是通过AnnotationConfigApplicationContext来生成的,但在Web项目中要使用AnnotationConfigWebApplicationContext来生成。其通过继承AbstractDispatcherServletInitializer这个类来实现,并且需要重写下面的三个方法来分别做SpringMVC、数据请求以及Spring的配置。

package configs;

import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.support.AbstractDispatcherServletInitializer;

public  class ServletConfig extends AbstractDispatcherServletInitializer {
    //加载SpringMVC配置
    @Override
    protected WebApplicationContext createServletApplicationContext() {
        //在Spring中,使用AnnotationConfigApllication来创建Spring容器,但Web环境下要使用下面的
        AnnotationConfigWebApplicationContext ctx=new AnnotationConfigWebApplicationContext();
        //上面是一个空的容器,使用register来加载SpringMVC的配置
        ctx.register(SpringMvcConfig.class);
        return ctx;
    }
    //设置哪些请求归属SpringMVC处理
    @Override
    protected String[] getServletMappings() {
        return new String[]{"/"};//代表所有请求都要交给SpringMVC去处理
    }
    //加载Spring容器配置
    @Override
    protected WebApplicationContext createRootApplicationContext() {
        AnnotationConfigWebApplicationContext ctx=new AnnotationConfigWebApplicationContext();
        //上面是一个空的容器,使用register来加载SpringMVC的配置
        ctx.register(SpringConfig.class);
        return ctx;
    }
}

当然我们也可以使用下面的代码来简化开发,只不过相较于上面的配置我们不知道具体是如何实现的而已。

在这里插入图片描述

随后我们定义Controller

package controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class UserController {
    @RequestMapping("/save")
    @ResponseBody//将返回的信息作为整体相应内容
    public String save(){
        System.out.print("controller..");
        return "{mode:ok}";
    }
}

我们分析一下这个案例的工作流程。

在这里插入图片描述

Spring加载控制

SpringMVC负责加载Controller中的Bean,而Spring则应该只负责加载业务层(service),数据层(dao)Bean,那么如何让Spring不重复加载SpringMVC负责的Bean呢?
一种方式是精确定位,即在Spring扫描时只写servicedao等,那么自然也就不会加载Controller的类了
另一种则是排除,在扫描时,依旧扫描全部包,但排除一部分,如Controller的包。

在这里插入图片描述

PostMan工具

这是一款可以模拟http请求的插件,可以方便我们开发。PostMan下载地址如下

https://www.postman.com/downloads/

下载后我们需要创建一个账号,随后我们创建一个工作空间,然后写入请求就可以模拟了。

在这里插入图片描述

SpringMVC开发Controller

请求映射路径

package controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
@RequestMapping("/users")
public class UserController {
    @RequestMapping("/save")
    @ResponseBody//将返回的信息作为整体相应内容
    public String save(){
        System.out.print("controller..");
        return "{mode:usersave}";
    }
}

不同于ServletdoGetdoPost方法,SpringMVC的后端代码是不区分GetPost的,因此我们只需要在PostMan中选择不同的提交形式即可。

在这里插入图片描述

然而,我们在实验过程中,如果传递的参数是汉字的话,则会出现乱码问题:{mode:彭祥}
该如何解决呢?在原本的Servlet中我们采用过滤器的方式解决乱码问题,在SpringMVC中亦是如此,那么该如何实现呢,我们在ServletConfig中重写getServletFilters()方法。

package configs;

import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.filter.CharacterEncodingFilter;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
import org.springframework.web.servlet.support.AbstractDispatcherServletInitializer;
import javax.servlet.Filter;
public  class ServletConfig extends AbstractAnnotationConfigDispatcherServletInitializer {
    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class[]{SpringMvcConfig.class};
    }
    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class[]{SpringConfig.class};
    }
    @Override
    protected String[] getServletMappings() {
        return new String[]{"/"};
    }
    @Override
    protected Filter[] getServletFilters() {
        CharacterEncodingFilter filter=new CharacterEncodingFilter();
        filter.setEncoding("UTF-8");
        return new Filter[]{filter};
    }
}

Controller中的传参代码如下:参数为name,而发送http请求的是:

在这里插入图片描述
需要注意的是,SpringMVC能够将http传递的参数与形参相同时进行映射。

package controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
@RequestMapping("/users")
public class UserController {
    @RequestMapping("/save")
    @ResponseBody//将返回的信息作为整体相应内容
    public String save(String name){
        System.out.print("name:"+name+"\ncontroller..");
        return "{mode:"+name+"}";
    }
}

然后,如何http请求的参数与形参不同,则无法映射,从而会导致传参失败。报400错误。

在这里插入图片描述

那么此时该如何映射呢,使用@RequestParam注解即可

 public String save(@RequestParam("username") String name){
        System.out.print("name:"+name+"\ncontroller..");
        return "{mode:"+name+"}";
    }

那么如果形参是一个对象呢?如下Users对象。

package domain;

public class Users {
    private int id;
    private String name;
    private String password;

    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
}
public String save(Users user){
        System.out.print("name:"+user.getName()+"\ncontroller..");
        return "{mode:"+user.getName()+"}";
    }

此时发送请求依旧成功。
在这里插入图片描述

那如果对于一些类里面嵌套类的情况呢?

在这里插入图片描述

后端代码不变,但http发送的请求参数需要改变:类名.属性名

?name=peng&password=1234&address.city=city

JSON格式传递参数

首先导入JSON坐标:

<dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>2.9.0</version>
</dependency>

由于SpringMVC是不支持JOON格式接收的,要想使其支持,我们需要在SpringMVC文件中开启@EnableWebMvc注解,即开启自动转换JSON数据的支持。

package configs;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
//创建SpringMVC的配置文件,加载需要的Bean
@ComponentScan("controller")
@EnableWebMvc
public class SpringMvcConfig {
}

随后我们运行发现SpringMVC将接收的List数组当对象了去构建了,导致报错,此时在List前加上@RequestBody注解即可,注意,此时不能加@RequestParm,因为此时数据是封装在JSON中的。

@RequestMapping("jsonlist")
    @ResponseBody
    public String jsonList(@RequestBody List<String> likes){
        System.out.print(likes);
        return "0";
    }

注意JSON数据的封装测试类型。

 @RequestMapping("jsonlist")
    @ResponseBody
    public String jsonList(@RequestBody List<String> likes){
        System.out.print(likes);
        return "0";
    }

在这里插入图片描述

  @RequestMapping("jsonpojo")
    @ResponseBody
    public String jsonPOJO(@RequestBody Users user){
        System.out.print(user);
        return "{user:"+user+"}";
    }

在这里插入图片描述

@RequestMapping("jsonpojolist")
    @ResponseBody
    public String jsonPOJOList(@RequestBody List<Users> users){
        System.out.print(users);
        return "{user:"+users+"}";
    }

在这里插入图片描述

日期型类型参数传递

在这里插入图片描述
在这里插入图片描述

还记得@EnableWebMvc注解吗,这个注解在格式转换中具有非常多的应用。
事实上我们前面所提到的JSON数据转换并不是真正的JSON数据,其只是一个字符串而已。真正要返回JSON格式的对象怎么做呢,很简单,只需要将返回值类型改为对应的对象类型即可。

 @RequestMapping("jsonpojo")
    @ResponseBody
    public Users jsonPOJO(@RequestBody Users user){
        System.out.print(user);
        return user;
    }
    @RequestMapping("jsonpojolist")
    @ResponseBody
    public List<Users> jsonPOJOList(@RequestBody List<Users> users){
        System.out.print(users);
        return users;
    }

在这里插入图片描述

REST风格访问资源

我们为什么要使用REST风格呢,这种方式有什么用呢?最明显的一点的就是简单写法简单,另一个特点就是可以隐藏请求,可以看到我们的查询、修改请求都可以隐藏。

在这里插入图片描述

那么REST叫风格而不叫规范呢?

在这里插入图片描述
那么在SpringMVCController中该如何写呢?

在这里插入图片描述

需要注意的是,在进行修改时,由于我们需要使用路径中的值,因此我们除了指定请求类型外,还需要再请求路径上添加一个占位符,名字与下面的参数相同,同时,还需要在形参前使用路径变量(@PathVaeiable)注解来声明路径。

在这里插入图片描述

@RequestBody等注解的区别在呢?

在这里插入图片描述

RSETful快速开发

由于我们在实际开发中都是将数据转换为JSON发送Controller中进行处理的,因此我们对一些功能进行简化。
采用了RESTful风格后,我们可以之间将@RequestMapping放到对应的Controller类前面。同时由于返回数据都是JSON格式,因此我们也可以将RequestBody放到Controller类前面,同时将@Controller与@RequestBody注解合二为一变为:@RestController

@Controller
@ResponseBody//将返回的信息作为整体相应内容
@RequestMapping("/users")
public class UserController {
    @RequestMapping(method = RequestMethod.POST)
    public String save(@RequestBody Users user){   System.out.print("name:"+user.getAddress().getCity()+"\ncontroller..");
        return "{mode:"+user.getName()+"}";
    }
 }

但是这样我们还要写 @RequestMapping(method = RequestMethod.POST),这也是很麻烦的,因此再次简化可以写为 @PostMapping,其余方法则如法炮制。

 @PostMapping
    public String save(@RequestBody Users user){
        System.out.print(user);
        return "{mode:"+user.getName()+"}";
    }
    @PutMapping("/{id}")
    public String edit(Integer id){
        System.out.print(id);
        return "{mode:1}";
    }
    @DeleteMapping("/{id}")
    public String delete(Integer id){
        System.out.print(id);
        return "{mode:1}";
    }

在这里插入图片描述

基于RESTful的页面交互

我们该如何进行RESTful的页面交互呢?
我们首先创建一个index.html页面,然后我们访问一下,发现404请求。

在这里插入图片描述

这是为什么呢,这是由于SpringMVC的请求给拦截处理了,还记得我们在SpringMVC的配置吗?

public  class ServletConfig extends AbstractAnnotationConfigDispatcherServletInitializer {
    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class[]{SpringMvcConfig.class};
    }
    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class[]{SpringConfig.class};
    }
    @Override
    protected String[] getServletMappings() {
        return new String[]{"/"};
    }
    @Override
    protected Filter[] getServletFilters() {
        CharacterEncodingFilter filter=new CharacterEncodingFilter();
        filter.setEncoding("UTF-8");
        return new Filter[]{filter};
    }
}

里面的getServletMappings() {return new String[]{"/"};会拦截所有的请求,导致我们的html文件被拦截了,那么该怎么办呢?

我们需要配置一个SpringSupport配置文件,实现一个方法,让来自/pages/**的请求不发送到SpringMVC而是直接访问/pages/,这个配置非常重要,我们可以配置许多静态资源。

package configs;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
@Configuration
public class SpringMvcSupport extends WebMvcConfigurationSupport {
    @Override
    protected void addResourceHandlers(ResourceHandlerRegistry registry) {
        //当路径时pages下内容时,不用走SpringMVC,而要走pages路径
        registry.addResourceHandler("/pages/**").addResourceLocations("/pages/");
        //添加一个资源处理器
    }
}

随后我们在SpringMVC配置中扫描一下configs

@ComponentScan({"controller","configs"})
@EnableWebMvc
public class SpringMvcConfig{
}

OK了。

在这里插入图片描述

前后端传输协议

为了方便前后端开发合作,定义一套格式,方便数据交互。

在这里插入图片描述
由于这个结果是由表现层输出的,因此我们将结果类(Result)封装在了Controller包中。同时还需要提供Code,同样被封装在Controller中。

package controller;

public class Results {
    private Object data;
    private String msg;
    private Integer code;
    public Results( Integer code,Object data) {
        this.data = data;
        this.code = code;
    }
    public Results(Object data, String msg, Integer code) {
        this.data = data;
        this.msg = msg;
        this.code = code;
    }
    public Object getData() {
        return data;
    }
    public void setData(Object data) {
        this.data = data;
    }
    public String getMsg() {
        return msg;
    }
    public void setMsg(String msg) {
        this.msg = msg;
    }
    public Integer getCode() {
        return code;
    }
    public void setCode(Integer code) {
        this.code = code;
    }
}

Code的定义,这是我们与前端人员商量好的。

package controller;

public class Code {
    public static Integer Save_OK=20011;
    public static Integer DEL_OK=20021;
    public static Integer UPDATE_OK=20031;
    public static Integer GET_OK=20041;
    public static Integer Save_ERR=20010;
    public static Integer DEL_ERR=20020;
    public static Integer UPDATE_ERR=20030;
    public static Integer GET_ERR=20040;
}

随后我们对Controller的结果进行封装修改:

	@Autowired
    UserService us;
    @GetMapping("/{gname}")
    public Results MenuList(@PathVariable String gname){
        List<Menu> lists= us.list(gname);
        System.out.print(lists.toString());
        Integer code=lists!=null?Code.GET_OK:Code.GET_ERR;
        String msg=lists!=null?"":"查询失败";
        return new Results(lists,msg,code);
    }

至此,我们便完成了前后端数据的传递。

异常处理

上述过程都是在保证不出现错误与异常的情况下进行的,而我们的实际开发中时常会有多种情况会导致异常的发生。

在这里插入图片描述
那么一旦发生了这些异常,就会发生报错,如400,500等错误,而前端人员获取到这种异常也是无法处理的,因为它并不在我们先前规定的前后端协议中,因此,我们要对异常进行处理:
我们在COntroller中定义一个项目异常处理类,这个异常是处理所有异常结果的,一旦发生异常,便会捕获异常并对数据进行封装,变为与前端协商好的格式,同时应该发生通知给运维人员或开发人员。

package controller;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
@RestControllerAdvice//代表是处理rest风格controller异常
public class ProjectExectionAdvice {
    @ExceptionHandler(Exception.class)//这是使用一个异常处理器处理所有异常
    public Results doException(Exception ex){
        System.out.print("发生异常!");
        return new Results(666,null,null);
    }
}

此时返还给前端的结果便是这种,我们可以让前端人员设计一个页面让用户稍后再试。

在这里插入图片描述

事实上,上面的异常是处理的所有异常,而异常是具有不同分类的,项目异常分类如下:

在这里插入图片描述
针对项目异常,我们需要做对应的事务处理:

在这里插入图片描述
我们可以自己定义不同的异常情况来进行处理。

在这里插入图片描述

拦截器

原本的请求处理流程:

在这里插入图片描述
加入拦截器的请求处理流程,拦截器可以做权限控制。
在这里插入图片描述

拦截器(Interceptor)是一种动态拦截方法调用的机制,在SpringMVc中动态拦截控制器方法的执行作用:

  • 在指定的方法调用前后执行预先设定的代码
  • 阻止原始方法的执行

讲到这里,我们会发现,拦截器与我们先前所作的过滤器的效果很相近,事实上,两者的功能上的确是很类似的。但仍存在差异:

  • 归属不同:Filter属于Servlet技术,Interceptor属于SpringMVC技术
  • 拦截内容不同:Filter对所有访问进行增强,Interceptor仅针对SpringMVc的访问进行增强

那么拦截器该如何实现呢?
首先,拦截器是在Controller前后使用的,因此我们可以将拦截器定义在表现层,定义如下:
首先该类重写HandlerInterceptor的接口,其实随后我们需要将该类声明为一个Bean,即可以进行扫描,加上@Component即可

package controller.interpector;

import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Component
public class ProjectInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.print("preHandle\n");
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.print("postHandle\n");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.print("afterCompletion\n");
    }
}

随后我们只是重写了这个方法,那么该在哪里调用呢,还记得先前写的SpringMvcSupport类吗,我们曾在里面定义了过滤器,现在我们的拦截器依旧在里面调用:我们新增一个addInterceptors方法,该方法的使用与过滤器极为相近,随后我们为其添加过滤器,并设置需要拦截的请求。

package configs;
import controller.interpector.ProjectInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
@Configuration
public class SpringMvcSupport extends WebMvcConfigurationSupport {
    @Autowired
    private ProjectInterceptor projectInterceptor;
    @Override
    protected void addResourceHandlers(ResourceHandlerRegistry registry) {
        //当路径时pages下内容时,不用走SpringMVC,而要走pages路径
  registry.addResourceHandler("/pages/**").addResourceLocations("/pages/");//添加一个资源处理器
    }

    @Override
    protected void addInterceptors(InterceptorRegistry registry) {
        System.out.print("拦截器");
        registry.addInterceptor(projectInterceptor).addPathPatterns("/users/*");
    }
}

注意,该拦截请求的匹配及其严格,如果写的是/users那么只会过滤对应的请求,如果后面有参数就不符合了,因此我们多写为"/users/*",同时,这个可以传递多个拦截请求,如下:

registry.addInterceptor(projectInterceptor).addPathPatterns("/users/*","/goods/*");

学到这里,其实我们可以对拦截器与过滤器进行简化配置,我们让SpringMvcConfig实现WebMvcConfigurer接口即可去除掉原来的SpringMvcSupport,两种方法都可以。但这种 方式由于实现了接口,因此与Spring绑定较强,即侵入性较强。

在这里插入图片描述

关于拦截器中的参数定义如下:

在这里插入图片描述
此外,当我们配置多个拦截器时,便可以形成拦截器链,一般我们在开发时,一般使用一个拦截器便可以了。

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

iOS UIFont-实现三方字体的下载和使用

UIFont 系列传送门 第一弹加载本地字体:iOS UIFont-新增第三方字体 第二弹加载线上字体:iOS UIFont-实现三方字体的下载和使用 前言 在上一章我们完成啦如何加载使用本地的字体。如果我们有很多的字体可供用户选择,我们当然可以全部使用本地字体加载方式,可是这样就增加了…

算法---动态规划练习-7(按摩师)【类似打家劫舍】

按摩师 1. 题目解析2. 讲解算法原理3. 编写代码 1. 题目解析 题目地址&#xff1a;点这里 2. 讲解算法原理 首先&#xff0c;给定一个整数数组 nums&#xff0c;其中 nums[i] 表示第 i 天的预约时间长度。 定义两个辅助数组 f 和 g&#xff0c;长度都为 n&#xff08;n 是数组…

STM32时钟简介

1、复位&#xff1a;使时钟恢复原始状态 就是将寄存器状态恢复到复位值 STM32E10xxx支持三种复位形式,分别为系统复位、上电复位和备份区域复位。 复位分类&#xff1a; 1.1系统复位 除了时钟控制器的RCC_CSR寄存器中的复位标志位和备份区域中的寄存器以外,系统 复位将复位…

SQL-CRUD-2数据库实验

目录 第一关任务描述 相关知识 插入完整内容的行 插入选定内容的行 编程要求 测试说明 第一关代码 第二关任务描述 相关知识 删除表中的指定行 删除表中的所有行 编程要求 测试说明 第二关代码 第三关任务描述 相关知识 更新表中的指定行 编程要求 测试说明…

【学习】信创产品软件测试企业建设参考清单

“信创&#xff0c;即信息技术应用创新产业&#xff0c;涉及IT基础设施、基础软件、应用软件、信息安全等方面&#xff0c;产品覆盖面广、专业性强。作为目前的一项国家战略&#xff0c;也是当今形势下国家经济发展的新动能&#xff0c;信创产业发展已经成为促进经济数字化转型…

SlerfTools:简化操作,激发Solana生态创新潜能

在区块链世界的快速演变中,Solana生态系统以其独特的高性能吸引了全球的目光。然而,随着生态系统的蓬勃发展,用户和开发者面临的挑战也日渐增多。正是在这样的背景下,一个名为SlerfTools的新星项目应运而生,它承诺将为Solana带来一场革命性的变革。 项目的诞生 SlerfTools并非…

【QT+QGIS跨平台编译】043:【libprotobuf-lite+Qt跨平台编译】(一套代码、一套框架,跨平台编译)

点击查看专栏目录 文章目录 一、libprotobuf-lite介绍二、文件下载三、文件分析四、pro文件五、编译实践一、libprotobuf-lite介绍 libprotobuf-lite 是 Protocol Buffers 的 C++ 轻量级运行时库,专门设计用于在资源受限的环境下使用。与标准的 libprotobuf(Protocol Buffers…

深入浅出的揭秘游标尺模式与迭代器模式的神秘面纱 ✨

​&#x1f308; 个人主页&#xff1a;danci_ &#x1f525; 系列专栏&#xff1a;《设计模式》 &#x1f4aa;&#x1f3fb; 制定明确可量化的目标&#xff0c;坚持默默的做事。 &#x1f680; 转载自&#xff1a;设计模式深度解析&#xff1a;深入浅出的揭秘游标尺模式与迭代…

力扣 718. 最长重复子数组

题目来源&#xff1a;https://leetcode.cn/problems/maximum-length-of-repeated-subarray/description/ C题解&#xff08;思路来源代码随想录&#xff09;&#xff1a;动态规划 确定dp数组&#xff08;dp table&#xff09;以及下标的含义。dp[i][j] &#xff1a;以下标i - …

速通数据结构第三站 单链表

系列文章目录 速通数据结构与算法系列 1 速通数据结构与算法第一站 复杂度 http://t.csdnimg.cn/sxEGF 2 速通数据结构与算法第二站 顺序表 http://t.csdnimg.cn/WVyDb 感谢佬们支持&#xff01; 目录 系列文章目录 前言一、单链表 1 结构体 …

踏上机器学习之路:探索数据科学的奥秘与魅力

✨✨ 欢迎大家来访Srlua的博文&#xff08;づ&#xffe3;3&#xffe3;&#xff09;づ╭❤&#xff5e;✨✨ &#x1f31f;&#x1f31f; 欢迎各位亲爱的读者&#xff0c;感谢你们抽出宝贵的时间来阅读我的文章。 我是Srlua小谢&#xff0c;在这里我会分享我的知识和经验。&am…

hxp CTF 2021 - A New Novel LFI(新颖的解法)

一、环境 unbentu&#xff0c;docker https://2021.ctf.link/assets/files/includers%20revenge-25377e1ebb23d014.tar.xz 二、解析 PHP Filter 当中有一种 convert.iconv 的 Filter &#xff0c;可以用来将数据从字符集 A 转换为字符集 B &#xff0c;其中这两个字符集可以…

记录pycharm配置Anaconda环境时没有反应的问题

记录pycharm配置Anaconda环境时没有反应的问题 背景 下载最新pycharm后在设置中配置add interpreter Anaconda环境时&#xff0c;x选中conda.ba文件点击Load Enviroments后&#xff0c;没有反应&#xff0c;就闪了一下&#xff0c;也有添加成功 探索路程 试过了重启&#x…

NineData与StarRocks商业化运营公司镜舟科技完成产品兼容认证

近日&#xff0c;镜舟科技与NineData完成产品兼容测试。在经过联合测试后&#xff0c;镜舟科技旗下产品与NineData云原生智能数据管理平台完全兼容&#xff0c;整体运行高效稳定。 镜舟科技致力于帮助中国企业构建卓越的数据分析系统&#xff0c;打造独具竞争力的“数据护城河”…

量化交易入门(二十五)什么是RSI,原理和炒股实操

前面我们了解了KDJ&#xff0c;MACD&#xff0c;MTM三个技术指标&#xff0c;也进行了回测&#xff0c;结果有好有坏&#xff0c;今天我们来学习第四个指标RSI。RSI指标全称是相对强弱指标(Relative Strength Index),是通过比较一段时期内的平均收盘涨数和平均收盘跌数来分析市…

leetcode热题100.柱状图中最大的矩形

Problem: 84. 柱状图中最大的矩形 文章目录 题目思路复杂度Code 题目 给定 n 个非负整数&#xff0c;用来表示柱状图中各个柱子的高度。每个柱子彼此相邻&#xff0c;且宽度为 1 。 求在该柱状图中&#xff0c;能够勾勒出来的矩形的最大面积。 示例 1: 输入&#xff1a;hei…

RAM IP核

1.原理 数据使能信号充当掩码的作用。1表示1字节就是8个位有效。

答题小程序功能细节揭秘:如何提升用户体验和满足用户需求?

答题小程序功能细节体现 随着移动互联网的快速发展&#xff0c;答题小程序成为了用户获取知识、娱乐休闲的重要平台。一款优秀的答题小程序不仅应该具备简洁易用的界面设计&#xff0c;更应该在功能细节上做到极致&#xff0c;以提升用户体验和满足用户需求。本文将从题库随机…

八大技术趋势案例(虚拟现实增强现实)

科技巨变,未来已来,八大技术趋势引领数字化时代。信息技术的迅猛发展,深刻改变了我们的生活、工作和生产方式。人工智能、物联网、云计算、大数据、虚拟现实、增强现实、区块链、量子计算等新兴技术在各行各业得到广泛应用,为各个领域带来了新的活力和变革。 为了更好地了解…

day56 动态规划part13

300. 最长递增子序列 中等 给你一个整数数组 nums &#xff0c;找到其中最长严格递增子序列的长度。 子序列 是由数组派生而来的序列&#xff0c;删除&#xff08;或不删除&#xff09;数组中的元素而不改变其余元素的顺序。例如&#xff0c;[3,6,2,7] 是数组 [0,3,1,6,2,2,…