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;
    }
}

這樣訪問就正常了

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章