SpringBoot 简明教程

前言

Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程。

简言之:简单粗暴
话不多说,走起……

创建 Spring boot 项目

项目名为:SpringBoot

SpringBoot 简明教程_第1张图片
选择 Spring Initializr

选择Maven,War

SpringBoot 简明教程_第2张图片
选择 Maven --> War

选择Web项目,加载Web模块

SpringBoot 简明教程_第3张图片
选择 Web --> Web

1. 入门

一上来,无需多余的配置,直接新建 controller包,在其下新建HelloController.java文件,代码如下:

package pan.springboot.controller;

/**
 * Created by panzhangbao on 1/11/18.
 * Copyright © 2017年 panzhangbao. All rights reserved.
 */

import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 1. Spring Boot 入门
 */
@RestController
@RequestMapping("/hello")   // 全局配置
public class HelloController {

    /**
     * 无参 get
     * http://localhost:8080/hello
     * @return string
     */
    @GetMapping
    public  String getHello() {
        return "Hello , spring boot.";
    }

    /** 单个参数 post
     * http://localhost:8080/hello/info?name=panzhangbao
     * @param name
     * @return map
     */
    @PostMapping("/info")
    public Map getInfo(@RequestParam(value = "name",required = false, defaultValue = "defaultName") String myName) {
        Map map = new HashMap<>(  );
        map.put( "name", myName );
        return map;
    }

    /** 多个参数
     * http://localhost:8080/hello/info2?name=panzhangbao&age=20
     * @param name
     * @param age
     * @return map
     */
    @GetMapping("/info2")
    public Map getInfo(@RequestParam String name, @RequestParam String age) {
        Map map = new HashMap<>(  );
        map.put( "name", name );
        map.put( "age", age );
        return map;
    }

    /**
     * http://localhost:8080/hello/list
     * @return list
     */
    @RequestMapping("/list")
    public List> getList() {
        List> list = new ArrayList<>();
        Map map = null;
        for (int i = 1; i <= 5; i++) {
            map = new HashMap<>();
            map.put("name" + i, "panzhangbao");
            map.put( "age", String.format( "%d", i ) );
            list.add(map);
        }
        return list;
    }

}

新建本地 Tomcat 服务器(端口号:8080),对接口进行测试例如:多个参数查询 info2
浏览器输入http://localhost:8080/hello/info2?name=panzhangbao&age=20进行测试

2. Servlet、Filter、Listener、Interceptor

执行顺序:listener > filter > interceptor > servlet

Servlet

有时候,Web开发使用 Controller 基本上可以完成大部分需求,但是我们还可能会用到 Servlet、Filter、Listener、Interceptor 等等。
在spring boot中添加自己的 Servlet 有两种方法,代码注册Servlet和注解自动注册(Filter和Listener也是如此)。

  1. 代码注册通过ServletRegistrationBean、 FilterRegistrationBean 和 ServletListenerRegistrationBean 获得控制。也可以通过实现 ServletContextInitializer 接口直接注册。
  2. 在 SpringBootApplication 上使用@ServletComponentScan 注解后,Servlet、Filter、Listener 可以直接通过 @WebServlet、@WebFilter、@WebListener 注解自动注册,无需其他代码。


    SpringBoot 简明教程_第4张图片
    添加 @ServletComponentScan 组件注解
  • 第一种:在SpringbootApplication.java中添加 servlet 组件注解,代码如下:
package pan.springboot;

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

// 添加 servlet 组件注解
@ServletComponentScan
@SpringBootApplication
public class SpringbootApplication {

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

新建servlet包,新建PanServlet.java,代码如下:

package pan.springboot.servlet;

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;
import java.io.PrintWriter;

/**
 * Created by panzhangbao on 1/11/18.
 * Copyright © 2017年 panzhangbao. All rights reserved.
 */
// http://localhost:8080/index
// 不指定name的情况下,name默认值为类全路径,即org.springboot.sample.servlet.PanServlet
@WebServlet(urlPatterns = "/testservlet", description = "Servlet 的说明")
public class PanServlet extends HttpServlet {

    private static final long serialVersionUID = -8685285401859800066L;

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println(">>>>>>>>>>doGet()<<<<<<<<<<<");
        doPost(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println(">>>>>>>>>>doPost()<<<<<<<<<<<");
        resp.setContentType("text/html");
        resp.setCharacterEncoding("gb2312");

        PrintWriter out = resp.getWriter();
        out.println("");
        out.println("");
        out.println("Servlet Test");
        out.println("");
        out.println("");
        out.println("

大家好,我的名字叫 PanServlet

"); out.println(""); out.println(""); } }

浏览器输入http://localhost:8080/testservlet进行测试

  • 第二种:代码注册,在 SpringbootApplication.java中添加 @bean,代码如下:
package pan.springboot;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import pan.springboot.servlet.PanServlet;

@SpringBootApplication
public class SpringbootApplication {

    /**
     * 代码注册 servlet
     * @return
     */
    @Bean
    public ServletRegistrationBean servletRegistrationBean() {
        return new ServletRegistrationBean( new PanServlet() , "/testservlet");
    }

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

测试 servlet,同上

有时候,我们需要修改 DispatcherServlet 默认设置(默认拦截 "/")。
注意,修改默认设置会禁用平常的 Controller 调用,这里只是演示如何进行修改。
这里也是在SpringBootApplication.java 里面添加 @Bean,代码如下:

package pan.springboot;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.web.servlet.DispatcherServlet;

@SpringBootApplication
public class SpringbootApplication {

    /**
     * 修改 DispatcherServlet 默认设置(默认拦截 "/")
     * @param dispatcherServlet
     * @return
     */
    @Bean
    public ServletRegistrationBean dispatcherRegistration(DispatcherServlet dispatcherServlet) {
        ServletRegistrationBean registration = new ServletRegistrationBean(dispatcherServlet);
        registration.getUrlMappings().clear();
        // 拦截 *.do
        registration.addUrlMappings("*.do");
        // 拦截 *.json
        registration.addUrlMappings("*.json");
        return registration;
    }

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

为方便返回 Json 数据,这里添加 阿里巴巴的 fastjson 依赖,在pom.xml里面添加:

 
        
            com.alibaba
            fastjson
            1.2.37
        

新建PanServletJson.java,方便测试,代码如下:

package pan.springboot.servlet;

import com.alibaba.fastjson.JSONObject;

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;
import java.io.PrintWriter;
import java.util.HashMap;

/**
 * Created by panzhangbao on 1/11/18.
 * Copyright © 2017年 panzhangbao. All rights reserved.
 */
// http://localhost:8080/index
// 不指定name的情况下,name默认值为类全路径,即org.springboot.sample.servlet.PanServlet
@WebServlet(urlPatterns = "/testservlet.json", description = "Servlet 的说明")
public class PanServletJson extends HttpServlet {

    private static final long serialVersionUID = -8685285401859800066L;

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println(">>>>>>>>>>doGet()<<<<<<<<<<<");
        doPost(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println(">>>>>>>>>>doPost()<<<<<<<<<<<");
        resp.setContentType("application/json; charset=utf-8");

        JSONObject jsonObject = new JSONObject(  );
        jsonObject.put( "name", "panzhangbao" );
        jsonObject.put( "age", "66" );
        jsonObject.put( "city", "上海" );
        PrintWriter out = null;
        try {
            out = resp.getWriter();
            out.write( String.valueOf( jsonObject ) );
        }catch (IOException e) {
            e.printStackTrace();
        }finally {
            if (out != null) {
                out.close();
            }
        }
    }
}

浏览器输入http://localhost:8080/testservlet.json进行测试

Filter

这里采用@ServletComponentScan形式
新建PanFilter.java,代码如下:

package pan.springboot.filter;

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

/**
 * Created by panzhangbao on 2017/10/12.
 * Copyright © 2017年 panzhangbao. All rights reserved.
 */
// http://localhost:8080/filter
@WebFilter(filterName = "filterName", urlPatterns = "/filter")
public class PanFilter implements Filter{
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("过滤器初始化");
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("执行过滤操作");
        // 更改 编码
        servletResponse.setCharacterEncoding("utf-8");
        filterChain.doFilter(servletRequest, servletResponse);
    }

    @Override
    public void destroy() {
        System.out.println("过滤器销毁");
    }
}

浏览器输入```http://localhost:8080/filter,在 日志窗口 查看打印日志结果

Listener

  • ServletContextListener
    新建PanServletContextListener.java文件,代码如下:
package pan.springboot.listener;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;

/**
 * Created by panzhangbao on 2017/10/12.
 * Copyright © 2017年 panzhangbao. All rights reserved.
 */
@WebListener
public class PanServletContextListener implements ServletContextListener{

    @Override
    public void contextInitialized(ServletContextEvent servletContextEvent) {
        System.out.println("ServletContextListener 初始化");
        System.out.println(servletContextEvent.getServletContext().getServerInfo());
    }

    @Override
    public void contextDestroyed(ServletContextEvent servletContextEvent) {
        System.out.println("ServletContextListener 被销毁");
    }
}

直接运行,即可调用

  • HttpSessionListener(有 session 时会调用)
    新建PanHttpSessionListener.java,代码如下:
package pan.springboot.listener;

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

/**
 * Created by panzhangbao on 2017/10/12.
 * Copyright © 2017年 panzhangbao. All rights reserved.
 */

// 返回 jsp 文件时会调用
@WebListener
public class PanHttpSessionListener implements HttpSessionListener{

    /**
     * Session 创建事件
     * @param httpSessionEvent
     */
    @Override
    public void sessionCreated(HttpSessionEvent httpSessionEvent) {
        System.out.println("HttpSessionListener 被创建");
    }

    /**
     * Session 失效事件
     * @param httpSessionEvent
     */
    @Override
    public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
        System.out.println("HttpSessionListener 被销毁");
    }
}

Interceptor

创建PanHandlerInterceptor.java文件,实现HandlerInterceptor的接口,代码如下:

package pan.springboot.interceptor;

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

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

/**
 * Created by panzhangbao on 1/12/18.
 * Copyright © 2017年 panzhangbao. All rights reserved.
 */

public class PanHandlerInterceptor implements HandlerInterceptor{
    @Override
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
        System.out.println(">>>PanWebMvcConfigurerAdapter>>>>>>>在请求处理之前进行调用(Controller方法调用之前)");

        // 只有返回true才会继续向下执行,返回false取消当前请求
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
        System.out.println(">>>PanWebMvcConfigurerAdapter>>>>>>>请求处理之后进行调用,但是在视图被渲染之前(Controller方法调用之后)");
    }

    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
        System.out.println(">>>PanWebMvcConfigurerAdapter>>>>>>>在整个请求结束之后被调用,也就是在DispatcherServlet 渲染了对应的视图之后执行(主要是用于进行资源清理工作)");
    }
}

创建PanWebMvcConfigurerAdapter.java,继承自WebMvcConfigurerAdapter,代码如下:

package pan.springboot.interceptor;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

/**
 * Created by panzhangbao on 1/12/18.
 * Copyright © 2017年 panzhangbao. All rights reserved.
 */

@Configuration
public class PanWebMvcConfigurerAdapter extends WebMvcConfigurerAdapter{

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 多个拦截器组成一个拦截器链
        // addPathPatterns 用于添加拦截规则
        // excludePathPatterns 用户排除拦截
        registry.addInterceptor( new PanHandlerInterceptor() ).addPathPatterns( "/**" );
//        registry.addInterceptor( new PanHandlerInterceptor2() ).addPathPatterns( "/**" );

        super.addInterceptors(registry);
    }
}

3. Runner(启动时加载数据)

在实际应用中,我们会有在项目服务启动的时候就去加载一些数据或做一些事情这样的需求。
为了解决这样的问题,Spring Boot 为我们提供了一个方法,通过实现接口 CommandLineRunner 来实现

新建PanRunner1.java,实现CommandLineRunner接口,代码如下:

package pan.springboot.runner;

/**
 * Created by panzhangbao on 2017/10/12.
 * Copyright © 2017年 panzhangbao. All rights reserved.
 */

import org.springframework.boot.CommandLineRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

/**
 * 启动加载数据 1
 */

@Component
@Order(value = 1) // 当有多个 启动加载数据时,进行优先级顺序设置
public class PanRunner1 implements CommandLineRunner {
    @Override
    public void run(String... strings) throws Exception {
        System.out.println(">>>>>>>>>>>>>>>服务启动执行 1,执行加载数据等操作 <<<<<<<<<<<<<");
    }
}

直接运行tomcat,即可查看结果

4. Logger

springboot 中内部集成了Logger,可以直接使用
使用代码示例如下:

        String name = "打印的内容";
        /**
         * 这里使用 slf4j,一般需要 import 的主要有 slf4j 的 Logger 和 LoggerFactory
         */
        final Logger panLog = LoggerFactory.getLogger(this.getClass() );

        /** 输出级别
         *  ERROR 为严重错误 主要是程序的错误
         *  WARN 为一般警告,比如session丢失
         *  INFO 为一般要显示的信息,比如登录登出
         *  DEBUG 为程序的调试信息
         */
        panLog.error(name);
        panLog.warn(name);
        panLog.info(name);
        panLog.debug(name);

5. 多线程

创建线程配置类PanTaskExecutorConfig.java,代码如下:

package pan.springboot.config;

import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.aop.interceptor.SimpleAsyncUncaughtExceptionHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.Executor;

/**
 * Created by panzhangbao on 2017/10/23.
 * Copyright © 2017年 panzhangbao. All rights reserved.
 */

/**
 * 线程配置类
 */
@Configuration
@ComponentScan("pan.springboot.service")
@EnableAsync
public class PanTaskExecutorConfig implements AsyncConfigurer{

    /**
     * //实现AsyncConfigurer接口并重写getAsyncExecutor方法,
     * 并返回一个ThreadPoolTaskExecutor,这样我们就获得了一个基于线程池TaskExecutor
     * @return
     */
    @Bean
    @Override
    public Executor getAsyncExecutor() {
        System.out.println("线程配置类");

        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize( 5 );
        executor.setMaxPoolSize( 10 );
        executor.setQueueCapacity( 25 );
        executor.initialize();
        return executor;
    }

    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return new SimpleAsyncUncaughtExceptionHandler();
    }
}

简单写个多线程任务测试AsyncTaskService.java,代码如下:

package pan.springboot.service;

import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

/**
 * Created by panzhangbao on 2017/10/23.
 * Copyright © 2017年 panzhangbao. All rights reserved.
 */

/**
 * 自定义线程执行任务类
 */
@Service
public class AsyncTaskService {

    // 表明是异步方法
    @Async
    public void executeAsyncTask(Integer i) {
        System.out.println("执行异步任务: " + i);
    }

}

编写一个测试类,测试代码如下:

        /**
         * 多线程
         */
        AnnotationConfigApplicationContext context =
                new AnnotationConfigApplicationContext(PanTaskExecutorConfig.class);

        AsyncTaskService asyncTaskService = context.getBean(AsyncTaskService.class);

        for (int i = 0; i < 10; i++) {
            asyncTaskService.executeAsyncTask(i);
        }
        context.close();

6. 切面编程

pom.xml中添加 aop依赖:

 
        
            org.springframework.boot
            spring-boot-starter-aop
        

创建切面编程文件PanAspect.java,代码如下:

package pan.springboot.aspect;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;

/**
 * Created by panzhangbao on 2017/10/23.
 * Copyright © 2017年 panzhangbao. All rights reserved.
 */

@Aspect
@Component
public class PanAspect {

    /**
     * execution:用于匹配子表达式。
     *  匹配 pan.sercice 包及其子包中所有类中的所有方法,返回类型任意,方法参数任意
     */
//    @Pointcut("execution(* pan.service..*.*(..))")
//    public void executePointcut() {
//        // 此处无需写任何代码
//    }

    // within:用于匹配连接点所在的Java类或者包。
//    @Pointcut("within(pan.service.*)")
    @Pointcut("within(pan.springboot.service.PanAspectService)")
    public void executePointcut() {
        // 此处无需写任何代码
        System.out.println("调用 executePointcut() 方法");
    }

    @Before( "executePointcut()" )
    public void doBefore() {
        System.out.println("调用 aop doBefore() 方法");
    }

    @After( "executePointcut()" )
    public void doAfter(JoinPoint joinPoint) {
        System.out.println("调用 doAfter() 方法\n" +
                "类名:"+joinPoint.getTarget().getClass() +
                "\n参数值:"+ Arrays.asList(joinPoint.getArgs()) +
                "\n方法名:"+joinPoint.getSignature() + "\n");

        // 接收到请求,记录请求内容
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        // 记录下请求内容
        System.out.println("URL : " + request.getRequestURL().toString());
        System.out.println("HTTP_METHOD : " + request.getMethod());
        System.out.println("IP : " + request.getRemoteAddr());
        System.out.println("CLASS_METHOD : " + joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());
        System.out.println("ARGS : " + Arrays.toString(joinPoint.getArgs()));
    }

    @AfterReturning(returning = "ret", pointcut = "executePointcut()")
    public void doAfterReturning(Object ret) throws Throwable {
        System.out.println("RESPONSE:" + ret);
    }
}

新建测试服务PanAspectService.java,代码如下:

package pan.springboot.service;

import org.springframework.stereotype.Service;

/**
 * Created by panzhangbao on 2017/10/23.
 * Copyright © 2017年 panzhangbao. All rights reserved.
 */

@Service
public class PanAspectService {

    public void eatFood(String foodName) {
        System.out.println("去吃" + foodName +"啥的");
    }

    public void watchMovie(String movieName) {
        System.out.println("去看" + movieName + "啥的");
    }
}

新建AspectController.java进行测试,代码如下:

package pan.springboot.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import pan.springboot.service.PanAspectService;

/**
 * Created by panzhangbao on 1/12/18.
 * Copyright © 2017年 panzhangbao. All rights reserved.
 */
@RestController
public class AspectController {

    @Autowired
    PanAspectService panAspectService;

    /**
     * 切面编程
     */
    @GetMapping("aop")
    public void testAspect() {
        panAspectService.eatFood("小苹果");
        panAspectService.watchMovie("《金刚》");
    }

}

浏览器输入http://localhost:8080/aop查看结果

7. 文件传输

说到文件传输,这里不得不使用 html / jsp 文件,这里以 html 文件来进行演示
springboot 中要想支持 html文件,必须在pom.xml中添加thymeleaf依赖:

 
        
            org.springframework.boot
            spring-boot-starter-thymeleaf
        

resources文件夹下新建templates文件夹
templates文件夹下新建filePage.html,具体代码如下:





    文件上传、下载页面
    






文件:

文件1: 文件2: 文件3:

dog.jpg 下载

为了便于操作,在 service文件夹下新建了FileService.java对上传操作进行了封装,具体代码如下:

package pan.springboot.service;

import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.OutputStream;

/**
 * Created by panzhangbao on 1/13/18.
 * Copyright © 2017年 panzhangbao. All rights reserved.
 */

@Service
public class FileService {
    /**
     * 上传文件具体操作
     * @param multipartFile 文件
     * @param filePath  文件存储路径
     * @throws Exception
     */
    public void uploadFile(MultipartFile multipartFile, String filePath) throws Exception {
        File file = new File(filePath);
        if(!file.exists()){
            file.mkdirs();
        }
        FileOutputStream fos = new FileOutputStream(filePath + multipartFile.getOriginalFilename());
        fos.write(multipartFile.getBytes());
        fos.flush();
        fos.close();
    }

}

FileController.java,代码如下:

package pan.springboot.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import pan.springboot.service.FileService;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URL;
import java.net.URLConnection;


/**
 * Created by panzhangbao on 11/3/17.
 * Copyright © 2017年 panzhangbao. All rights reserved.
 */

@Controller
public class FileController {

    /**
     * 跳转到 templates/filePage.html
     * @return
     *
     * http://localhost:8080/showFilePage
     */
    @GetMapping("showFilePage")
    public String openUploadFileHtml() {
        return "filePage";
    }

    @Autowired
    FileService fileService;

    /**
     * 文件上传
     * @param request
     * @param multipartFile
     * @return
     */
    @PostMapping("uploadFileAction")
    @ResponseBody
    public String uploadFileAction(HttpServletRequest request,
                                   @RequestParam("file") MultipartFile multipartFile){

//        String fileName = file.getOriginalFilename();   // 例如:wolf.jpg
//        String contentType = file.getContentType(); // 例如:image/png
//        String filePath = request.getSession().getServletContext().getRealPath("uploadFile/");    // 服务器真实路径
        String filePath = "/Users/slcf666/Desktop/";    // 上传后的文件存储路径 - 这里暂时写的路径为 本地桌面
        try {
            // 有文件才上传
            if (multipartFile.getSize() > 0) {
                fileService.uploadFile(multipartFile, filePath);
            }else {
                return "sorry, you haven't choose any file";
            }
        } catch (Exception e) {
            e.printStackTrace();

        }

        return "upload file success!";
    }

    /**
     * 多文件上传 - 前提是 文件必须全部都有
     * @param multipartFiles
     * @return
     */
    @PostMapping("uploadMultiFileAction")
    @ResponseBody
    public String uploadMultiFileAction(@RequestParam("file") MultipartFile[] multipartFiles) {
        String filePath = "/Users/slcf666/Desktop/";
        System.out.println("个数:" + multipartFiles.length);
        try {
            // 记录真实上传文件个数
            int count = 0;
            for (MultipartFile multipartfile: multipartFiles) {
                if (multipartfile.getSize() > 0) {
                    fileService.uploadFile( multipartfile, filePath );
                    count ++;
                }
            }
            if (count == 0) {
                return "sorry, you haven't choose any file";
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return "upload files success!";
    }

    /**
     *  文件下载
     * @param response
     * @throws IOException
     *
     * http://localhost:8080/downloadFileAction
     */
    @RequestMapping("downloadFileAction")
    public void downloadFileAction(HttpServletResponse response) throws IOException {
        // 文件网络地址
        URL url = new URL("https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1516002946070&di=3b4052077eb3da9b5b5ffd3664f08f5a&imgtype=0&src=http%3A%2F%2Fimg2.everychina.com%2Fimg%2F09%2F81%2F498167e9cf13f90a4cf9684524c7-600x400c1-3005%2Fplastic_pet_dog.jpg");
        URLConnection conn = url.openConnection();

        InputStream inputStream = conn.getInputStream();
        // 文件下载后要保存的位置
        FileOutputStream fileOutputStream = new FileOutputStream("/Users/slcf666/Desktop/dog.png");

        byte[] buffer = new byte[1024];
        int len = 0;
        while ((len = inputStream.read(buffer)) != -1) {
            fileOutputStream.write(buffer, 0, len);
        }
    }

}

浏览器中输入http://localhost:8080/showFilePage,进入文件操作页面,具体页面如图所示:

文件上传、下载页面

点击 浏览,选择具体文件后,点击 单文件上传,即可进行文件上传
注意:
1. 上传文件的保存位置可以通过修改 filePath的值进行更改
因为我这里是 mac 系统,所以把文件放在了桌面上,即:String filePath = "/Users/slcf666/Desktop/";
你们可以根据具体情境进行相应的更改;文件下载位置亦是如此,这里不再多做赘述
单文件上传 和 多文件上传操作相似,这里也不再进行赘述

2. 这里未对上传文件大小进行限制,如若想进行限制,可以在SpringbootApplication.java下添加 @bean 进行配置,具体代码如下:

/**
     * 文件上传配置
     * @return
     */
    @Bean
    public MultipartConfigElement multipartConfigElement() {
        MultipartConfigFactory factory = new MultipartConfigFactory();
        // 单个文件最大大小 10MB
        factory.setMaxFileSize( "10MB" );
        // 设置上传数据总大小 100MB
        factory.setMaxRequestSize( "100MB" );

        return factory.createMultipartConfig();
    }

点击 dog.jpg 下载 即可下载,这里下载后的保存位置也是 mac 桌面
文件传输讲解到此告一段落

8. JPA(基于 Hibernate)

搞了这么久,看来有人早就急了,说好的数据库呢。别急,老铁,这不是来了嘛。这里讲的是 JPA 注解形式调用 MySQL 数据库。
话不多说,操作数据库之前,先在pom.xml中添加几个依赖,代码如下:

        
        
            mysql
            mysql-connector-java
        

        
        
            org.springframework.boot
            spring-boot-starter-data-jpa
        

        
        
            org.springframework.boot
            spring-boot-configuration-processor
            true
        
        
            org.springframework.boot
            spring-boot-starter-data-jpa
        
        
            org.springframework.boot
            spring-boot-starter-data-jpa
        

添加配置文件,这里用的 yml类型文件,application.yml,内容如下:

spring:
#    配置数据库
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/db_person?useUnicode=true&characterEncoding=utf8
    username: root
    password: 123456
  jpa:
    hibernate:
    #    create 自动创建新表
    #    create-drop 服务器停止时,会删除表
    #    update 更新数据,不会删除数据           - 推荐此写法
    #    validate 验证表和实体类是否一致,不一致的话就会报错
    #    none 什么也不做
      ddl-auto: update
#      控制台显示 sql 语句
      show-sql: true

server:
# 配置服务器端口
  port: 8081

新建db_person.sql文件,代码如下:

/*
 Navicat Premium Data Transfer

 Source Server         : localhost
 Source Server Type    : MySQL
 Source Server Version : 50637
 Source Host           : localhost
 Source Database       : db_person

 Target Server Type    : MySQL
 Target Server Version : 50637
 File Encoding         : utf-8

 Date: 01/15/2018 16:51:11 PM
*/

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
--  Table structure for `tb_person`
-- ----------------------------
DROP TABLE IF EXISTS `tb_person`;
CREATE TABLE `tb_person` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `p_age` int(11) DEFAULT NULL,
  `p_name` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1;

-- ----------------------------
--  Records of `tb_person`
-- ----------------------------
BEGIN;
INSERT INTO `tb_person` VALUES ('1', '11', 'pan'), ('3', '33', 'li');
COMMIT;

SET FOREIGN_KEY_CHECKS = 1;

entity包下新建Person.java文件,代码如下:

package pan.springboot.entity;

import javax.persistence.*;

//jpa @Entity - 对应数据库中的 Person 表
@Entity
@Table(name = "tb_person")
public class Person {

//    @Id 设置主键
    @Id
//    自增
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer id;

//    设置 column,省去 get 和 set 方法
    @Column(name = "p_name")
    private String name;
    @Column(name = "p_age")
    private Integer age;

//    无参构造方法必写 for jpa
    public Person() {
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

repository包下创建PersonRepository.java文件,代码如下:

package pan.springboot.repository;

import org.springframework.data.jpa.repository.JpaRepository;
import pan.springboot.entity.Person;

import java.util.List;

public interface PersonRepository extends JpaRepository {

//    扩展
    Person findById(Integer id);

//    通过年龄查询
    List findByAge(Integer age);

//    通过 id 删除
    void deleteById(Integer id);
}

最后一步,在controller包下新建PersonController.java文件,代码如下:

package pan.springboot.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import pan.springboot.entity.Person;
import pan.springboot.repository.PersonRepository;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

@RestController
// 设置全局 url
@RequestMapping("person")
public class PersonController {

    @Autowired
    private PersonRepository personRepository;

    /**
     * 查询人的列表
     * @return List
     */
    @GetMapping(value = "/getPersons")
    public List getPersonList() {
        return personRepository.findAll();
    }

    /**
     * 添加一个人
     * @param name
     * @param age
     * @return Person
     */
    @PostMapping(value = "/addPerson")
    public Person addPerson(@RequestParam(value = "name", required = false, defaultValue = "pan") String name,
                            @RequestParam("age") Integer age) {
        Person person = new Person();
        person.setName( name );
        person.setAge( age );

        return personRepository.save(person);
    }

    /**
     * 通过 id 查询 - 扩展
     * @param id
     * @return
     */
    @GetMapping(value = "getPerson/{id}")
    public Person getPerson(@PathVariable("id") Integer id) {
        return personRepository.findById( id );
    }

    /**
     * 通过 age 查询 - 扩展
     * @param age
     * @return
     */
    @GetMapping(value = "getPerson/{age}")
    public List getPersonByAge(@PathVariable("age") Integer age) {
        return personRepository.findByAge( age );
    }

    /**
     * 更新一个人
     * @param name
     * @param age
     * @return Person
     */
    @PutMapping(value = "/updatePerson")
    public Person updatePerson(@RequestParam("id") Integer id,
                               @RequestParam("name") String name,
                               @RequestParam("age") Integer age) {
        Person person = new Person();
        person.setId( id );
        person.setName( name );
        person.setAge( age );
        return personRepository.save(person);
    }

    /**
     * 删除一个人
     * @param id
     */
    @DeleteMapping("/deletePerson")
    public void deletePerson(@RequestParam("id") Integer id) {
        personRepository.deleteById( id );
    }

    /**
     * 事务管理 - 只有查询不需要加事务
     * @return
     */
    @Transactional
    @PostMapping("/addTwoPersons")
    public List addTwoPersons() {
        Person person = new Person();
        person.setName("A");
        person.setAge( 1 );
        personRepository.save(person);

        Person person2 = new Person();
        person2.setName("B");
        person2.setAge( 2 );
        personRepository.save(person2);

        List personList = new ArrayList(  );
        personList.add( person );
        personList.add( person2 );
        return personList;
    }
}

浏览器中输入http://localhost:8080/person/getPersons,进行用户列表post 方式下,输入http://localhost:8080/person/addPerson?name=you&&age=66,进行人员添加操作
修改、删除操作在这里就不做介绍了,大家自己看代码吧。

你可能感兴趣的:(SpringBoot 简明教程)