經常使用註解html
編寫一個簡單的UserController類
@RestController @RequestMapping(value = "/user") public class UserController { @RequestMapping(method = RequestMethod.GET) public List<User> query(@RequestParam(name = "username",required = true) String username, @PageableDefault(page = 1,size = 20,sort = "username",direction = Sort.Direction.DESC)Pageable pageable){ System.out.println(pageable.getSort()); List<User>users=new ArrayList<>(); users.add(new User("aaa","111")); users.add(new User("bbb","222")); users.add(new User("ddd","333")); return users; } }
@PageableDefault SpingData分頁參數 page當前頁數默認0開始 sizi每頁個數默認10 sort 排序
在demo的pom.xml裏面引入spirngboot的測試java
<!--spring測試框架--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> </dependency>
測試/user接口
@RunWith(SpringRunner.class) //運行器 @SpringBootTest public class UserControllerTest { @Autowired private WebApplicationContext wac; private MockMvc mockMvc; @Before public void stup(){ mockMvc= MockMvcBuilders.webAppContextSetup(wac).build(); } //測試用例 @Test public void whenQuerSuccess() throws Exception { String result=mockMvc.perform(MockMvcRequestBuilders.get("/user") //傳過去的參數 .param("username","admin") .contentType(MediaType.APPLICATION_JSON_UTF8)) //判斷請求的狀態嗎是否成功,200 .andExpect(MockMvcResultMatchers.status().isOk()) //判斷返回的集合的長度是不是3 .andExpect(MockMvcResultMatchers.jsonPath("$.length()").value(3)) //打印信息 .andDo(MockMvcResultHandlers.print()) .andReturn().getResponse().getContentAsString(); //打印返回結果 System.out.println(result); }
經常使用註解github
實體對象
@NoArgsConstructor @AllArgsConstructor public class User { public interface UserSimpleView{}; public interface UserDetailView extends UserSimpleView{}; private String username; private String password; @JsonView(UserSimpleView.class) public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } @JsonView(UserDetailView.class) public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } }
Controller類
@RestController @RequestMapping(value = "/user") public class UserController { @RequestMapping(value = "/{id:\\d+}",method = RequestMethod.GET) // 正則表達式 :\\d+ 表示只能輸入數字 //用戶名密碼都顯示 @JsonView(User.UserDetailView.class) public User userInfo(@PathVariable String id){ User user=new User(); user.setUsername("tom"); return user; } }
測試用例
@RunWith(SpringRunner.class) //運行器 @SpringBootTest public class UserControllerTest { @Autowired private WebApplicationContext wac; private MockMvc mockMvc; @Before public void stup(){ mockMvc= MockMvcBuilders.webAppContextSetup(wac).build(); } //用戶詳情用例 @Test public void whenUserInfoSuccess() throws Exception { String result=mockMvc.perform(MockMvcRequestBuilders.get("/user/1") .contentType(MediaType.APPLICATION_JSON_UTF8)) //判斷請求的狀態嗎是否成功,200 .andExpect(MockMvcResultMatchers.status().isOk()) //判斷返回到username是否是tom .andExpect(MockMvcResultMatchers.jsonPath("$.username").value("tom")) //打印信息 .andDo(MockMvcResultHandlers.print()) .andReturn().getResponse().getContentAsString(); //打印返回結果 System.out.println(result); } }
經常使用註解web
實體對象
@NoArgsConstructor @AllArgsConstructor public class User { public interface UserSimpleView{}; public interface UserDetailView extends UserSimpleView{}; private String id; private String username; //不容許password爲null @NotBlank private String password; private Date birthday; @JsonView(UserSimpleView.class) public String getId() { return id; } public void setId(String id) { this.id = id; } @JsonView(UserSimpleView.class) public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } @JsonView(UserDetailView.class) public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } @JsonView(UserSimpleView.class) public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } }
Controller類
@RequestMapping(method = RequestMethod.POST) @JsonView(User.UserSimpleView.class) //@Valid啓用校驗password不容許爲空 public User createUser(@Valid @RequestBody User user, BindingResult errors){ //若是校驗有錯誤是true並打印錯誤信息 if(errors.hasErrors()){ errors.getAllErrors().stream().forEach(error -> System.out.println(error.getDefaultMessage())); } System.out.println(user.getUsername()); System.out.println(user.getPassword()); System.out.println(user.getBirthday()); user.setId("1"); return user; }
測試用例
@RunWith(SpringRunner.class) //運行器 @SpringBootTest public class UserControllerTest { @Autowired private WebApplicationContext wac; private MockMvc mockMvc; @Before public void stup(){ mockMvc= MockMvcBuilders.webAppContextSetup(wac).build(); } //用戶建立用例 @Test public void whenCreateSuccess() throws Exception { Date date=new Date(); String content="{\"username\":\"tom\",\"password\":null,\"birthday\":"+date.getTime()+"}"; String result=mockMvc.perform(MockMvcRequestBuilders.post("/user") .content(content) .contentType(MediaType.APPLICATION_JSON_UTF8)) //判斷請求的狀態嗎是否成功,200 .andExpect(MockMvcResultMatchers.status().isOk()) //判斷返回到username是否是tom .andExpect(MockMvcResultMatchers.jsonPath("$.id").value("1")) .andReturn().getResponse().getContentAsString(); //打印返回結果 System.out.println(result); } }
驗證註解
| 註解 | 解釋 |
| -------- | -------- |
| @NotNull | 值不能爲空 |
| @Null | 值必須爲空 |
| @Pattern(regex=) | 字符串必須匹配正則表達式 |
| @Size(min=,max=) | 集合的元素數量必須在min和max之間 |
| @Email | 字符串必須是Email地址 |
| @Length(min=,max=) | 檢查字符串長度 |
| @NotBlank | 字符串必須有字符 |
| @NotEmpty | 字符串不爲null,集合有元素 |
| @Range(min=,max=) | 數字必須大於等於min,小於等於max |
| @SafeHtml | 字符串是安全的html |
| @URL | 字符串是合法的URL |
| @AssertFalse | 值必須是false |
| @AssertTrue | 值必須是true |
| @DecimalMax(value=,inclusive) | 值必須小於等於(inclusive=true)/小於(inclusive=false) value指定的值 |
| @DecimalMin(value=,inclusive) | 值必須大於等於(inclusive=true)/大於(inclusive=false) value指定的值 |
| @Digits(integer=,fraction=) | integer指定整數部分最大長度,fraction小數部分最大長度 |
| @Future | 被註釋的元素必須是一個未來的日期 |
| @Past | 被註釋的元素必須是一個過去的日期 |
| @Max(value=) | 值必須小於等於value值 |
| @Min(value=) | 值必須大於等於value值 |正則表達式
實體對象
@NoArgsConstructor @AllArgsConstructor public class User { public interface UserSimpleView{}; public interface UserDetailView extends UserSimpleView{}; private String id; //自定義註解 @MyConstraint(message = "帳號必須是tom") private String username; //不容許password爲null @NotBlank(message = "密碼不能爲空") private String password; //加驗證生日必須是過去的時間 @Past(message = "生日必須是過去的時間") private Date birthday; @JsonView(UserSimpleView.class) public String getId() { return id; } public void setId(String id) { this.id = id; } @JsonView(UserSimpleView.class) public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } @JsonView(UserDetailView.class) public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } @JsonView(UserSimpleView.class) public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } }
Controller類
@RequestMapping(value = "/{id:\\d+}",method = RequestMethod.PUT) @JsonView(User.UserSimpleView.class) //@Valid啓用校驗password不容許爲空 public User updateUser(@Valid @RequestBody User user, BindingResult errors){ //若是校驗有錯誤是true並打印錯誤信息 if(errors.hasErrors()){ errors.getAllErrors().stream().forEach(error -> System.out.println(error.getDefaultMessage())); } System.out.println(user.getUsername()); System.out.println(user.getPassword()); System.out.println(user.getBirthday()); user.setId("1"); return user; }
測試用例
@RunWith(SpringRunner.class) //運行器 @SpringBootTest public class UserControllerTest { @Autowired private WebApplicationContext wac; private MockMvc mockMvc; @Before public void stup(){ mockMvc= MockMvcBuilders.webAppContextSetup(wac).build(); } //用戶修改用例 @Test public void whenUpdateSuccess() throws Exception { //當前時間加一年 Date date = new Date(LocalDateTime.now().plusYears(1).atZone(ZoneId.systemDefault()).toInstant().toEpochMilli()); String content = "{\"id\":\"1\",\"username\":\"44\",\"password\":null,\"birthday\":" + date.getTime() + "}"; String result = mockMvc.perform(MockMvcRequestBuilders.put("/user/1") .content(content) .contentType(MediaType.APPLICATION_JSON_UTF8)) //判斷請求的狀態嗎是否成功,200 .andExpect(MockMvcResultMatchers.status().isOk()) //判斷返回到username是否是tom .andExpect(MockMvcResultMatchers.jsonPath("$.id").value("1")) .andReturn().getResponse().getContentAsString(); //打印返回結果 System.out.println(result); }
自定義註解
MyConstraint類
import javax.validation.Constraint; import javax.validation.Payload; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; //做用在字段跟方法上面 @Target({ElementType.FIELD,ElementType.METHOD}) //運行時註解 @Retention(RetentionPolicy.RUNTIME) //須要校驗註解的類 @Constraint(validatedBy = MyConstraintValidator.class) public @interface MyConstraint { String message() default "{org.hibernate.validator.constraints.NotBlank.message}"; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; }
MyConstraintValidator類
import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorContext; //範型1.驗證的註解 2.驗證的數據類型 public class MyConstraintValidator implements ConstraintValidator<MyConstraint,Object> { @Override public void initialize(MyConstraint myConstraint) { //校驗器初始化的規則 } @Override public boolean isValid(Object value, ConstraintValidatorContext constraintValidatorContext) { //校驗username若是是tom驗證經過 if (value.equals("tom")){ return true; }else{ return false; } } }
Controller類
@RequestMapping(value = "/{id:\\d+}",method = RequestMethod.DELETE) //@Valid啓用校驗password不容許爲空 public void deleteUser(@PathVariable String id){ System.out.println(id); }
測試用例
@RunWith(SpringRunner.class) //運行器 @SpringBootTest public class UserControllerTest { @Autowired private WebApplicationContext wac; private MockMvc mockMvc; @Before public void stup(){ mockMvc= MockMvcBuilders.webAppContextSetup(wac).build(); } //用戶刪除用例 @Test public void whenDeleteSuccess() throws Exception { mockMvc.perform(MockMvcRequestBuilders.delete("/user/1") .contentType(MediaType.APPLICATION_JSON_UTF8)) //判斷請求的狀態嗎是否成功,200 .andExpect(MockMvcResultMatchers.status().isOk()); }
把BindingResult errors去掉spring
@RequestMapping(method = RequestMethod.POST) @JsonView(User.UserSimpleView.class) //@Valid啓用校驗password不容許爲空 public User createUser(@Valid @RequestBody User user){ //若是校驗有錯誤是true並打印錯誤信息 // if(errors.hasErrors()){ // errors.getAllErrors().stream().forEach(error -> System.out.println(error.getDefaultMessage())); // } System.out.println(user.getUsername()); System.out.println(user.getPassword()); System.out.println(user.getBirthday()); user.setId("1"); return user; }
查看返回的異常信息json
建立文件結構以下404錯誤將跳轉對應頁面api
建立filter文件
@Component public class TimeFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { System.out.println("TimeFilter init"); } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { System.out.println("TimeFilter doFilter"); long start=new Date().getTime(); filterChain.doFilter(servletRequest,servletResponse); System.out.println("耗時"+(new Date().getTime()-start)); } @Override public void destroy() { System.out.println("TimeFilter destroy"); } }
須要吧filter文件@Component標籤去除安全
@Configuration public class WebConfig { @Bean public FilterRegistrationBean timeFilterRegistration(){ FilterRegistrationBean registration=new FilterRegistrationBean(); TimeFilter timeFilter=new TimeFilter(); registration.setFilter(timeFilter); //filter做用的地址 List<String>urls=new ArrayList<>(); urls.add("/user"); registration.setUrlPatterns(urls); return registration; } }
建立Interceptor文件
@Component public class TimeInterceptor implements HandlerInterceptor { //控制器方法調用以前 @Override public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception { System.out.println("preHandle"); System.out.println("進入方法"+((HandlerMethod)o).getMethod().getName()); httpServletRequest.setAttribute("startTime",new Date().getTime()); //是否調用後面的方法調用是true return true; } //控制器方法被調用 @Override public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception { System.out.println("postHandle"); Long start= (Long) httpServletRequest.getAttribute("startTime"); System.out.println("time interceptor耗時"+(new Date().getTime()-start)); } //控制器方法完成以後 @Override public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception { System.out.println("afterCompletion"); System.out.println("exception is"+e); } }
把過濾器添加到webconfig文件
@Configuration public class WebConfig extends WebMvcConfigurerAdapter { @Autowired private TimeInterceptor timeInterceptor; //過濾器 @Bean public FilterRegistrationBean timeFilterRegistration(){ FilterRegistrationBean registration=new FilterRegistrationBean(); TimeFilter timeFilter=new TimeFilter(); registration.setFilter(timeFilter); //filter做用的地址 List<String>urls=new ArrayList<>(); urls.add("/user/*"); registration.setUrlPatterns(urls); return registration; } //攔截器 @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(timeInterceptor); } }
@Aspect @Component public class TimeAspect { //@Befor方法調用以前 //@After()方法調用 //@AfterThrowing方法調用以後 //包圍,覆蓋前面三種 @Around("execution(* com.guosh.web.controller.UserController.*(..))")//表達式表示usercontroller裏全部方法其餘表達式能夠查詢切片表達式 public Object handleControllerMethod(ProceedingJoinPoint pjp) throws Throwable { System.out.println("time aspect start"); //能夠獲取到傳入參數 Object[]args=pjp.getArgs(); for (Object arg: args) { System.out.println("arg is"+arg); } long start=new Date().getTime(); //至關於filter裏doFilter方法 Object object=pjp.proceed(); System.out.println("time aspect耗時"+(new Date().getTime()-start)); System.out.println("time aspect end"); return object; } }
過濾器Filter :能夠拿到原始的http請求與響應信息
攔截器Interceptor :能夠拿到原始的http請求與響應信息還能夠拿處處理請求方法的信息
切片Aspect :能夠拿到方法調用傳過來的值
返回的上傳文件後路徑對象
在application.yml裏添加上傳地址
#上傳文件路徑 uploadfiledir: filePath: /Users/shaohua/webapp/guoshsecurity
@Data @NoArgsConstructor @AllArgsConstructor public class FileInfo { private String path; }
@RestController @RequestMapping("/file") public class FileController { @Value("${uploadfiledir.filePath}") private String fileDataStorePath;//文件上傳地址 @RequestMapping(method = RequestMethod.POST) public FileInfo upload(@RequestParam("file") MultipartFile file) throws IOException { //文件名 System.out.println(file.getOriginalFilename()); //文件大小 System.out.println(file.getSize()); //獲取文件後綴名 String ext=StringUtils.getFilenameExtension(file.getOriginalFilename()); File fileDir = new File(fileDataStorePath); //判斷是否建立目錄 if (!fileDir.exists()) { if (!fileDir.mkdirs() || !fileDir.exists()) { // 建立目錄失敗 throw new RuntimeException("沒法建立目錄!"); } } File localFile=new File(fileDataStorePath, UUID.randomUUID().toString().replace("-", "")+"."+ext); file.transferTo(localFile); //返回上傳的路徑地址 return new FileInfo(localFile.getAbsolutePath()); } //下載文件 @RequestMapping(value ="/{id}" ,method = RequestMethod.GET) public void download(@PathVariable String id, HttpServletResponse response){ //模擬下載直接填好了下載文件名稱 try(InputStream inputStream = new FileInputStream(new File(fileDataStorePath,"13a2c075b7f44025bbb3c590f7f372eb.txt")); OutputStream outputStream=response.getOutputStream();){ response.setContentType("application/x-download"); response.addHeader("Content-Disposition","attachment;filename="+"13a2c075b7f44025bbb3c590f7f372eb.txt\""); IOUtils.copy(inputStream,outputStream); } catch (Exception e) { e.printStackTrace(); } } }
在demo模塊引入
<dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.9.2</version> </dependency> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>2.9.2</version> </dependency>
添加swagger的配置類
@Configuration @EnableSwagger2 public class Swagger2Config { @Value("${sys.swagger.enable-swgger}") private Boolean enableSwgger; @Bean public Docket createRestApi() { return new Docket(DocumentationType.SWAGGER_2) .enable(enableSwgger) .apiInfo(apiInfo()) .select() .apis(RequestHandlerSelectors.basePackage("com.guosh.web")) //swgger插件做用範圍 //.paths(PathSelectors.regex("/api/.*")) .paths(PathSelectors.any()) //過濾接口 .build(); } private ApiInfo apiInfo() { return new ApiInfoBuilder() .title("SpringSecurityDemo") //標題 .description("API描述") //描述 .contact(new Contact("guoshaohua", "http://www.guoshaohua.cn", ""))//做者 .version("1.0") .build(); } }
經常使用註解