SpringSecurity 开发安全的RESTful服务(持续更新)

SpringSecurity 开发安全的RESTful服务

一. 初入RESTful

1.1 本章导航

  • 使用Spring MVC编写Restful API
  • 使用Spring MVC处理其他web应用常见的需求和场景
  • Restful API开发常用辅助框架

1.2 使用SpringMVC 编写RESTful API

  • 使用Restful API的第一印象如图:
    在这里插入图片描述
  • 特点如下:
    1. 用URL描述资源
    2. 使用HTTP方法描述行为。使用HTTP状态码来表示不同的结果
    3. 使用json交互数据
    4. RESTful只是一种风格,并不是强制的标准。

1.3 REST成熟度模型

  • 如图:
    在这里插入图片描述

1.4 常用注解

  • 映射注解:
    • @RestController:标明此Controller提供RestAPI
    • @RequestMapping及其变体:映射http请求url到java方法
    • @RequestParam 映射请求参数到java方法的参数
  • 请求映射简写举例:
    • Get请求举例:
      @RequestMapping(value="/demo",method=RequestMethod.GET)
      
    • Get请求简写后举例:
      @GetMapping("demo")
      

      这里的Get请求可以省略method,直接将@RequestMapping改为@GetMapping,同时当括号内只有一个值的时候,value可以忽略,而"/"可以忽略,Spring会自己加上。其他的如增删改都如此。

  • 分页注解:
    1. 分页对象: Pageeable: 它是Spring提供的一个分页对象,当前端需要进行分页查询的时候,我们可以使用此对象进行分页;
    2. 分页注解:@PageableDefault: 可以对分页对象进行分页 ,示例如下:
    public void mthod(Model1 model1, @PageableDefault(page=2,size=17,sort="username,asc")Pageable pageable);
    
  • 传参注解:
    • @PathVariable: 映射url片段到java方法的参数,在url声明中使用正则表达式
      • 使用@PathVariable可以指定名称(name=“变量名”),这样就可以将变量映射到这个参数上,如果不进行映射,则必须要保证参数名和上面的@RequestMapping()内的{变量名}与其一致。
      • 映射的使用@PathVariable的前提条件是 映射的接口有一个{变量名} 进行映射,同时在方法内加上@PathVariable注解即可;示例如下:
      @RequestMapping("user/{id}")
      public User getInfo(@PathVariable String id){
      	...
      }
      
      • 可以添加正则表达式,如图:
        在这里插入图片描述
    • @JsonView控制json输出内容
      • 使用接口来声明多个视图
      • 在值对象的get方法上指定视图
      • 在Controller方法上指定视图
        • User 实体类 -> 定义接口 和 指定视图
        public class User{
        	public interface UserSimpleView {};
        	public interface UserDetailView extends UserSimpleView {};
        	private String username;
        	private String p@ssw0rd;
        	@JsonView(UserSimpleView.class)
        	public String getUsername(){return username};
        	public void setUsername(String username){this.username = username;}
        	@JsonView(UserDetailView.class)
        	public String getPassword(){return password}
        }
        
      • 在Controller层上指定视图:
        @RequestMapping(value="/user",method= RequestMethod.GET)
        @JsonView(User.UserSimpleView.class)
        public List<User> query(UserQueryCondition condition,@PageableDefault(page=2,size = 17 ,sort ="user,desc") Pageable pageable){
        	System.out.println(pageable.getPageSize());
        	System.out.println(pageable.getPageNumber());
        	System.out.println(pageable.getSort());
        	List<User> users=new ArrayList<>();
        	users.add(new User());
        	return users;
        }
        
        @RequestMapping(value="/user/{id://d+}",method=RequestMethod.GET)
        @JsonView(User.UserDetailView.class)
        public User getInfo(@PathVariable String id)
        public User getInfo(@PathVariable String id){
        	User user=new User();
        	user.setUsername("user");
        	return user;
        }
        

        @JsonView的作用就是在相同的对象,我们可以手动控制返回哪些字段。一个对象中的字段可以进行筛选,只返回其中的部分字段。

  • @RequestBody 映射请求体到java方法的参数

    当前端传到后端是一个JSON格式的字符串的时候,后端是无法直接解析的,需要在参数前加上这个注解;

  • @Valid注解和BindingResult验证请求参数的合法性并处理校验结果。
    • 使用@Valid 的话,可以开启校验。如果在实体类中配置了如 @NotBlank等注解,就会在执行方法前先校验参数,如果不符合要求则直接返回失败。但是如果传入了参数: BindingResult 对象的时候,可以将报错信息存入此对象中,我们可以进一步处理,不必直接返回。如图所示:
      在这里插入图片描述

    在pom.xml中加入spring-boot-maven-plugin的插件,可以打包出可以直接执行的jar包(会包含引入的依赖的jar包。)

  • 其他常用注解:
    • 常用的验证注解
      • 如图:
        在这里插入图片描述
        在这里插入图片描述

        这些所有的注解都有一个共有的值,叫做message,它可以自定义错误信息;如:

        	@NotBlank(message="密码不能为空")
        	private String password;
        
    • 自定义消息
      • 自定义校验器:
        public class MyConstraintValidator implements ConstraintValidator<MyContraint,Object>{
        
        @Autowired
        private HelloService helloService;
        
        @Override
        private void initialize(MyConstraint constraintAnnotation){
        	System.out.println("my validator init");
        }
        @Override
        public boolean isValid(Object value,ConstraintValidatorContext context){
        	helloService.greeting("tom");
        	System.out.println(value);
        	return true;
        }
        }
        
      • 编写注解类:
        @Target({ElementType.METHOD,ElementType.FIELD})
        @Retention(RetentionPolicy.RUNTIME)
        @Constraint(validatedBy= MyConstraintValidator.class)
        public @interface MyConstraint{
        	String message();
        	Class<?>[] groups() default{};
        	Class<? extends Plyload>[] payload() default{};
        }
        

        里面的message,groups和plyload这三个是必不可少的,每个注解类都需要这个。

      • 使用自定义注解:
        在这里插入图片描述
    • 自定义校验注解

1.5 RESTful错误机制

  • 本节内容:
    • Spring Boot中默认的错误处理机制

      • SpringBoot 的一个默认机制就是会去判断,请求是浏览器发送的还是手机发送的。如果是错误信息的话,SpringBoot能够根据不同的设备,返回不一样的数据格式;比如:手机返回json,浏览器返回html页面等
      • 在指定目录下(error)下写对应的页面,当浏览器访问时出现了对应的错误时,就会自动跳转到对应的页面中。如图所示:
    • 自定义异常处理

      1. 首先创建一个自定义异常类:(可以创建一个包Package叫做exception,将此类放到下面)
        public class UserNotExistException extends RuntimeException{
        	private static final long serialVersionUID= -6112780192479692859L;
        	private String id;
        	public UserNotExistException(String id){
        		super("user not exit");
        		this.is = is;
        	}
        	//   id  的get,set方法省略...
        }
        
      2. 在接口中使用自定义的异常类:
        @GetMapping("/{id:\\d+}")
        @JsonView(User.UserDetailView.class)
        public User getInfo(@PathVariable String id){
        	throw new UserNotExistException(“user not exist”);
        }
        
      3. 设置统一异常处理:
        @ControllerAdvice
        public class ControllerExceptionHandler{
        	@ExceptionHandler(UserNotExistException.class)
        	@ResponseBody
        	@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
        	public Map<String,Object> handleUserNotExistException(UserNotExisException ex){
        		Map<String,Object> result=new HashMap<>();
        		result.put("id",ex.getId());
        		result.put("message",ex.getMessage());
        		return result;
        	}
        }
        
        • @ControllerAdvice,是Spring3.2提供的新注解,它是一个Controller增强器,可对controller中被 @RequestMapping注解的方法加一些逻辑处理。最常用的就是异常处理
        • 在@ExceptionHandler中指定了异常类。这样在抛出了此异常后就可以做统一异常处理了。

1.6 RESTful拦截机制

  • 本节介绍内容

    • 过滤器(Filter)
    • 拦截器
    • 切片
  • 过滤器:

    • 手写一个过滤器:
      @Component
      public class TimeFIlter implements Filter{
      @Override
      public void destroy(){
      	System.out.println("time filter destroy ");
      }
      @Override
      public void doFilter(ServletRequest request,ServletResponse response, FilterChain chain) throws IOException,ServletException{
      	System.out.println("time filter start");
      	long start =new Date().getTime();
      	chain.doFilter(request,response);
      	System.out.println("time filter:"+ (new Date().getTime()-start));
      	System.out.println("time filter finish");
      }
      	@Override
      	public void init(FilterConfig arg0) throws ServletException{
      		System.out.println("time filter init");
      	}
      }	
      

      如destroy 是结束时进入的方法,init是服务启动时会执行的方法,doFilter是方法被执行前被调用和执行后的方法。使用过滤器可以拦截服务请求。

    • 如何把第三方没有@Component注解的过滤器加入到过滤器链上去,也可以将我们自己写的过滤器去掉@Component,然后通过下方去注册加上去。方法如下:
      • 创建一个配置类:WebConfig
        @Configuration
        public class WebConfig{
        	@Bean
        	public FilterRegistrationBean timeFilter(){
        		FilterRegistrationBean registrationBean =new FilterRegistrationBean();
        		TimeFilter timeFilter=new TimeFilter();
        		registrationBean.setFilter(timeFilter);
        		List<String> urls=new ArrayList<>();
        		url.add("/*");
        		registrationBean.setUrlPatterns(urls);
        		return registratonBean;
        	}
        }
        
发布了127 篇原创文章 · 获赞 52 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/qq_37128049/article/details/103695919
今日推荐