springboot技术点总结一

是什么:对spring的简化,自动装配,开箱即用,关注业务本身而你不是xml配置,甚至不配置将常用功能场景集成到一个个start,更加容易搭建web工程,适合开发微服务,自动配置,独立容器

spring组件是轻量级但是配置切是重量级别的,后来引入注解但是配置还是不少,而且存在版本冲突

将常用的功能封装成一个个start,需要什么就导入依赖

<!--导入配置文件处理器,配置文件进行绑定就会有提示-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>

@RequestParam

 @GetMapping("/hello")
    public String hello(@RequestParam(value = "name", defaultValue = "World") String name) {
        return String.format("Hello %s!", name);
    }

http://localhost:8080/hello 返回Hello World!
http://localhost:8080/hello?name=Amy 返回Hello Amy!

@EnableAutoConfiguration 开启依赖自动化配置
@SpringBootApplication 来标注一个主程序类,说明这是一个Spring Boot应用
@ConfigurationProperties(prefix = “person”) 配置文件值注入
@ComponentScan 同级包或者子包扫描
@自动以configuration创建配置,代替配置文件
在这里插入图片描述
在这里插入图片描述
@ConfigurationPropertie可以安全注入
配置类@Configuration------>Spring配置文件 、使用@Bean给容器中添加组件

@Configuration
public class AllConfiguration extends WebMvcConfigurerAdapter{
	//准备框架中需要维护的拦截器对象<bean>
	@Bean
	public CartInterceptor cartIntInit(){
		return new CartInterceptor();
	}
}


@Configuration//spring-config.xml
//@ImportResource(value="classpath:spring.xml")
public class Demo01Config {
	//<bean id="haha" class="org.springframework.web.client.RestTemplate"/>
	@Bean(value="haha") //相当于bean标签
	public RestTemplate initTemplate(){
		return new RestTemplate();
	}
	//将读取的<bean标签转化成代码实现
	//<bean class="com.jt.component.Demo01Component"></bean>
	@Bean //如果不设置value,将会默认以方法名称作为当前内存bean的id使用
	public Demo01Component initComponent(){
		return new Demo01Component();
	}
	
}


//属性读取注入到对象中,springboot容器一旦加载
	//appcation.properties,@Value必须在扫描范围内的类中使用
	@Value("${userUserName}")
	private String userName;
	@Value("${age}")
	private Integer age;
	@Value("${id}")
	private Integer id;
	@RequestMapping("springboot/test03")
	public User test03(String name){
		User user=new User();
		user.setAge(age);
		user.setId(id);
		user.setName(name);
		return user;
	}
	如果是非appcation.properties,book.properties则需要@PropertySource引入资源,yml不支持

@SpringBootApplication是一个组合注解包括:

  • @SpringBootConfiguration
    • @Configuration配置类
  • @EnableAutoConfiguration自动配置
  • @ComponentScan包扫描——同级或者子包下
banner定制

在资源目录下新建一个banner.txt文件
http://patorjk.com/software/taag 在这个网站制作
在这里插入图片描述

springboot多环境(dev,test,prod)配置
  • application.properties 配置
  • application-dev.properties 配置(开发环境配置)
  • application-test.properties 配置(测试环境配置)
  • application-prod.properties 配置(生产环境配置)
    通过修改application.properties文件spring.profiles.active参数决定加载对应环境的配置如:
spring.profiles.active=dev,启动开发配置环境

Json处理

spring-boot-starter-web整合了Jackson,所以springboot工程可以拿来直接使用,直接在方法上加 @ResponseBody注解或者在类上加@RestController
@RestController是一个组合注解:

  • @Controller
  • @ResponseBody

HttpMessageConverter ,看名字就知道,这是一个消息转换工具,有两方面的功能:

  1. 将服务端返回的对象序列化成 JSON 字符串
  2. 将前端传来的 JSON 字符串反序列化成 Java 对象
    所有的 JSON 生成都离不开相关的 HttpMessageConverter

SpringMVC 自动配置了 Jackson 和 Gson 的 HttpMessageConverter,Spring Boot 中又对此做了自动化配置:

  1. org.springframework.boot.autoconfigure.http.JacksonHttpMessageConvertersConfiguration
  2. org.springframework.boot.autoconfigure.http.GsonHttpMessageConvertersConfiguration
    所以,如果用户使用 jackson 和 gson 的话,没有其他额外配置,则只需要添加依赖即可。

利用jackson序列化和反序列化

  • ObjectMapper mapper = new ObjectMapper();
  • String json = mapper.writeValueAsString(product);
  • Product product = mapper.readValue(json, Product.class);

如果想使用Gson或者FastJson需要去除默认jackson的依赖导入相应的依赖入:

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

<!--        <dependency>
            <groupId>com.google.code.gson</groupId>
            <artifactId>gson</artifactId>
        </dependency>-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.49</version>
        </dependency>

访问静态资源

springboot工程默认静态资源放在五个地方:

  1. classpath:/META-INF/resources/
  2. classpath:/resources/
  3. classpath:/static/
  4. classpath:/public/
  5. /
    实际上/static/已经够用了

自定义访问路径

spring.resources.static-locations=classpath:/
spring.mvc.static-path-pattern=/**

第一行配置表示定义资源位置,第二行配置表示定义请求 URL 规则。以上文的配置为例,如果我们这样定义了,表示可以将静态资源放在 resources目录下的任意地方,我们访问的时候当然也需要写完整的路径,例如在resources/static目录下有一张名为1.png 的图片,那么访问路径就是 http://localhost:8080/static/1.png ,注意此时的static不能省略。

Java 代码定义

@Configuration
public class WebMVCConfig implements WebMvcConfigurer {
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/**").addResourceLocations("classpath:/aaa/");
    }
}

文件上传

单文件上传:

 SimpleDateFormat sdf = new SimpleDateFormat("/yyyy/MM/dd/");

    @PostMapping("/upload")
    public String upload(MultipartFile file, HttpServletRequest req) {
        String format = sdf.format(new Date());
        String realPath = req.getServletContext().getRealPath("/img") + format;
        File folder = new File(realPath);
        if (!folder.exists()) {
            folder.mkdirs();
        }
        String oldName = file.getOriginalFilename();
        String newName = UUID.randomUUID().toString() + oldName.substring(oldName.lastIndexOf("."));
        try {
            file.transferTo(new File(folder, newName));
            String url = req.getScheme() + "://" + req.getServerName() + ":" + req.getServerPort() + "/img" + format + newName;
            return url;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "error";
    }

多文件上传:

 @PostMapping("/uploads")
    public String uploads(MultipartFile[] files, HttpServletRequest req) {
        String format = sdf.format(new Date());
        String realPath = req.getServletContext().getRealPath("/img") + format;
        File folder = new File(realPath);
        if (!folder.exists()) {
            folder.mkdirs();
        }
        for (MultipartFile file : files) {
            String oldName = file.getOriginalFilename();
            String newName = UUID.randomUUID().toString() + oldName.substring(oldName.lastIndexOf("."));
            try {
                file.transferTo(new File(folder, newName));
                String url = req.getScheme() + "://" + req.getServerName() + ":" + req.getServerPort() + "/img" + format + newName;
                System.out.println(url);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return "success";
    }

Ajax上传:

<body>
<div id="result"></div>
<input type="file" id="file">
<input type="button" value="上传" onclick="uploadFile()">
<script>
    function uploadFile() {
        var file = $("#file")[0].files[0];
        var formData = new FormData();
        formData.append("file", file);
        $.ajax({
            type:'post',
            url:'/upload',
            processData:false,
            contentType:false,
            data:formData,
            success:function (msg) {
                $("#result").html(msg);
            }
        })
    }
</script>
</body>

@ControllerAdvice

@ControllerAdvice ,很多初学者可能都没有听说过这个注解,实际上,这是一个非常有用的注解,顾名思义,这是一个增强的 Controller。使用这个 Controller ,这是 SpringMVC 提供的功能,在 Spring Boot 中可以直接使用,下面分别来看。可以实现三个方面的功能:

  1. 全局异常处理
  2. 全局数据绑定
  3. 全局数据预处理

全局异常处理:

	@ControllerAdvice

	public class MyGlobalExceptionHandler {

		@ExceptionHandler(Exception.class)

		public ModelAndView customException(Exception e) {

			ModelAndView mv = new ModelAndView();

			mv.addObject("message", e.getMessage());

			mv.setViewName("myerror");

			return mv;

		}

	}

在该类中,可以定义多个方法,不同的方法处理不同的异常,例如专门处理空指针的方法、专门处理数组越界的方法…,也可以直接向上面代码一样,在一个方法中处理所有的异常信息。

@ExceptionHandler 注解用来指明异常的处理类型,即如果这里指定为 NullpointerException,则数组越界异常就不会进到这个方法中来。

全局数据绑定
全局数据绑定功能可以用来做一些初始化的数据操作,我们可以将一些公共的数据定义在添加@ControllerAdvice 注解的类中,这样,在每一个 Controller 的接口中,就都能够访问导致这些数据。
使用步骤,首先定义全局数据,如下:

@ControllerAdvice
public class GlobalData {
    @ModelAttribute(value = "info")
    public Map<String,Object> mydata() {
        Map<String, Object> map = new HashMap<>();
        map.put("name", "javaboy");
        map.put("address", "www.javaboy.org");
        return map;
    }
   }

使用 @ModelAttribute 注解标记该方法的返回数据是一个全局数据,默认情况下,这个全局数据的 key 就是返回的变量名,value 就是方法返回值,当然开发者可以通过 @ModelAttribute 注解的 name 属性去重新指定 key。

 @GetMapping("/hello")
    public String hello(Model model) {
        Map<String, Object> map = model.asMap();
        Set<String> keySet = map.keySet();
        for (String key : keySet) {
            System.out.println(key + ":" + map.get(key));
        }
        return "hello";
    }

全局数据预处理
考虑有两个实体类,Book 和 Author,分别定义如下:

public class Book {
    private String name;
    private Double price;

    public String getName() {
        return name;
    }

    @Override
    public String toString() {
        return "Book{" +
                "name='" + name + '\'' +
                ", price=" + price +
                '}';
    }

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

    public Double getPrice() {
        return price;
    }

    public void setPrice(Double price) {
        this.price = price;
    }
}
public class Author {
    private String name;
    private Integer age;

    public String getName() {
        return name;
    }

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

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

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }
}
@RestController
public class BookController {
    @PostMapping("/book")
    public void addBook(@ModelAttribute("b") Book book, @ModelAttribute("a") Author author) {
        System.out.println(book);
        System.out.println(author);
    }
}
@ControllerAdvice
public class GlobalData {
    @ModelAttribute(value = "info")
    public Map<String,Object> mydata() {
        Map<String, Object> map = new HashMap<>();
        map.put("name", "javaboy");
        map.put("address", "www.javaboy.org");
        return map;
    }

    @InitBinder("a")
    public void initA(WebDataBinder binder) {
        binder.setFieldDefaultPrefix("a.");
    }
    @InitBinder("b")
    public void initB(WebDataBinder binder) {
        binder.setFieldDefaultPrefix("b.");
    }
}

这样请求参数接上相应前缀就可以避免参数混淆

自定义异常

在 Spring Boot 项目中 ,异常统一处理,可以使用 Spring 中 @ControllerAdvice 来统一处理,也可以自己来定义异常处理方案。Spring Boot 中,对异常的处理有一些默认的策略
默认情况下,Spring Boot 中的异常页面 是这样的:
在这里插入图片描述
从这个异常提示中,也能看出来,之所以用户看到这个页面,是因为开发者没有明确提供一个 /error 路径,如果开发者提供了 /error 路径 ,这个页面就不会展示出来,不过在 Spring Boot 中,提供 /error 路径实际上是下下策,Spring Boot 本身在处理异常时,也是当所有条件都不满足时,才会去找 /error 路径。那么就先来看看,在 Spring Boot 中,如何自定义 error 页面,整体上来说,可以分为两种,一种是静态页面,另一种是动态页面。

静态异常页面
自定义静态异常页面,又分为两种,第一种 是使用 HTTP 响应码来命名页面,例如 404.html、405.html、500.html ….,另一种就是直接定义一个 4xx.html,表示400-499 的状态都显示这个异常页面,5xx.html 表示 500-599 的状态显示这个异常页面。

默认是在 classpath:/static/error/ 路径下定义相关页面:
在这里插入图片描述
此时,启动项目,如果项目抛出 500 请求错误,就会自动展示 500.html 这个页面,发生 404 就会展示 404.html 页面。如果异常展示页面既存在 5xx.html,也存在 500.html ,此时,发生500异常时,优先展示 500.html 页面。

动态异常页面
动态的异常页面定义方式和静态的基本 一致,可以采用的页面模板有 jsp、freemarker、thymeleaf。动态异常页面,也支持 404.html 或者 4xx.html ,但是一般来说,由于动态异常页面可以直接展示异常详细信息,所以就没有必要挨个枚举错误了 ,直接定义 4xx.html(这里使用thymeleaf模板)或者 5xx.html 即可。
注意,动态页面模板,不需要开发者自己去定义控制器,直接定义异常页面即可 ,Spring Boot 中自带的异常处理器会自动查找到异常页面。
页面定义如下:
在这里插入图片描述
页面内容如下:
在这里插入图片描述
默认情况下,完整的异常信息就是这5条,展示 效果如下 :
在这里插入图片描述
如果动态页面和静态页面同时定义了异常处理页面,例如 classpath:/static/error/404.html 和 classpath:/templates/error/404.html 同时存在时,默认使用动态页面。即完整的错误页面查找方式应该是这样:

发生了500错误–>查找动态 500.html 页面–>查找静态 500.html –> 查找动态 5xx.html–>查找静态 5xx.html。

自定义异常数据
默认情况下,在Spring Boot 中,所有的异常数据其实就是上文所展示出来的5条数据,这5条数据定义在 org.springframework.boot.web.reactive.error.DefaultErrorAttributes 类中,具体定义在 getErrorAttributes 方法中 :在这里插入图片描述

DefaultErrorAttributes 类本身则是在org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration 异常自动配置类中定义的,如果开发者没有自己提供一个 ErrorAttributes 的实例的话,那么 Spring Boot 将自动提供一个ErrorAttributes 的实例,也就是 DefaultErrorAttributes 。
基于此 ,开发者自定义 ErrorAttributes 有两种方式 :

  1. 直接实现 ErrorAttributes 接口
  2. 继承 DefaultErrorAttributes(推荐),因为 DefaultErrorAttributes 中对异常数据的处理已经完成,开发者可以直接使用。
    具体定义如下:
    在这里插入图片描述
    定义好的 ErrorAttributes 一定要注册成一个 Bean ,这样,Spring Boot 就不会使用默认的 DefaultErrorAttributes 了,运行效果如下图:
    在这里插入图片描述
    自定义异常视图
    异常视图默认就是前面所说的静态或者动态页面,这个也是可以自定义的,首先 ,默认的异常视图加载逻辑在 org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController 类的 errorHtml 方法中,这个方法用来返回异常页面+数据,还有另外一个 error 方法,这个方法用来返回异常数据(如果是 ajax 请求,则该方法会被触发)。
    在这里插入图片描述
    在这里,首先以异常响应码作为视图名分别去查找动态页面和静态页面,如果没有查找到,则再以 4xx 或者 5xx 作为视图名再去分别查找动态或者静态页面。
    要自定义异常视图解析,也很容易 ,由于 DefaultErrorViewResolver 是在 ErrorMvcAutoConfiguration 类中提供的实例,即开发者没有提供相关实例时,会使用默认的 DefaultErrorViewResolver ,开发者提供了自己的 ErrorViewResolver 实例后,默认的配置就会失效,因此,自定义异常视图,只需要提供 一个 ErrorViewResolver 的实例即可:
    在这里插入图片描述
    实际上,开发者也可以在这里定义异常数据(直接在 resolveErrorView 方法重新定义一个 model ,将参数中的model 数据拷贝过去并修改,注意参数中的 model 类型为 UnmodifiableMap,即不可以直接修改),而不需要自定义MyErrorAttributes。定义完成后,提供一个名为123的视图,如下图:
    在这里插入图片描述

模板引擎thymeleaf

添加依赖

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

配置1

thymeleaf:
    cache: false
    check-template-location: true
    encoding: UTF-8
    mode: HTML5
    prefix: classpath:/templates/
    servlet:
      content-type: text/html
    suffix: .html

在templates编写模板

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<table border="1">
    <tr>
        <td>编号</td>
        <td>用户名</td>
        <td>地址</td>
    </tr>
    <tr th:each="user : ${users}">

        <td th:text="${user.id}"></td>
        <td th:text="${user.name}"></td>
        <td th:text="${user.address}"></td>
    </tr>
</table>
</body>
</html>

控制层代码

@GetMapping("/test")
//@CrossOrigin(value = "http://localhost:8093")
    public String test(Model model){
        List<user> users=new ArrayList<>();
        for (int i=0;i<=10;i++){
            user user=new user();
            user.setId(i);
            user.setName("深圳");
            user.setAddress("有");
            users.add(user);
        }
        model.addAttribute("users",users);
        return "test";
    }

CROS跨域

同源策略
同源策略是由Netscape提出的一个著名的安全策略,它是浏览器最核心也最基本的安全功能,现在所有支持JavaScript的浏览器都会使用这个策略。所谓同源是指协议、域名以及端口要相同。同源策略是基于安全方面的考虑提出来的,这个策略本身没问题,但是在实际开发中,由于各种原因又经常有跨域的需求,传统的跨域方案是JSONP,JSONP虽然能解决跨域但是有一个很大的局限性,那就是只支持GET请求,不支持其他类型的请求,而今天说的CORS(跨域源资源共享)(CORS,Cross-origin resource sharing)是一个W3C标准,它是一份浏览器技术的规范,提供了Web服务从不同网域传来沙盒脚本的方法,以避开浏览器的同源策略,这是JSONP模式的现代版。
在Spring框架中,对于CORS也提供了相应的解决方案,看看SpringBoot中如何实现CORS。

新建两个工程,8081和8082,通过springboot实现8081访问8080的接口,8081静态资源目录新建一个html文件

<div id="app"></div>
<input type="button" onclick="btnClick()" value="get_button">
<input type="button" onclick="btnClick2()" value="post_button">
<script>
    function btnClick() {
        $.get('http://localhost:8080/hello', function (msg) {
            $("#app").html(msg);
        });
    }

    function btnClick2() {
        $.post('http://localhost:8080/hello', function (msg) {
            $("#app").html(msg);
        });
    }
</script>

在8080添加同源注解

@RestController
public class HelloController {
    @CrossOrigin(value = "http://localhost:8081")
    @GetMapping("/hello")
    public String hello() {
        return "hello";
    }

    @CrossOrigin(value = "http://localhost:8081")
    @PostMapping("/hello")
    public String hello2() {
        return "post hello";
    }
}

这样就能跨域访问了

拦截器

编写拦截器

/**
 * @author yuzb
 * @date 2020/5/20 13:59
 * @description
 */
public class MyInterceptor implements HandlerInterceptor {

    /*
     * @Description 该方法在控制器的处理请求方法前执行
     * @Return boolean true 表示继续向下执行,返回 false 表示中断后续
     * @Author yuzb
     * @throws Exception
     * @Date 2020/5/20 14:02
     **/
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("preHandle方法在控制器的处理请求方法调用之后,解析视图之前执行");
        return true;
    }

    /*
     * @Description 解析试图视图之前调用
     * @Return void
     * @Author yuzb
     * @throws Exception
     * @Date 2020/5/20 14:03
     **/
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("postHandle方法在控制器的处理请求方法调用之后,解析视图之前执行");
    }

    /*
     * @Description 视图渲染结束后执行
     * @Return void
     * @Author yuzb
     * @throws Exception
     * @Date 2020/5/20 14:04
     **/
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("afterCompletion方法在控制器的处理请求方法执行完成后执行,即视图渲染结束之后执行");
    }
}

注册拦截器

```java
/**
 * @author yuzb
 * @date 2020/5/20 14:06
 * @description
 */
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(myInterceptor()).addPathPatterns("/test/**");
    }

    @Bean
    MyInterceptor myInterceptor() {
        return new MyInterceptor();
    }
}

系统启动任务

系统启动时要做的操作

第一种 CommandLineRunner

@Component
@Order(99)
public class MyCommandLineRunner1 implements CommandLineRunner {
    @Override
    public void run(String... args) throws Exception {
        System.out.println("MyCommandLineRunner1>>>"+ Arrays.toString(args));
    }
}
@Component
@Order(98)
public class MyCommandLineRunner2 implements CommandLineRunner {
    @Override
    public void run(String... args) throws Exception {
        System.out.println("MyCommandLineRunner2>>>"+ Arrays.toString(args));
    }
}
@Component
@Order(99)
public class MyCommandLineRunner1 implements CommandLineRunner {
    @Override
    public void run(String... args) throws Exception {
        System.out.println("MyCommandLineRunner1>>>"+ Arrays.toString(args));
    }
}


@Order(99)数字越大执行越靠后,优先级的值为 Integer.MAX_VALUE,表示优先级最低

第二种ApplicationRunner
ApplicationRunner 和 CommandLineRunner 功能一致,用法也基本一致,唯一的区别主要体现在对参数的处理上,ApplicationRunner 可以接收更多类型的参数(ApplicationRunner 除了可以接收 CommandLineRunner 的参数之外,还可以接收 key/value形式的参数)。
使用 ApplicationRunner ,自定义类实现 ApplicationRunner 接口即可,组件注册以及组件优先级的配置都和 CommandLineRunner 一致,如下:

@Component
@Order(99)
public class MyApplicationRunner01 implements ApplicationRunner {
    @Override
    public void run(ApplicationArguments args) throws Exception {
        String[] sourceArgs = args.getSourceArgs();//获取启动的所有参数
        System.out.println("sourceArgs:" + Arrays.toString(sourceArgs));
        List<String> nonOptionArgs = args.getNonOptionArgs();
        System.out.println("nonOptionArgs:" + nonOptionArgs);
        Set<String> optionNames = args.getOptionNames();
        System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>");
        for (String optionName : optionNames) {
            System.out.println(optionName + ":" + args.getOptionValues(optionName));
        }
        System.out.println(">>>>>>>>>>>>>>>MyApplicationRunner01结束>>>>>>>>>>>>>>>>");
    }
}

@Component
@Order(98)
public class MyApplicationRunner02 implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
String[] sourceArgs = args.getSourceArgs();//获取启动的所有参数
System.out.println(“sourceArgs:” + Arrays.toString(sourceArgs));
List nonOptionArgs = args.getNonOptionArgs();
System.out.println(“nonOptionArgs:” + nonOptionArgs);
Set optionNames = args.getOptionNames();
System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>");
for (String optionName : optionNames) {
System.out.println(optionName + “:” + args.getOptionValues(optionName));
}
System.out.println(">>>>>>>>>>>>>>>MyApplicationRunner02结束>>>>>>>>>>>>>>>>");
}
}


当项目启动时,这里的 run 方法就会被自动执行,关于 run 方法的参数 ApplicationArguments ,说如下几点:

  1. args.getNonOptionArgs();可以用来获取命令行中的无key参数(和CommandLineRunner一样)。
  2. args.getOptionNames();可以用来获取所有key/value形式的参数的key。
  3. args.getOptionValues(key));可以根据key获取key/value 形式的参数的value。
  4. args.getSourceArgs(); 则表示获取命令行中的所有参数。

参考地址

加载xml配置

在资源目录下新建beans.xml

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

    <bean class="org.javaboy.xml.SayHello" id="sayHello"/>
</beans>

写一个配置类

@Configuration
@ImportResource(locations = "classpath:beans.xml")
public class WebMvcConfig {

}

bean类

public class SayHello {
    public String sayHello() {
        return "hello xml";
    }
}

测试

@RunWith(SpringRunner.class)
@SpringBootTest
public class XmlApplicationTests {

    @Autowired
    SayHello sayHello;
    @Test
    public void contextLoads() {
        System.out.println(sayHello.sayHello());
    }

}

这个功能很鸡肋一般不用

web基础组件

servlet

@WebServlet(urlPatterns = "/myservlet")
public class MyServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("MyServlet");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        super.doPost(req, resp);
    }
}

过滤器

@WebFilter(urlPatterns = "/*")
public class MyFilter implements Filter {
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("MyFilter");
        filterChain.doFilter(servletRequest, servletResponse);
    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void destroy() {

    }
}

监听器

@WebListener
public class MyRequestListener implements ServletRequestListener {
    @Override
    public void requestDestroyed(ServletRequestEvent sre) {
        System.out.println("requestDestroyed");
    }

    @Override
    public void requestInitialized(ServletRequestEvent sre) {
        System.out.println("requestInitialized");
    }
}

路径映射

简单的页面不需要渲染

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {

    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/cc").setViewName("cc");
        //多个继续配置
       // registry.addViewController("/gg").setViewName("gg);
    }
    

在templates建一个html文件叫cc.html

参数类型转换

  @ResponseBody
    @GetMapping("/qq")
    public String hello(Date birth) {
        System.out.println(birth);
        return birth.toString();
    }

访问没有明显的报错但是会警告for value ‘2018-12-5’; nested exception is java.lang.IllegalArgumentException]


@Component
public class DateConverter implements Converter<String, Date> {
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
    @Override
    public Date convert(String source) {
        if (source != null && !"".equals(source)) {
            try {
                return sdf.parse(source);
            } catch (ParseException e) {
                e.printStackTrace();
            }
        }
        return null;
    }
}

这样访问就正常了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值