经常使用注解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();
}
}
复制代码
经常使用注解