Java SSM篇5——SpringMVC

Java SSM篇5——SpringMVC

1、MVC模式

MVC是软件工程中的一种软件架构模式,它是一种分离业务逻辑与显示界面的开发思想

  • M(model)模型:处理业务逻辑,封装实体
  • V(view) 视图:展示内容
  • C(controller)控制器:负责调度分发(1.接收请求、2.调用模型、3.转发到视图)

在这里插入图片描述

2、SpringMVC优点

  • 轻量级,简单易学
  • 高效 , 基于请求响应的MVC框架
  • 与Spring兼容性好,无缝结合
  • 约定优于配置
  • 功能强大:RESTful、数据验证、格式化、本地化、主题等
  • 简洁灵活

3、SpringMVC快速入门

导入依赖

<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>5.3.6</version>
    </dependency>
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>4.0.1</version>
    </dependency>
    <dependency>
        <groupId>javax.servlet.jsp</groupId>
        <artifactId>javax.servlet.jsp-api</artifactId>
        <version>2.3.3</version>
    </dependency>
</dependencies>

在web.xml注册DispatcherServlet

<?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/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
    <!--注册DispatcherServlet-->
    <servlet>
        <servlet-name>springmvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:springmvc-config.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <!--/ 匹配所有的请求;(不包括.jsp)-->
    <!--/* 匹配所有的请求;(包括.jsp)-->
    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>

springmvc核心配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       https://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/mvc
       https://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <!-- 自动扫描包,让指定包下的注解生效,由IOC容器统一管理 -->
    <context:component-scan base-package="cn.winkto.controller"/>
    <!-- 让Spring MVC不处理静态资源 -->
    <mvc:default-servlet-handler />
    <!--处理器映射器和处理器适配器,以及功能增强-->
    <mvc:annotation-driven />
    <!-- 视图解析器 -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"
          id="internalResourceViewResolver">
        <!-- 前缀 -->
        <property name="prefix" value="/WEB-INF/jsp/" />
        <!-- 后缀 -->
        <property name="suffix" value=".jsp" />
    </bean>

</beans>

第一个controller

@Controller
public class HelloController {
    @RequestMapping("/hello")
    public String hello(){
        System.out.println("hello");
        return "hello";
    }
}

hello.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<h1>Hello, i am winkto!</h1>
</body>
</html>

错误分析:web项目下没有lib包或者包不全

4、Spring执行流程

在这里插入图片描述

在这里插入图片描述

5、SpringMVC组件详解

  • 前端控制器:DispatcherServlet 用户请求到达前端控制器,它就相当于 MVC 模式中的 C,DispatcherServlet 是整个流程控制的 中心,由它调用其它组件处理用户的请求,DispatcherServlet 的存在降低了组件之间的耦合性
  • 处理器映射器:HandlerMapping HandlerMapping 负责根据用户请求找到 Handler 即处理器,SpringMVC 提供了不同的映射器 实现不同的映射方式,例如:配置文件方式,实现接口方式,注解方式等
  • 处理器适配器:HandlerAdapter 通过 HandlerAdapter 对处理器进行执行,这是适配器模式的应用,通过扩展适配器可以对更多类型 的处理器进行执行
  • 处理器:Handler【开发者编写】 它就是我们开发中要编写的具体业务控制器。由 DispatcherServlet 把用户请求转发到 Handler。由Handler 对具体的用户请求进行处理
  • 视图解析器:ViewResolver View Resolver 负责将处理结果生成 View 视图,View Resolver 首先根据逻辑视图名解析成物 理视图名,即具体的页面地址,再生成 View 视图对象,最后对 View 进行渲染将处理结果通过页面展示给 用户
  • 视图:View 【开发者编写】 SpringMVC 框架提供了很多的 View 视图类型的支持,包括:jstlView、freemarkerView、 pdfView等。最常用的视图就是 jsp。一般情况下需要通过页面标签或页面模版技术将模型数据通过页面展 示给用户,需要由程序员根据业务需求开发具体的页面

6、SpringMVC请求

  • 基本类型参数
  • 对象类型参数
  • 数组类型参数
  • 集合类型参数

6.1、基本类型参数

参数名称与请求参数的name一致,参数值会自动映射匹配

@RequestMapping("/parameter1")
@ResponseBody
public String parameter1(int id, String name){
    return id+"==="+name;
}
http://localhost:8080/springmvc_war_exploded/parameter1?id=1&name=zhangsan

6.2、对象类型参数

实体类属性名与请求参数的name一致,参数值会自动映射匹配

public class Person {
    private int id;
    private String name;
    private String password;
}
@RequestMapping("/parameter2")
@ResponseBody
public String parameter2(Person person){
    return person.toString();
}
http://localhost:8080/springmvc_war_exploded/parameter2?id=2&name=lisi&password=blingbling

6.3、数组类型参数

数组名称与请求参数的name一致,参数值会自动映射匹配

@RequestMapping("/parameter3")
@ResponseBody
public String parameter3(String[] hobits){
    return Arrays.toString(hobits);
}
http://localhost:8080/springmvc_war_exploded/parameter3?hobits=Basketball&hobits=Football

6.4、集合类型参数

public class Paramater {
    private List<Person> people;
    private Person person;
}
@RequestMapping("/parameter4")
@ResponseBody
public String parameter4(Paramater paramater){
    return paramater.toString();
}
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>$Title$</title>
  </head>
  <body>
    <form action="${pageContext.request.contextPath}/parameter4" method="post">

      list集合<br>
      第一个元素:
      <input type="text" name="people[0].id" placeholder="编号">
      <input type="text" name="people[0].name" placeholder="姓名">
      <input type="text" name="people[0].password" placeholder="密码"><br>
      第二个元素:
      <input type="text" name="people[1].id" placeholder="编号">
      <input type="text" name="people[1].name" placeholder="姓名">
      <input type="text" name="people[1].password" placeholder="密码"><br>
      person:
      <input type="text" name="person.id" placeholder="编号">
      <input type="text" name="person.name" placeholder="姓名">
      <input type="text" name="person.password" placeholder="密码"><br>
      <input type="submit" value="提交">
    </form>
  </body>
</html>

6.5、中文乱码

6.5.1、GET 方式请求出现的中文乱码

使用 String 的getBytes(“ISO-8859-1”)方法,先转换为 byte[] ,再创建一个String,既 String name=new String(bytes,”UTF-8”);

6.5.2、POST 方式请求出现的中文乱码
<!-- 配置编码过滤 -->
<filter>
    <filter-name>EncoidingFilter</filter-name>
    <filter-class>cn.winkto.controller.EncoidingFilter</filter-class>

    <init-param>
        <param-name>Encoding</param-name>
        <param-value>utf-8</param-value>
    </init-param>
</filter>

<filter-mapping>
    <filter-name>EncoidingFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

6.6、自定义类型转换

6.6.1、日期类型转换
@RequestMapping("/parameter5")
@ResponseBody
public String parameter5(Date date){
    return date.toString();
}
<form action="${pageContext.request.contextPath}/parameter5" method="post">
  <input type="text" name="date">
  <input type="submit" value="提交">
</form>
2020/02/02
Sun Feb 02 00:00:00 CST 2020

以/分割确实没有什么问题,但是一旦使用-分割就出现错误

6.6.2、自定义类型转换

自定义转换器

public class DateConverter implements Converter<String, Date> {
    public Date convert(String s) {
        SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        try {
            return simpleDateFormat.parse(s);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return null;
    }
}

配置转换器

<bean id="converter" class="org.springframework.context.support.ConversionServiceFactoryBean">
    <property name="converters">
        <set>
            <bean class="cn.winkto.converter.DateConverter" />
        </set>
    </property>
</bean>

启动转换器

<mvc:annotation-driven conversion-service="converter" />

测试

2020-02-02 10:19:00
Sun Feb 02 10:19:00 CST 2020

6.7、@RequestParam

当请求的参数name名称与Controller的业务方法参数名称不一致时,就需要通过@RequestParam注 解显示的绑定

@RequestMapping("/parameter6")
@ResponseBody
public String parameter6(@RequestParam(value = "a",defaultValue = "0",required = false) int id){
    return id+"";
}
http://localhost:8080/springmvc_war_exploded/parameter6
0
http://localhost:8080/springmvc_war_exploded/parameter6?a=1
1

6.8、@RequestHeader、@CookieValue

@RequestMapping("/parameter7")
@ResponseBody
public String parameter7(@RequestHeader("cookie") String cookie){
    return cookie;
}
@RequestMapping("/parameter8")
@ResponseBody
public String parameter8(@CookieValue("JSESSIONID") String JSESSIONID){
    return JSESSIONID;
}

6.9、原生servlet的获取

@RequestMapping("/parameter9")
@ResponseBody
public String parameter9(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, HttpSession httpSession){
    System.out.println(httpServletRequest);
    System.out.println(httpServletResponse);
    System.out.println(httpSession);
    return "servlet";
}

7、SpringMVC响应

7.1、页面跳转

7.1.1、返回字符串逻辑视图
@RequestMapping("/hello")
public String hello(){
    return "hello";
}
7.1.2、原始ServletAPI
@RequestMapping("/hello1")
public void hello1(HttpServletRequest httpServletRequest,HttpServletResponse httpServletResponse) throws ServletException, IOException {
    httpServletRequest.getRequestDispatcher("/WEB-INF/jsp/hello.jsp").forward(httpServletRequest,httpServletResponse);
}
@RequestMapping("/hello2")
public void hello2(HttpServletRequest httpServletRequest,HttpServletResponse httpServletResponse) throws ServletException, IOException {
    httpServletResponse.sendRedirect(httpServletRequest.getContextPath()+"/hello");
}
7.1.3、ModelAndView
@RequestMapping("/hello3")
public ModelAndView hello(ModelAndView modelAndView) {
    modelAndView.setViewName("hello");
    return modelAndView;
}

7.2、返回数据

@RequestMapping("/hello4")
@ResponseBody
public String hello4() {
    return "hello";
}

7.3、 转发和重定向

7.3.1、原始ServletAPI
@RequestMapping("/hello1")
public void hello1(HttpServletRequest httpServletRequest,HttpServletResponse httpServletResponse) throws ServletException, IOException {
    httpServletRequest.getRequestDispatcher("/WEB-INF/jsp/hello.jsp").forward(httpServletRequest,httpServletResponse);
}
@RequestMapping("/hello2")
public void hello2(HttpServletRequest httpServletRequest,HttpServletResponse httpServletResponse) throws ServletException, IOException {
    httpServletResponse.sendRedirect(httpServletRequest.getContextPath()+"/hello");
}
7.3.2、springmvc
@RequestMapping("/hello5")
public String hello5() {
    return "forward:/WEB-INF/jsp/hello.jsp";
}
@RequestMapping("/hello6")
public String hello6() {
    return "redirect:/hello";
}

7.4、@SessionAttributes

  • 如果在多个请求之间共用数据,则可以在控制器类上标注一个 @SessionAttributes,配置需要在 session中存放的数据范围,Spring MVC将存放在model中对应的数据暂存到 HttpSession 中
  • 只能放置在控制器类上

7.5、静态资源访问的开启

7.5.1、处理1
<mvc:resources mapping="/js/**" location="/js/"/>
7.5.2、处理2
<mvc:default-servlet-handler/>

8、@ResponseBody

用于将Controller的方法返回的对象,通过HttpMessageConverter接口转换为指定格式的数 据如:json,xml等,通过Response响应给客户端

9、RestFul

Restful是一种软件架构风格、设计风格,而不是标准,只是提供了一组设计原则和约束条件。主要用 于客户端和服务器交互类的软件,基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存机 制等。 Restful风格的请求是使用“url+请求方式”表示一次请求目的的

9.1、方式对比

传统方式

http://127.0.0.1/item/queryItem.action?id=1 查询,GET
http://127.0.0.1/item/saveItem.action 新增,POST
http://127.0.0.1/item/updateItem.action 更新,POST
http://127.0.0.1/item/deleteItem.action?id=1 删除,GET或POST

RestFul风格

http://127.0.0.1/item/1 查询,GET
http://127.0.0.1/item 新增,POST
http://127.0.0.1/item 更新,PUT
http://127.0.0.1/item/1 删除,DELETE

9.2、Restful的好处

  • 使路径变得更加简洁
  • 获得参数更加方便,框架会自动进行类型转换
  • 通过路径变量的类型可以约束访问参数,如果类型不一样,则访问不到对应的请求方法,如这里访问是的路径是/commit/1/a,则路径与方法不匹配,而不会是参数转换失败

9.3、Restful的使用

  • @GetMapping
  • @PostMapping
  • @PutMapping
  • @DeleteMapping
  • @PatchMapping
//基本类型
@GetMapping("/restful1/{a}")
@ResponseBody
public String restful1(@PathVariable int a) {
    return a+"";
}
//对象类型
@GetMapping("/restful2/{id}/{name}/{password}")
@ResponseBody
public String restful2(Person person) {
    return person.toString();
}
http://localhost:8080/springmvc_war_exploded/restful1/1
http://localhost:8080/springmvc_war_exploded/restful2/1/zhangsan/lisi

10、文件

10.1、文件上传三要素

  • 表单项 type=“file”
  • 表单的提交方式 method=“POST”
  • 表单的enctype属性是多部分表单形式 enctype=“multipart/form-data"

10.2、文件上传原理

  • 当form表单修改为多部分表单时,request.getParameter()将失效
  • 当form表单的enctype取值为 application/x-www-form-urlencoded 时, form表单的正文内容格式是: name=value&name=value
  • 当form表单的enctype取值为 mutilpart/form-data 时,请求正文内容就变成多部分形式

10.3、文件上传的实现

导入依赖

<dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.4</version>
</dependency>

配置文件上传解析器

<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <property name="defaultEncoding" value="utf-8"></property>
    <!-- 设定文件上传的最大值为5MB,5*1024*1024 -->
    <property name="maxUploadSize" value="5242880"></property>
    <!-- 设定文件上传时写入内存的最大值,如果小于这个参数不会生成临时文件,默认为10240 -->
    <property name="maxInMemorySize" value="40960"></property>
</bean>

配置接口

@Controller
public class FileLoad {
    //传统方式
    @RequestMapping("/upload")
    public String upload(@RequestParam("file") CommonsMultipartFile file, HttpServletRequest request) throws IOException {
        String filename = file.getOriginalFilename();
        if ("".equals(filename)){
            return "redirect:/index.jsp";
        }
        System.out.println(filename);
        String path=request.getServletContext().getRealPath("upload");
        File file1=new File(path);
        if (!file1.exists()){
            file1.mkdir();
        }
        System.out.println(path);
        InputStream inputStream=file.getInputStream();
        OutputStream outputStream=new FileOutputStream(new File(path,filename));
        int len=0;
        byte[] bytes= new byte[1024];
        while ((len=inputStream.read(bytes))!=-1){
            outputStream.write(bytes,0,len);
            outputStream.flush();
        }
        inputStream.close();
        outputStream.close();
        System.out.println("ok===================");
        return "redirect:/index.jsp";
    }
    //springmvc方式
    @RequestMapping("upload1")
    public String upload1(@RequestParam("file") CommonsMultipartFile file, HttpServletRequest request) throws IOException {
        String path=request.getServletContext().getRealPath("upload");
        File file1=new File(path);
        if (!file1.exists()){
            file1.mkdir();
        }
        System.out.println(path);
        file.transferTo(new File(path+"/"+file.getOriginalFilename()));
        return "redirect:/index.jsp";
    }
}

jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>$Title$</title>
  </head>
  <body>
  <form action="${pageContext.request.contextPath}/upload" method="post" enctype="multipart/form-data">
    <input type="file" name="file">
    <input type="submit" value="Submit">
  </form>
  </body>
</html>

10.4、文件下载

接口

@Controller
public class FileLoad {
    @RequestMapping("/download")
    public String downloads(HttpServletResponse response , HttpServletRequest request) throws Exception{
        //要下载的图片地址
        String  path = request.getServletContext().getRealPath("/upload");
        String  fileName = "1.png";

        //1、设置response 响应头
        response.reset(); //设置页面不缓存,清空buffer
        response.setCharacterEncoding("UTF-8"); //字符编码
        response.setContentType("multipart/form-data"); //二进制传输数据
        //设置响应头
        response.setHeader("Content-Disposition",
                "attachment;fileName="+ URLEncoder.encode(fileName, "UTF-8"));

        File file = new File(path,fileName);
        //2、 读取文件--输入流
        InputStream input=new FileInputStream(file);
        //3、 写出文件--输出流
        OutputStream out = response.getOutputStream();

        byte[] buff =new byte[1024];
        int index=0;
        //4、执行 写出操作
        while((index= input.read(buff))!= -1){
            out.write(buff, 0, index);
            out.flush();
        }
        out.close();
        input.close();
        return null;
    }
}

jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>$Title$</title>
  </head>
  <body>
  <a href="${pageContext.request.contextPath}/download">1.png</a>
  </body>
</html>

11、拦截器

Spring MVC 的拦截器类似于 Servlet 开发中的过滤器 Filter,用于对处理器进行预处理和后处理

11.1、拦截器与过滤器的比对

区别过滤器拦截器
使用范围任何java web项目只有springmvc项目才可以使用
拦截范围url-paten配置了/*后可以对所有资源进行拦截只会拦截控制器方法

11.2、拦截器快速入门

书写拦截器,实现HandlerInterceptor接口

public class MyInterceptor implements HandlerInterceptor {
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("方法前");
        return true;
    }

    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("方法后");
    }

    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("清理操作");
    }
}

springmvc核心配置文件配置拦截器

<mvc:interceptors>
    <mvc:interceptor>
        <!--/** 包括路径及其子路径-->
        <!--/admin/* 拦截的是/admin/add等等这种 , /admin/add/user不会被拦截-->
        <!--/admin/** 拦截的是/admin/下的所有-->
        <mvc:mapping path="/**"/>
        <!--bean配置的就是拦截器-->
        <bean class="cn.winkto.controller.MyInterceptor"/>
    </mvc:interceptor>
</mvc:interceptors>

11.3、拦截器链

开发中拦截器可以单独使用,也可以同时使用多个拦截器形成一条拦截器链。开发步骤和单个拦截器 是一样的,只不过注册的时候注册多个,注意这里注册的顺序就代表拦截器执行的顺序

书写拦截器,实现HandlerInterceptor接口

public class MyInterceptor implements HandlerInterceptor {
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("方法前");
        return true;
    }

    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("方法后");
    }

    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("清理操作");
    }
}
public class MyInterceptor1 implements HandlerInterceptor {
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("方法前");
        return true;
    }

    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("方法后");
    }

    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("清理操作");
    }
}

springmvc核心配置文件配置拦截器

<mvc:interceptors>
    <mvc:interceptor>
        <!--/** 包括路径及其子路径-->
        <!--/admin/* 拦截的是/admin/add等等这种 , /admin/add/user不会被拦截-->
        <!--/admin/** 拦截的是/admin/下的所有-->
        <mvc:mapping path="/**"/>
        <!--bean配置的就是拦截器-->
        <bean class="cn.winkto.controller.MyInterceptor"/>
    </mvc:interceptor>
    <mvc:interceptor>
        <mvc:mapping path="/**"/>
        <!--bean配置的就是拦截器-->
        <bean class="cn.winkto.controller.MyInterceptor1"/>
    </mvc:interceptor>
</mvc:interceptors>

12、异常处理

12.1、异常处理思路

  • 当前方法捕获处理(try-catch),这种处理方式会造成业务代码和异常处理代码的耦合
  • 自己不处理,而是抛给调用者处理(throws),调用者再抛给它的调用者,也就是一直向上抛

在这种方法的基础上,衍生出了SpringMVC的异常处理机制,系统的mapper、service、controller出现都通过throws Exception向上抛出,最后由springmvc前端控 制器交由异常处理器进行异常处理

在这里插入图片描述

12.2、自定义异常处理

编写自定义异常处理器,继承HandlerExceptionResolver接口,书写页面跳转,并注入容器

@Component
public class MyHandlerExceptionResolver implements HandlerExceptionResolver {
    public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
        System.out.println("发生异常了"+e);
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("error");
        return modelAndView;
    }
}

异常页面

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<h1>Error</h1>
</body>
</html>

测试

@RequestMapping("/hello")
public String hello(){
    throw new RuntimeException("啦啦啦");
}

12.3、web的处理异常机制

web.xml

<!--处理500异常-->
<error-page>
    <error-code>500</error-code>
    <!--路径以web目录为基准-->
    <location>/500.jsp</location>
</error-page>
<!--处理404异常-->
<error-page>
    <error-code>404</error-code>
    <!--路径以web目录为基准-->
    <location>/404.jsp</location>
</error-page>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

眼眸流转

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值