1. 程式人生 > >SpringBoot堅持學習第一天:傳參校驗配置測試

SpringBoot堅持學習第一天:傳參校驗配置測試

一、SpringBoot產生的背景

        Spring Boot 誕生一方面是因為 Spring 自身發展所遇到的問題,另一方面在微服務思想誕生之際,急需要一款快速開發工具來實現微服務技術落地,在這樣的背景下誕生了 Spring Boot。
        正是由於 Spring IoC 和 Spring Aop 兩個強大的功能才有了 Spring,Spring 生態不斷的發展才有了 Spring Boot,使用 Spring Boot 讓 Spring 更易用更有生命力,Spring Cloud 是基於 Spring Boot 開發的一套微服務架構下的服務治理方案。

        Spring Boot 整體的設計思想是:約定優於配置。依賴此設計思路,Spring Boot 進行了大刀闊斧的改革,讓開發、測試、部署更為便捷。眾多的 Starters 成就了 Spring Boot 的發展,讓使用 Spring Boot 開發專案變得更加簡單。

二、SpringBoot模擬傳送URL

@RunWith(SpringRunner.class) 代表執行一個 Spring 容器

@SpringBootTest
public class HelloTest {

    private MockMvc mockMvc;

    @Before
    public void setUp() throws Exception {
        //載入某個Controller資源
        mockMvc = MockMvcBuilders.standaloneSetup(new HelloController()).build();
    }

    @Test
    public void getHello() throws Exception {
        //模擬一個URL
        mockMvc.perform(MockMvcRequestBuilders.post("/hello?name=小明")
                //設定JSON資料格式,防止亂碼
                .accept(MediaType.APPLICATION_JSON_UTF8)).//andDo(print());
        //判斷伺服器返回的JSON資料是否有字串“微笑”
        andExpect(MockMvcResultMatchers.content().string(Matchers.containsString("微笑")));
    }

   @Test
   public void getUser() throws Exception {
        //獲取JSON資料標準寫法
        String responseString = mockMvc.perform(MockMvcRequestBuilders.post("/getUser"))
                .andReturn().getResponse().getContentAsString();
        System.out.println("result : "+responseString);
   }

    //對映到User實體
    @Test
    public void saveUsers() throws Exception {
        mockMvc.perform(MockMvcRequestBuilders.post("/saveUser")
                .param("name","")
                .param("age","666")
                .param("pass","test")
        );
    }
}

在測試階段,如果後臺需要的是一個@RequestBody對映的實體,可以將其先暫時去掉,模擬傳送表單資料。測試通過後,可以將@RequestBody再添加回去。 

三、傳參

        若不在方法上指明 method = RequestMethod.GET 或者 method = RequestMethod.POST,即如果不進行設定預設兩種方式的請求都支援。

        (1)我們傳入一個屬性 name,直接使用物件接收也可以支援。

    輸入:http://localhost:8080/getUser?name=abc&pass=123

    @RequestMapping(name = "/getUser")
    public User getUser(User user) {
 
        return user;
    }

    返回JSON資料:{"name":"abc","age":0,"pass":"123"}

        (2)使用 URL 進行傳參

    輸入:http://localhost:8080/get/abc

    @RequestMapping(value = "get/{name}", method = RequestMethod.GET)
    public String get(@PathVariable String name) {
        return name;
    }
  
    頁面顯示:abc

四、校驗實體錯誤資訊

        Java實體上有部分約束。

import org.hibernate.validator.constraints.Length;

import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;

public class User {
    @NotEmpty(message = "姓名不能為空")
    private String name;

    @Max(value = 100, message = "年齡不能大於100歲")
    @Min(value = 18, message = "必須年滿18歲!")
    private int age;
    @NotEmpty(message = "密碼不能為空")
    @Length(min = 6, message = "密碼長度不能小於6位")
    private String pass;

  ...

@Valid 引數前面新增 @Valid 註解,代表此物件使用了引數校驗;

BindingResult 引數校驗的結果會儲存在此物件中,可以根據屬性判斷是否校驗通過,校驗不通過可以將錯誤資訊打印出來。 在請求到此方法體的時候,就已經觸發校驗事件了,校驗結果存放在BindingResult物件中。

    @RequestMapping("/saveUser")
    public void saveUser(@Valid User user, BindingResult result) {
        System.out.println("user:" + user);
        if (result.hasErrors()) {
            List<ObjectError> list = result.getAllErrors();
            for (ObjectError error : list) {
                System.out.println(error.getCode() + "-" + error.getDefaultMessage());
            }
        }
    }

user:[email protected]
NotEmpty-姓名不能為空
Max-年齡不能大於100歲
Length-密碼長度不能小於6位

五、自定義 Filter

        自定義 Filter 兩個步驟:

實現 Filter 介面,實現其中的 doFilter() 方法;
新增 @Configuration 註解,將自定義 Filter 加入過濾鏈。

public class MyFilter implements Filter {
    @Override
    public void doFilter(ServletRequest servletRequest,
                         ServletResponse servletResponse, FilterChain filterChain)
            throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        System.out.println("this is MyFilter,url :" + request.getRequestURI());
        filterChain.doFilter(servletRequest, servletResponse);
    }
}
@Configuration
public class WebConfiguration {
    @Bean
    public FilterRegistrationBean testFilterRegistration() {

        FilterRegistrationBean registration = new FilterRegistrationBean();
        //加入過濾器
        registration.setFilter(new MyFilter());
        //配置攔截規則
        registration.addUrlPatterns("/*");
        registration.setName("MyFilter");
        //設定攔截器優先順序,越小優先順序越高
        registration.setOrder(6);
        return registration;
    }
}

六、讀取配置檔案

        同時存在 application.yml 和 application.properties,並且裡面配置相同,application.properties 的配置會覆蓋 application.yml。

#resources/application.properties
neo.title=標題
neo.description=描述
# 讀取多個配置檔案 , 匹配配置檔案中 neo 開頭
@Component
@ConfigurationProperties(prefix="neo")
public class NeoProperties {
    private String title;
    private String description;
    //get set..
}
@RunWith(SpringRunner.class)
@SpringBootTest
public class PropertiesTest {
    @Value("${neo.title}")
    private String title;

    @Resource
    private NeoProperties properties;
    
    @Test
    public void testSingle2(){
        System.out.println(title);
        System.out.println(properties.getTitle());
        System.out.println(properties.getDescription());
    }
}

標題
標題
描述

七、自定義配置檔案

# resources / other.properties

other.title=other title
other.blog=other blog
@Component
@ConfigurationProperties(prefix="other")
@PropertySource("classpath:other.properties")
public class OtherProperties {
    private String title;
    private String blog;
    //get set
}
@RunWith(SpringRunner.class)
@SpringBootTest
public class PropertiesTest {
    @Resource
    private OtherProperties properties;

    @Test
    public void test(){
        System.out.println(properties.getBlog());
        System.out.println(properties.getTitle());
    }
}

other blog
other title