Spring Security(编写restful风格的接口)

用户详情请求

使用@PathVariable注解去绑定url中的参数

    @RequestMapping(value="user/{id}",method = RequestMethod.GET)
    public User getInfo(@PathVariable(required = false) String id) {
        User user=new User();
        user.setUsername("tom");
        return user;
    }

测试用例

    @Test
    public void whenGenInfoSuccess() throws Exception {
        mockMvc.perform(MockMvcRequestBuilders.get("/user/1")
                .contentType(MediaType.APPLICATION_JSON_UTF8))
                .andExpect(MockMvcResultMatchers.status().isOk())
                .andExpect(MockMvcResultMatchers.jsonPath("$.username").value("tom"));
    }

需求:传来的必须是数字

    @RequestMapping(value="user/{id:\\d+}",method = RequestMethod.GET)
    public User getInfo(@PathVariable(required = false) String id) {
        User user=new User();
        user.setUsername("tom");
        return user;
    }
    @Test
    public void whenGenInfoFail() throws Exception {
        mockMvc.perform(MockMvcRequestBuilders.get("/user/a")
                .contentType(MediaType.APPLICATION_JSON_UTF8))
                .andExpect(MockMvcResultMatchers.status().is4xxClientError());
    }

需求:query接口不能将password字段返回给前端,getInfo接口要将password字段返回给前端
解析:使用@JsonView

@Data
public class User {
    @JsonView(UserSimpleView.class)
    private String username;
    @JsonView(UserDetailView.class)
    private String password;
    
    public interface UserSimpleView{};
    
    public interface UserDetailView extends UserSimpleView{};
}
@RestController
public class UserController {
    
    
    @RequestMapping(value = "/user",method = RequestMethod.GET)
    @JsonView(User.UserSimpleView.class)
    public List<User> query(@RequestParam(required = false) String username,@PageableDefault(page = 1,size = 10,sort = "username,asc") Pageable pageable){
        System.out.println(pageable.getPageSize()+"---"+pageable.getPageNumber()+"---"+pageable.getSort());
        List<User> users=new ArrayList<User>(3);
        users.add(new User());
        users.add(new User());
        users.add(new User());
        return users;
    }
    @JsonView(User.UserDetailView.class)
    @RequestMapping(value="user/{id:\\d+}",method = RequestMethod.GET)
    public User getInfo(@PathVariable(required = false) String id) {
        User user=new User();
        user.setUsername("tom");
        return user;
    }
    
}

用户创建请求

    @PostMapping
    public User createUser(User user) {
        System.out.println("user==>"+user);
        user.setId("1");
        return user;
    }
    @Test
    public void whenCreateSuccess() throws Exception {
        String content = "{\"username\":\"tom\",\"password\":null}";
        String res = mockMvc
                .perform(MockMvcRequestBuilders.post("/user").contentType(MediaType.APPLICATION_JSON_UTF8)
                        .content(content))
                .andExpect(MockMvcResultMatchers.status().isOk())
                .andExpect(MockMvcResultMatchers.jsonPath("$.id").value(1)).andReturn().getResponse()
                .getContentAsString();
        System.out.println(res);
    }

发现controller类的参数User内并没有传过来的值。
需要加一个@RequestBody

    @PostMapping
    public User createUser(@RequestBody User user) {
        System.out.println("user==>"+user);
        user.setId("1");
        return user;
    }

之前并没有接触过@RequestBody注解,网上查询了一下该注解的作用https://blog.csdn.net/justry_deng/article/details/80972817
简单的说就是:参数放在请求体中,必须用@RequestBody注解接收。

需求:处理日期类型的参数
(视频上所说,由于现在前后端分离的情况,可能后台一个接口会被不同的渠道调用,app,网页端。这些渠道可能显示的格式不同,所以一般而言后端传给前端会是时间戳格式,然后再由前端选择显示的格式。但我们现在并不是= =,而是传格式化好了的时间,可以用@DateTimeFormat 和 @JsonFormat 注解,@DateTimeFormat 在RequestBody中不生效)

需求:校验参数的合法性,并处理校验的结果
解析:使用@vaild注解和BindingResult注解

@Data
@ToString
public class User {
    @JsonView(UserSimpleView.class)
    private String id;
    
    @JsonView(UserSimpleView.class)
    private String username;
    
    @NotBlank(message = "密码不能为空")
    @JsonView(UserDetailView.class)
    private String password;

    private Date birthDate;

    public interface UserSimpleView {
    };

    public interface UserDetailView extends UserSimpleView {
    };
}
    @PostMapping
    public User createUser(@Valid @RequestBody User user,BindingResult errors) {
        if(errors.hasErrors()) {
            errors.getAllErrors().stream().forEach(error-> System.out.println(error.getDefaultMessage()));
        }
        
        System.out.println("user==>"+user);
        user.setId("1");
        return user;
    }

(这里我使用的参数校验和视频上的略有出入,看我的实现可以看常用功能文章系列的参数校验那一篇。)

用户修改请求

@Data
@ToString
public class User {
    @JsonView(UserSimpleView.class)
    private String id;
    
    @JsonView(UserSimpleView.class)
    private String username;
    
    @NotBlank(message = "密码不能为空")
    @JsonView(UserDetailView.class)
    private String password;

    @Past(message = "生日必须是过去的时间")
    private Date birthDate;

    public interface UserSimpleView {
    };

    public interface UserDetailView extends UserSimpleView {
    };
}
    @PutMapping(value="/{id:\\d+}")
    public User updateUser(@Valid @RequestBody User user,BindingResult errors) {
        if(errors.hasErrors()) {
            errors.getAllErrors().stream().forEach(error-> System.out.println(error.getDefaultMessage()));
        }
        System.out.println("user==>"+user);
        user.setId("1");
        return user;
    }
    @Test
    public void whenUpdateSuccess() throws Exception {
        Date date=new Date(LocalDateTime.now().plusYears(1).atZone(ZoneId.systemDefault()).toInstant().toEpochMilli());
        
        String content = "{\"id\":\"1\",\"username\":\"tom\",\"password\":null,\"birthDate\":"+date.getTime()+"}";
        String res = mockMvc
                .perform(MockMvcRequestBuilders.put("/user/1").contentType(MediaType.APPLICATION_JSON_UTF8)
                        .content(content))
                .andExpect(MockMvcResultMatchers.status().isOk())
                .andExpect(MockMvcResultMatchers.jsonPath("$.id").value(1)).andReturn().getResponse()
                .getContentAsString();
        System.out.println(res);
    }

需求:自定义校验注解

public class MyConstraintValidator implements ConstraintValidator<MyConstraint, Object> {

    @Override
    public void initialize(MyConstraint constraintAnnotation) {
        System.out.println("MyConstraintValidator  init");
    }

    @Override
    public boolean isValid(Object value, ConstraintValidatorContext context) {
        System.out.println("value==》"+value);
        // TODO 写具体的校验逻辑,true验证通过,false验证不过
        return false;
    }

}
@Target({ElementType.METHOD,ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = MyConstraintValidator.class)
public @interface MyConstraint {
    String message() default "";

    Class<?>[] groups() default { };

    Class<? extends Payload>[] payload() default { };

}
    @MyConstraint(message = "自定义校验不过")
    @JsonView(UserSimpleView.class)
    private String username;

服务器异常处理

spring boot的默认异常处理机制是,浏览器返回错误页面,客户端返回json数据。
1、在src/main/resources下建立resources文件夹,然后再建error文件夹,再建立相应的错误页面。如404.hmtl,500.html


image.png

多线程提高接口性能

使用swagger生成文档

1、引入pom依赖

<!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger2 -->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>2.9.2</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger-ui -->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>2.9.2</version>
        </dependency>

2、使用@EnableSwagger2开启swagger

@SpringBootApplication
@EnableSwagger2
public class DemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}

3、使用注解
@Api注解:说明这个controller是干什么的

@Api("用户服务")
public class UserController

@ApiOperation:说明这个方法是干什么的

    @ApiOperation(value = "用户创建服务")
    @PostMapping
    public User createUser(@Valid @RequestBody User user,BindingResult errors)

@ApiModelProperty :参数是对象时,说明对象的属性

    @ApiModelProperty("用户名")
    @JsonView(UserSimpleView.class)
    private String username;
    
    @ApiModelProperty("用户密码")
    @NotBlank(message = "密码不能为空")
    @JsonView(UserDetailView.class)
    private String password;

    @ApiModelProperty("用户生日")
    @Past(message = "生日必须是过去的时间")
    private Date birthDate;

@ApiParam:参数是单独的一个时,说明。

public List<User> query(@ApiParam("用户名")@RequestParam(required = false) String username,@PageableDefault(page = 1,size = 10,sort = "username,asc") Pageable pageable){

参考链接://www.greatytc.com/p/a66cf3acd29a

使用wiremock伪造rest服务

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。