SpringBoot的Web开发支持【超详细【一篇搞定】果断收藏系列】

使用spring-boot-starter-web启动器,开始web支持,内嵌一个Tomcat,添加了对于SpringMVC的支持。Spring Boot默认servlet容器为tomcat。

Spring Boot supports the following embedded servlet containers:

NameServletVersion
Tomcat9.04.0
Jetty9.43.1
Undertow2.04.0

常用的服务器配置

  • 配置端口号Spring Boot 默认端口是8080,如果想要进行更改的话,在配置文件中加入:server.port=8081
  • 配置session的超时时间server.servlet.session.timeout=2M

使用Jetty服务器替换Tomcat

项目目录:
在这里插入图片描述

排除Tomcat的启动器,引入Jetty

pom.xml:

<dependencies>

   <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
        <exclusions>
            <exclusion>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-tomcat</artifactId>
            </exclusion>
        </exclusions>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-jetty</artifactId>
    </dependency>
    
</dependencies>

在这里插入图片描述

application.yml

application.yml:

server:
  port: 80

编写入口程序

入口程序:

package com.keafmd;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * Keafmd
 *
 * @ClassName: App03
 * @Description:
 * @author: 牛哄哄的柯南
 * @Date: 2021-04-06 13:57
 * @Blog: https://keafmd.blog.csdn.net/
 */
@SpringBootApplication
public class App03 {
    public static void main(String[] args) {
        SpringApplication.run(App03.class,args);
    }
}

编写Controller测试

Controller测试:

package com.keafmd.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * Keafmd
 *
 * @ClassName: JettyController
 * @Description:
 * @author: 牛哄哄的柯南
 * @Date: 2021-04-06 13:56
 * @Blog: https://keafmd.blog.csdn.net/
 */
@RestController
public class JettyController {

    /**
     * http://127.0.0.1:80/hello
     * @return
     */

    @GetMapping("/hello")
    public String hello(){

        return "hello keafmd";
    }

}

测试结果

运行启动类,效果如下:
在这里插入图片描述

访问:http://127.0.0.1:80/hello
在这里插入图片描述

Jetty对jsp的支持

添加依赖

springboot中的jetty为内嵌的jetty,支持jsp需要添加额外的依赖。

在pom.xml中添加如下依赖:

<!--jetty容器支持jsp start-->
      <dependency>
          <groupId>org.eclipse.jetty</groupId>
          <artifactId>jetty-server</artifactId>
      </dependency>
      <dependency>
          <groupId>org.eclipse.jetty</groupId>
          <artifactId>apache-jsp</artifactId>
      </dependency>
      <dependency>
          <groupId>org.eclipse.jetty</groupId>
          <artifactId>apache-jstl</artifactId>
      </dependency>
<!--jetty容器支持jsp end-->

SpringBoot集成使用jsp

需要设置:SpringBoot集成使用jsp(超详细)

编写一个jsp

在这里插入图片描述
注意是在webapp的目录下。

index.jsp:

<%--
  Created by IntelliJ IDEA.
  User: lenovo
  Date: 2021/4/6
  Time: 14:41
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<h1>Keafmd</h1>

</body>
</html>

编写Controller

JspController:

package com.keafmd.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

/**
 * Keafmd
 *
 * @ClassName: JspController
 * @Description:
 * @author: 牛哄哄的柯南
 * @Date: 2021-04-06 14:43
 * @Blog: https://keafmd.blog.csdn.net/
 */
@Controller
public class JspController {

    /**
     * http://127.0.0.1/keafmd
     * @return
     */

    @GetMapping("/keafmd")
    public String keafmd(){
        return "/index.jsp";
    }

}

测试结果

我提前配置好了80端口。
访问:http://127.0.0.1/keafmd

在这里插入图片描述

配置上下文

application.yml:

server:
  port: 80
spring:
  mvc:
    view:
      prefix: /WEB-INF/user/
      suffix: .jsp

编写user_list.jsp

在这里插入图片描述
user_list.jsp:

<%--
  Created by IntelliJ IDEA.
  User: lenovo
  Date: 2021/4/6
  Time: 14:45
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<h1>User_List</h1>

</body>
</html>

编写Controller

JspController:

package com.keafmd.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

/**
 * Keafmd
 *
 * @ClassName: JspController
 * @Description:
 * @author: 牛哄哄的柯南
 * @Date: 2021-04-06 14:43
 * @Blog: https://keafmd.blog.csdn.net/
 */
@Controller
public class JspController {

    /**
     * http://127.0.0.1/keafmd
     * @return
     */

    @GetMapping("/keafmd")
    public String keafmd(){
        return "/index.jsp";
    }

    @GetMapping("/userlist")
    public String userlist(){
        return "user_list";
    }


}

测试结果

访问:http://127.0.0.1/userlist
在这里插入图片描述

打包(jar和war)

区别:打jar包不能访问jsp资源,war包可以。

引入所需的插件

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <configuration>
                <fork>true</fork>
            </configuration>
        </plugin>
    </plugins>
</build>

打包

在这里插入图片描述

打开war包所在文件位置

在这里插入图片描述

在此处打开cmd,输入启动的命令

java -jar xxxxx.war/.jar

在这里插入图片描述

访问jsp页面

在这里插入图片描述

在这里插入图片描述

打jar包的话是访问不到user_list.jsp的,这里就不测试了。

对静态资源的配置

把类路径下的 /static、/public、/resources 和 /META-INF/resources 文件夹下的静态文件直接映射为 /,可以直接通过 http://localhost:8080/ 访问。

在resources下创建static目录,在创建common目录,然后创建tt.css。
在这里插入图片描述
访问:http://127.0.0.1:8080/common/tt.css

在这里插入图片描述

自定义资源映射

static-locations

默认支持的文件路径:classpath:/static,classpath:/public,classpath:/resources,classpath:/META-INF/resources
在这里插入图片描述
mm.css:

body{
    padding: 0;
}

tt.css:

body{
    margin: 0;
    padding: 0;
}

在我们没有在application.yml配置文件配置前,访问:http://localhost:8080/mm.css,结果如下↓
在这里插入图片描述

因为mm.css在自定义的mystatic文件夹下,不被静态资源识别,需要自定义。

但是可以直接访问:http://localhost:8080/common/tt.css,因为tt.css在static文件夹下。
在这里插入图片描述
当我们在application.yml配置文件夹下添加上自定义的文件夹后就可以访问了。

application.yml:

spring:
  mvc:
    static-path-pattern: /**
  web:
    resources:
      static-locations: classpath:/mystatic,classpath:/static,classpath:/public,classpath:/resources,classpath:/META-INF/resources

访问:http://localhost:8080/mm.css,结果如下↓,配置后可以直接访问。
在这里插入图片描述

static-path-pattern

当我们修改application.xml文件后:

spring:
  mvc:
    static-path-pattern: /css/**
  web:
    resources:
      static-locations: classpath:/mystatic,classpath:/static,classpath:/public,classpath:/resources,classpath:/META-INF/resources

像上面那样访问都是失败的了
在这里插入图片描述
在这里插入图片描述
我们需要加上/css才可以
在这里插入图片描述
在这里插入图片描述

配置自定义的Convert解决日期类型的参数转换

Convert、Formatter:用于接收浏览器请求的参数自动转化成响应类型的数据Stirng(1988-01-01)-Date(1988-01-01)

在这里插入图片描述

User:

package com.keafmd.entity;

import lombok.Data;

import java.util.Date;

/**
 * Keafmd
 *
 * @ClassName: User
 * @Description:
 * @author: 牛哄哄的柯南
 * @Date: 2021-04-07 9:53
 * @Blog: https://keafmd.blog.csdn.net/
 */
@Data
public class User {
    private String id;
    private Integer age;
    private String address;
    private Date createTime;
}

ConverterController:

package com.keafmd.controller;

import com.keafmd.entity.User;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * Keafmd
 *
 * @ClassName: ConverterController
 * @Description:
 * @author: 牛哄哄的柯南
 * @Date: 2021-04-07 9:54
 * @Blog: https://keafmd.blog.csdn.net/
 */
@RestController
public class ConverterController {


    /**
     * http://127.0.0.1:8080/user?createTime=2021-04-07 01:02:03
     * @param user
     * @return
     */
    @GetMapping("/user")
    User getUserInfo(User user){
        return user;
    }
}

DateConverter:

package com.keafmd.config;

import org.springframework.core.convert.converter.Converter;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
 * Keafmd
 *
 * @ClassName: DateConverter
 * @Description:
 * @author: 牛哄哄的柯南
 * @Date: 2021-04-07 9:58
 * @Blog: https://keafmd.blog.csdn.net/
 */
public class DateConverter implements Converter<String, Date> {
    /**
     * yyyy-MM-dd
     *
     * @param source
     * @return
     */
    @Override
    public Date convert(String source) {
        try {
            return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(source);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return null;
    }


}

BootWebMvcConfig:

package com.keafmd.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.format.FormatterRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;


/**
 * Keafmd
 *
 * @ClassName: BootWebMvcConfig
 * @Description:
 * @author: 牛哄哄的柯南
 * @Date: 2021-04-07 10:27
 * @Blog: https://keafmd.blog.csdn.net/
 */
@Configuration(proxyBeanMethods = false)
public class BootWebMvcConfig implements WebMvcConfigurer {

    @Override
    public void addFormatters(FormatterRegistry registry) {
        registry.addConverter(new DateConverter());
    }
}

还需要在application.yml配置一下时区和格式。

application.yml:

spring:
  jackson:
    time-zone: GMT+8
    date-format: yyyy-MM-dd HH:mm:ss

启动springboot,访问:http://127.0.0.1:8080/user?createTime=2021-04-07 01:02:03
在这里插入图片描述

自定义拦截器的配置

实现基础springmvc的拦截器

自定义类实现HandlerInterceptor接口

MyInterceptor:

package com.keafmd.config;

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

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Keafmd
 *
 * @ClassName: MyInterceptor
 * @Description:
 * @author: 牛哄哄的柯南
 * @Date: 2021-04-07 11:41
 * @Blog: https://keafmd.blog.csdn.net/
 */
public class MyInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("MyInterceptor.preHandle");
        return true;
    }

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

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

在这里插入图片描述

使用Java的形式配置拦截器的拦截路径

在WebMvcConfig中注册拦截器,实现WebMvcConfigrer接口,并声明Bean。

BootWebMvcConfig:

package com.keafmd.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.format.FormatterRegistry;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.util.List;


/**
 * Keafmd
 *
 * @ClassName: BootWebMvcConfig
 * @Description:
 * @author: 牛哄哄的柯南
 * @Date: 2021-04-07 10:27
 * @Blog: https://keafmd.blog.csdn.net/
 */
@Configuration(proxyBeanMethods = false)
public class BootWebMvcConfig implements WebMvcConfigurer {

    @Override
    public void addFormatters(FormatterRegistry registry) {
        registry.addConverter(new DateConverter());
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //注册拦截
        registry.addInterceptor(new MyInterceptor()).addPathPatterns("/**");
    }

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {

    }

    @Override
    public void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) {

    }
}

自定义页面跳转

BootWebMvcConfig:

package com.keafmd.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.format.FormatterRegistry;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.util.List;


/**
 * Keafmd
 *
 * @ClassName: BootWebMvcConfig
 * @Description:
 * @author: 牛哄哄的柯南
 * @Date: 2021-04-07 10:27
 * @Blog: https://keafmd.blog.csdn.net/
 */
@Configuration(proxyBeanMethods = false)
public class BootWebMvcConfig implements WebMvcConfigurer {

    @Override
    public void addFormatters(FormatterRegistry registry) {
        registry.addConverter(new DateConverter());
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //注册拦截
        registry.addInterceptor(new MyInterceptor()).addPathPatterns("/**");
    }



    /**
     * 映射自定义的跳转界面
     * @param registry
     */
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/index").setViewName("index.html");
        registry.addViewController("/home").setViewName("index.html");

    }

}

自定义资源映射

1、自动配置(在全局额配置文件中修改)

spring.mvc.static-path-pattern=/
spring.resources.static-locations= classpath:/static,classpath:/public,classpath:/resources,classpath:/META-INF/resources

2、自定义资源路径

自定义资源映射,重写WebMvcConfiger实现类的 重写addResourceHandler 方法
调用:addResourceHandler 用于处理哪些路径是静态资源
调用:addResourceLocations用于指定静态资源的实际目录
此方法会覆盖配置文件和默认的静态资源配置

BootWebMvcConfig:

package com.keafmd.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.format.FormatterRegistry;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.util.List;


/**
 * Keafmd
 *
 * @ClassName: BootWebMvcConfig
 * @Description:
 * @author: 牛哄哄的柯南
 * @Date: 2021-04-07 10:27
 * @Blog: https://keafmd.blog.csdn.net/
 */
@Configuration(proxyBeanMethods = false)
public class BootWebMvcConfig implements WebMvcConfigurer {

    @Override
    public void addFormatters(FormatterRegistry registry) {
        registry.addConverter(new DateConverter());
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //注册拦截
        registry.addInterceptor(new MyInterceptor()).addPathPatterns("/**");
    }

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {

        /**
         * http://127.0.0.1:8080/images/holiday.png
         */
        // registry.addResourceHandler()
        // registry.addResourceHandler("/images/").addResourceLocations("classpath:/imgs/");
        registry.addResourceHandler("/images/**").
                addResourceLocations("classpath:/imgs/",
                        "classpath:/mystatic/" ,
                        "classpath:/static/" ,
                        "classpath:/public/" ,
                        "classpath:/META-INF/resources",
                        "classpath:/resources");

    }
}

错误处理、异常处理

错误的类型:

  • 因为后台程序出错导致的Exception(http 500)

  • 因为参数传递错误(http 400)

  • 客户端的原因造成的路径不对(http 404)

当有错误产生,默认跳转到/error,指向的是BasicErrorController。

定制错误响应:
1、有模板引擎的情况下;error/状态码; 【将错误页面命名为 错误状态码.html 放在模板引擎文件夹里面的error文件夹下】,发生此状态码的错误就会来到对应的页面
2、没有模板引擎(模板引擎找不到这个错误页面),静态资源文件夹下找
3、以上都没有错误页面,就是默认来到Spring Boot默认的错误提示页面
可以使用4xx和5xx作为错误页面的文件名来匹配这种类型的所有错误,精确优先(优先寻找精确的状态码.html)

页面能获取的信息:
timestamp:时间戳
status:状态码
error:错误提示
exception:异常对象
message:异常消息
errors:JSR303数据校验的错误都在这里

在WebMvcConfiger的实现类中重写addViewConroller方法。

使用Java异常处理器

1、在Controller层面定义异常处理,哪里有异常哪里处理,只在某一个Controller中生效

JspController:

package com.keafmd.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Keafmd
 *
 * @ClassName: JspController
 * @Description:
 * @author: 牛哄哄的柯南
 * @Date: 2021-04-07 14:09
 * @Blog: https://keafmd.blog.csdn.net/
 */
@Controller
public class JspController {
    /**
     * http://127.0.0.1:8080/toview
     * @return
     */
    @GetMapping("/toview")
    String toview(){
        return "/hello.jsp";
    }


    @GetMapping("/business")
    String business(){
        int result = 0/0;
        return "/index.jsp";
    }


   /* @ExceptionHandler(value = Exception.class )
    @ResponseBody
    String resolveException(HttpServletRequest request, HttpServletResponse response, Exception ex  ){

        System.out.println(ex.getMessage());
        return "{status:'unup',msg:'出错了'}";
    }*/
}

2、定义全局的异常处理方式,定义一个类使用@ControllerAdvice ,在类中定义@ExceptionHandler的注解方法。

MyControllerAdvice:

package com.keafmd.controller;

import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Keafmd
 *
 * @ClassName: MyControllerAdvice
 * @Description:
 * @author: 牛哄哄的柯南
 * @Date: 2021-04-07 14:07
 * @Blog: https://keafmd.blog.csdn.net/
 */
@RestControllerAdvice
public class MyControllerAdvice {

    @ExceptionHandler(value = Exception.class )
//    @ResponseBody
    String resolveException(HttpServletRequest request, HttpServletResponse response, Exception ex  ){

        System.out.println(ex.getMessage());
        return "{status:'unup',msg:'全局的处理,Controller出错了'}";
    }
}

效果:
在这里插入图片描述

文件上传与下载

项目目录

新建个项目:springboot-file
在这里插入图片描述

pom.xml

pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.keafmd</groupId>
    <artifactId>springboot-file</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>


    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.4.4</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>


    <dependencies>

        <!--devtools-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
        </dependency>


        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.apache.tomcat.embed</groupId>
            <artifactId>tomcat-embed-jasper</artifactId>
        </dependency>

        <dependency>
            <groupId>jstl</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>

        <!-- 解析jsp类库  -->
        <dependency>
            <groupId>org.apache.tomcat.embed</groupId>
            <artifactId>tomcat-embed-jasper</artifactId>
        </dependency>
    </dependencies>



</project>

启动类

启动类AppFile:

package com.keafmd;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * Keafmd
 *
 * @ClassName: AppFile
 * @Description:
 * @author: 牛哄哄的柯南
 * @Date: 2021-04-07 15:08
 * @Blog: https://keafmd.blog.csdn.net/
 */

@SpringBootApplication
public class AppFile {
    public static void main(String[] args) {
        SpringApplication.run(AppFile.class,args);
    }
}

controller

BootConstants:

package com.keafmd.controller;

/**
 * Keafmd
 *
 * @ClassName: BootConstants
 * @Description:
 * @author: 牛哄哄的柯南
 * @Date: 2021-04-07 16:07
 * @Blog: https://keafmd.blog.csdn.net/
 */
public interface BootConstants {
    public static final String UPLOAD_DIR ="D:\\upload";
}

FileUploadController :

package com.keafmd.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.util.UUID;

/**
 * Keafmd
 *
 * @ClassName: FileUploadController
 * @Description:
 * @author: 牛哄哄的柯南
 * @Date: 2021-04-07 15:05
 * @Blog: https://keafmd.blog.csdn.net/
 */
@Controller
public class FileUploadController {


    @PostMapping("upload")
    String upload(MultipartFile pic) throws IOException {
        //1 将临时空间的文件,转储到 D:\\upload
        String originalFileName = pic.getOriginalFilename();
        //扩展名
        String ext = originalFileName.substring(originalFileName.lastIndexOf("."));
        //转储的新文件名
        String newFileName = UUID.randomUUID().toString() + ext;
        //转储到 D:\\upload 下的  uuid.png/uuid.jpg
        pic.transferTo(new File(BootConstants.UPLOAD_DIR, newFileName));
        //2 将数据存储到 db
        /**
         * 当前时间
         * 上传的ip
         * 操作的工号
         * 上传的文件名
         *
         */

        //3 跳转到列表页

        return "redirect:/list";
    }


    @GetMapping("list")
    String list(Model model) throws IOException {

        File[] list = new File(BootConstants.UPLOAD_DIR).listFiles();

        model.addAttribute("fileList",list);

        return "/list.jsp";
    }

}

DownloadController :

package com.keafmd.controller;

import org.springframework.core.io.FileSystemResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

import javax.servlet.http.HttpServletResponse;
import java.io.*;

/**
 * Keafmd
 *
 * @ClassName: DownloadController
 * @Description:
 * @author: 牛哄哄的柯南
 * @Date: 2021-04-07 16:10
 * @Blog: https://keafmd.blog.csdn.net/
 */
@Controller
public class DownloadController {


    /**
     * 3000
     *
     * 1024  1024 (2048)   954
     *
     *
     * @param path
     * @param response
     * @throws IOException
     */

    @GetMapping("/d1/{path}")
    public void download(@PathVariable String path , HttpServletResponse response) throws IOException {

        response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
        response.addHeader(HttpHeaders.CONTENT_DISPOSITION,"attachment;filename="+path);

        InputStream is = new FileInputStream(new File(BootConstants.UPLOAD_DIR,path));
        OutputStream os = response.getOutputStream();
        int len = -1;
        byte[] bytes = new byte[1024];
        while (   (len = is.read(bytes)) != -1){
            os.write(bytes,0,len);
        }
        os.close();
        is.close();
    }

    @GetMapping("/d2/{path}")
    public ResponseEntity download2(@PathVariable String path ) throws IOException {

        return ResponseEntity.ok().
                header(HttpHeaders.CONTENT_TYPE,"application/octet-stream").
                header(HttpHeaders.CONTENT_DISPOSITION,"attachment;filename="+path).
                body(new FileSystemResource(new File(BootConstants.UPLOAD_DIR,path)));
    }


}

AppConfig :

package com.keafmd.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 * Keafmd
 *
 * @ClassName: AppConfig
 * @Description:
 * @author: 牛哄哄的柯南
 * @Date: 2021-04-07 16:05
 * @Blog: https://keafmd.blog.csdn.net/
 */
@Configuration
public class AppConfig implements WebMvcConfigurer {

    /**
     * http://127.0.0.1/form
     * @param registry
     */
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/form").setViewName("/upload.jsp");
    }


    /**
     * http://127.0.0.1/down/ae37a66f-aec3-4e23-b2ed-7267adcfb2bb.png
     * @param registry
     */
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/down/**").addResourceLocations("file:D:\\upload\\");
    }

}

application.yml

server:
  port: 80

SpringBoot集成使用jsp(超详细)

点这里:SpringBoot集成使用jsp(超详细)

jsp

list.jsp:

<%--
  Created by IntelliJ IDEA.
  User: lenovo
  Date: 2021/4/7
  Time: 15:07
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
    <title>Title</title>
</head>
<body>

<table border="1" cellspacing="0" cellpadding="0" width="100%">
    <tr>
        <th>序号</th>
        <th>文件名称</th>
        <th>操作</th>
    </tr>

    <c:forEach items="${fileList}" var="file" varStatus="stat">
        <tr>
            <td>${stat.count}</td>
            <td>${file.getName()}</td>
            <td>
                <a href="${pageContext.request.contextPath}/down/04971284-d789-470a-a991-4d690c36b4ac.jpg">下载1</a>
                <a href="${pageContext.request.contextPath}/d1/04971284-d789-470a-a991-4d690c36b4ac.jpg">下载2</a>
                <a href="${pageContext.request.contextPath}/d2/04971284-d789-470a-a991-4d690c36b4ac.jpg">下载3</a>
            </td>
        </tr>
    </c:forEach>
</table>
</body>
</html>

upload.jsp:

<%--
  Created by IntelliJ IDEA.
  User: lenovo
  Date: 2021/4/7
  Time: 16:10
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>

<form method="post" action="${pageContext.request.contextPath}/upload" enctype="multipart/form-data">

    <input type="file" name="pic">


    <input type="submit" value="上传头像" >

</form>



</body>
</html>

效果

上传:
在这里插入图片描述
下载:
在这里插入图片描述

SpringBoot数据校验

问题引入

      我们在传参的时候,有时候需要对传的参数进行验证是否符合要求,这就需要就行数据校验了。

样例代码

说明:SpringBoot的2.2.x版本之前,如果使用starter-web默认包含校验框架,2.3.x之后或者没有使用starter-web,需要添加starter-validation的校验框架。
在这里插入图片描述

common的pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>spring-boot-02</artifactId>
        <groupId>com.keafmd</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>common</artifactId>
<dependencies>
    <dependency>
        <groupId>org.hibernate.validator</groupId>
        <artifactId>hibernate-validator</artifactId>
    </dependency>
</dependencies>

</project>

spring-boot-06的pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.4.4</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.keafmd</groupId>
    <artifactId>spring-boot-06</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>spring-boot-06</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.keafmd</groupId>
            <artifactId>common</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

        <dependency>
            <groupId>org.hibernate.validator</groupId>
            <artifactId>hibernate-validator</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

common的实体类User:

package com.keafmd.entity;

import lombok.Data;

import javax.validation.constraints.Max;
import java.util.Date;

/**
 * Keafmd
 *
 * @ClassName: User
 * @Description:
 * @author: 牛哄哄的柯南
 * @Date: 2021-04-08 9:07
 * @Blog: https://keafmd.blog.csdn.net/
 */
@Data
public class User {

    private String id;

    @Max(value = 18,message = "年龄不符合")
    private Integer age;
    private String address;
    private Date createTime;
}

UserController:

package com.keafmd.controller;

import com.keafmd.entity.User;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * Keafmd
 *
 * @ClassName: UserController
 * @Description:
 * @author: 牛哄哄的柯南
 * @Date: 2021-04-08 9:10
 * @Blog: https://keafmd.blog.csdn.net/
 */
@RestController
@RequestMapping("user")
public class UserController {

    /**
     * http://127.0.0.1/user/save?age=20
     * @param user
     * @return
     */
    @RequestMapping("save")
    User save(@Validated User user,BindingResult bindingResult){
        System.out.println(bindingResult.getFieldError().getDefaultMessage());
        return user;
    }

}

SpringBoot06Application

package com.keafmd;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SpringBoot06Application {

    public static void main(String[] args) {
        SpringApplication.run(SpringBoot06Application.class, args);
    }

}

效果

浏览器访问:http://127.0.0.1/user/save?age=20

在这里插入图片描述
idea控制台的输出信息:
在这里插入图片描述

注册Servlet三大组件【Servlet、Filter、Listener】

使用ServletComponentScan注解扫描

在这里插入图片描述

在启动类上添加@ServletComponentScan

SpringBoot06Application:

package com.keafmd;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;

@SpringBootApplication
@ServletComponentScan
public class SpringBoot06Application {

    public static void main(String[] args) {
        SpringApplication.run(SpringBoot06Application.class, args);
    }

}

定义Servlet

FirstSerlvet :

package com.keafmd.servletcomponent;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * Keafmd
 *
 * @ClassName: FirstSerlvet
 * @Description:
 * @author: 牛哄哄的柯南
 * @Date: 2021-04-08 9:55
 * @Blog: https://keafmd.blog.csdn.net/
 */

/**
 * http://127.0.0.1/my
 */
@WebServlet(urlPatterns = "/my")
public class FirstSerlvet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("FirstSerlvet.doPost");
        System.out.println("sessionid: "+req.getSession().getId());
    }
}

定义的Filter

FirstFilter:

package com.keafmd.servletcomponent;


import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;

/**
 * Keafmd
 *
 * @ClassName: FirstFilter
 * @Description:
 * @author: 牛哄哄的柯南
 * @Date: 2021-04-08 9:56
 * @Blog: https://keafmd.blog.csdn.net/
 */
@WebFilter(urlPatterns="/*")
public class FirstFilter implements Filter {
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("FirstFilter.doFilter");
        filterChain.doFilter(servletRequest,servletResponse);
    }
}

定义Listener

FirstListener:

package com.keafmd.servletcomponent;

import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

/**
 * Keafmd
 *
 * @ClassName: FirstListener
 * @Description:
 * @author: 牛哄哄的柯南
 * @Date: 2021-04-08 9:57
 * @Blog: https://keafmd.blog.csdn.net/
 */
@WebListener
public class FirstListener implements HttpSessionListener {
    @Override
    public void sessionCreated(HttpSessionEvent se) {
        System.out.println("FirstListener.sessionCreated: Session被创建");
    }
}

效果

访问:http://127.0.0.1/my

访问后,前端不会有什么效果。
在这里插入图片描述
idea的控制台的输出证明使用成功。
在这里插入图片描述
注意:当我们二次访问http://127.0.0.1/my的时候session应该是一样的。
在这里插入图片描述

使用registration的Bean注册组件

三大组件使用代码(不需要,@WebListener、@WebServlet(urlPatterns = “/servlet”)、@WebFilter(urlPatterns = “/*”))

在这里插入图片描述
pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.4.4</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.keafmd</groupId>
    <artifactId>spring-boot-07</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>spring-boot-07</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

application.yml:

server:
  port: 80

使用@Bean配合RegistrationBean类型注册

Appconfig:

package com.keafmd.servlet.config;

import com.keafmd.servlet.component.MySessionListener;
import com.keafmd.servlet.component.SecondFilter;
import com.keafmd.servlet.component.SecondServlet;

import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletListenerRegistrationBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 * Keafmd
 *
 * @ClassName: Appconfig
 * @Description:
 * @author: 牛哄哄的柯南
 * @Date: 2021-04-08 17:40
 * @Blog: https://keafmd.blog.csdn.net/
 */
@Configuration(proxyBeanMethods = false)
public class Appconfig implements WebMvcConfigurer {


    // 使用@Bean配合RegistrationBean类型注册 -- star
    /**
     *  http://127.0.0.1:80/sec
     *  http://127.0.0.1:80/second
     * @return
     */
    @Bean
    ServletRegistrationBean getServletRegistrationBean(){
        ServletRegistrationBean<SecondServlet> registrationBean = new ServletRegistrationBean<SecondServlet>();
        registrationBean.setServlet(new SecondServlet());
        registrationBean.addUrlMappings("/sec","/second");

        return registrationBean;
    }

    @Bean
    FilterRegistrationBean getFilterRegistrationBean(){
        FilterRegistrationBean<SecondFilter> registrationBean = new FilterRegistrationBean<SecondFilter>();
        registrationBean.setFilter(new SecondFilter());
        registrationBean.addUrlPatterns("/*");

        return registrationBean;
    }


    @Bean
    ServletListenerRegistrationBean getServletListenerRegistrationBean(){
        ServletListenerRegistrationBean registrationBean = new ServletListenerRegistrationBean();
        registrationBean.setListener(new MySessionListener());
        return registrationBean;
    }
    // 使用@Bean配合RegistrationBean类型注册 -- end


    /* 使用Bean注解定义跨域的Filter*/
    @Bean
    FilterRegistrationBean<CorsFilter> cors(){
        FilterRegistrationBean<CorsFilter> registrationBean = new FilterRegistrationBean<CorsFilter>();
        CorsConfiguration config = new CorsConfiguration();

        config.setAllowCredentials(true);
        config.addAllowedOrigin("*");
        config.addAllowedHeader("*");
        config.addAllowedMethod("*");

        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", config);

        CorsFilter filter = new CorsFilter(source);
        registrationBean.setFilter(filter);
        registrationBean.addUrlPatterns("/*");

        return registrationBean;
    }

	// 另外一种跨域方式
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**").allowedHeaders("*").allowedOrigins("*").allowedMethods("*");
    }
}

定义Servlet

SecondServlet:

package com.keafmd.servlet.component;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * Keafmd
 *
 * @ClassName: SecondServlet
 * @Description:
 * @author: 牛哄哄的柯南
 * @Date: 2021-04-08 17:41
 * @Blog: https://keafmd.blog.csdn.net/
 */
public class SecondServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("SecondServlet.doGet");
        System.out.println("sessionid: "+req.getSession().getId());
    }
}

定义Filter

SecondFilter:

package com.keafmd.servlet.component;

import javax.servlet.*;
import java.io.IOException;

/**
 * Keafmd
 *
 * @ClassName: SecondFilter
 * @Description:
 * @author: 牛哄哄的柯南
 * @Date: 2021-04-08 17:41
 * @Blog: https://keafmd.blog.csdn.net/
 */
public class SecondFilter implements Filter {
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        System.out.println("SecondFilter.doFilter 生效了");
        chain.doFilter(request, response);
    }
}

定义Listener

package com.keafmd.servlet.component;

import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

/**
 * Keafmd
 *
 * @ClassName: MySessionListener
 * @Description:
 * @author: 牛哄哄的柯南
 * @Date: 2021-04-08 17:42
 * @Blog: https://keafmd.blog.csdn.net/
 */
public class MySessionListener implements HttpSessionListener {

    @Override
    public void sessionCreated(HttpSessionEvent se) {
        System.out.println("Session对象被创建");
    }

    @Override
    public void sessionDestroyed(HttpSessionEvent se) {

    }
}

使用Bean注解定义跨域的Filter

Appconfig部分代码:

// 使用Bean注解定义跨域的Filter

    @Bean
    FilterRegistrationBean<CorsFilter> cors(){
        FilterRegistrationBean<CorsFilter> registrationBean = new FilterRegistrationBean<CorsFilter>();
        CorsConfiguration config = new CorsConfiguration();

        config.setAllowCredentials(true);
        config.addAllowedOrigin("*");
        config.addAllowedHeader("*");
        config.addAllowedMethod("*");

        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", config);

        CorsFilter filter = new CorsFilter(source);
        registrationBean.setFilter(filter);
        registrationBean.addUrlPatterns("/*");

        return registrationBean;
    }

第二种跨域方式

Appconfig部分代码:

@Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**").allowedHeaders("*").allowedOrigins("*").allowedMethods("*");
    }

效果

访问:http://127.0.0.1/sec
在这里插入图片描述
访问:http://127.0.0.1/second
在这里插入图片描述
idea控制台输出效果:
在这里插入图片描述

以上就是SpringBoot的Web开发支持【超详细【一篇搞定】】的全部内容。

看完如果对你有帮助,感谢点赞支持!
如果你是电脑端的话,看到右下角的 “一键三连” 了吗,没错点它[哈哈]

在这里插入图片描述

加油!

共同努力!

Keafmd

已标记关键词 清除标记
<p> <br /> </p> <p style="color:#24292E;"> 课程的实战源码是我在 GitHub 上开源项目 <a href="https://github.com/ZHENFENG13/spring-boot-projects">spring-boot-projects</a> 中的其中一个项目代码,目前已有 2300 多个 star,项目截图如下: </p> <p style="color:#24292E;"> <img src="https://img-bss.csdn.net/201908031439119810.png" alt="" /> </p> <p style="color:#24292E;"> <br /> </p> <p style="color:#24292E;"> 由于项目比较受大家欢迎,因此心中就出现了将它做成教学视频的想法,也就是你现在了解的这个课程《SpringBoot入门及前后端分离项目开发》,本课程是一个 Spring Boot 技术栈的实战类课程,课程共分为 3 大部分,前面两个部分为基础环境准备和相关概念介绍,第三个部分是 Spring Boot 项目实践开发。Spring Boot 介绍、前后端分离、API 规范等内容<strong>旨在让读者更加熟悉 SpringBoot 及企业开发中需要注意的事项并具有使用 SpringBoot 技术进行基本功能开发的能力;</strong>这最后的项目实战为课程的主要部分,我会带着大家实际的开发一个前后端分离的 Spring Boot 实践项目,让大家实际操作并从无到有开发一个线上项目,并学习到一定的开发经验以及其中的开发技巧,<span>旨在让读者具有将 Spring Boot 真正应用于项目开发的能力;</span> </p> <p style="color:#24292E;"> 以下为实践项目的页面和功能展示,分别为: </p> <ul style="color:#24292E;"> <li> 登录页面 </li> </ul> <p> <span style="background-color:#FFFFFF;"><img src="https://img-bss.csdn.net/201908031438579072.png" alt="" /><br /> </span> </p> <p style="color:#24292E;"> <br /> </p> <ul style="color:#24292E;"> <li> 列表页面(分页功能) </li> </ul> <p> <span style="background-color:#FFFFFF;"><img src="https://img-bss.csdn.net/201908031438403196.png" alt="" /><br /> </span> </p> <p style="color:#24292E;"> <br /> </p> <ul style="color:#24292E;"> <li> 图片上传功能 </li> </ul> <p> <span style="background-color:#FFFFFF;"><img src="https://img-bss.csdn.net/201908031438176997.png" alt="" /><br /> </span> </p> <p style="color:#24292E;"> <br /> </p> <ul style="color:#24292E;"> <li> 富文本编辑器整合使用 </li> </ul> <p style="color:#24292E;"> <br /> </p> <p style="color:#24292E;"> <img src="https://img-bss.csdn.net/201908031437475366.png" alt="" /> </p> <p style="color:#24292E;"> 实践项目的主要功能和页面就是这些,通过项目展示大家也能够感受到,在实际应用开发中的高频次功能都已经实现,稍加修改就可以运用到企业开发中,整个项目的开发模式为前后端分离的模式,即 Spring Boot 提供后端接口,前端页面通过 Ajax 异步调用接口的方式与后端服务器进行交互并将数据填充至页面中,这也是目前企业开发中比较重用的开发模式,希望大家能够了解并且能够实际的上手开发。 </p> <p> <br /> </p>
相关推荐
©️2020 CSDN 皮肤主题: 像素格子 设计师:CSDN官方博客 返回首页