經常使用註解html
編寫一個簡單的UserController類java
@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 排序git
在demo的pom.xml裏面引入spirngboot的測試github
<!--spring測試框架-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
複製代碼
測試/user接口web
@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);
}
複製代碼
jsonPath文檔語法查詢地址正則表達式
經常使用註解spring
實體對象json
@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類api
@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);
}
}
複製代碼
經常使用註解
實體對象
@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地址 | |
@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去掉
@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;
}
複製代碼
查看返回的異常信息
建立文件結構以下404錯誤將跳轉對應頁面
建立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();
}
}
複製代碼
經常使用註解