使用REST
使用Spring MVC开发Web应用程序的主要工作就是编写Controller逻辑。在Web应用中,除了需要使用MVC给用户显示页面外,还有一类API接口,称之为REST,通常输入输出都是JSON,便于第三方调用或者使用页面JavaScript与之交互。
Spring额外提供了一个@RestController
注解,使用@RestController
替代@Controller
后,每个方法自动变成API接口方法。编写ApiController
如下:
@RestController
@RequestMapping("/api")
public class ApiController {
@Autowired
UserService userService;
@GetMapping("/users")
public List<User> users() {
return userService.getUsers();
}
@GetMapping("/users/{id}")
public User user(@PathVariable("id") long id) {
return userService.getUserById(id);
}
@PostMapping("/signin")
public Map<String, Object> signin(@RequestBody SignInRequest signinRequest) {
try {
User user = userService.signin(signinRequest.email, signinRequest.password);
return Map.of("user", user);
} catch (Exception e) {
return Map.of("error", "SIGNIN_FAILED", "message", e.getMessage());
}
}
public static class SignInRequest {
public String email;
public String password;
}
}
User
能被正确地序列化为JSON,但暴露了password
属性。要避免输出password
属性,可以把User
复制到另一个UserBean
对象,该对象只持有必要的属性,但这样做比较繁琐。另一种简单的方法是直接在User
的password
属性定义处加上@JsonIgnore
表示完全忽略该属性:
public class User {
...
@JsonIgnore
public String getPassword() {
return password;
}
...
}
但是这样如果写一个register(User user)
方法,那么该方法的User对象也拿不到注册时用户传入的密码了。如果要允许输入password
,但不允许输出password
,即在JSON序列化和反序列化时,允许写属性,禁用读属性,可以更精细地控制如下:
public class User {
...
@JsonProperty(access = Access.WRITE_ONLY)
public String getPassword() {
return password;
}
...
}
同样的,可以使用@JsonProperty(access = Access.READ_ONLY)
允许输出,不允许输入。
小结
使用@RestController
可以方便地编写REST服务,Spring默认使用JSON作为输入和输出。
要控制序列化和反序列化,可以使用Jackson提供的@JsonIgnore
和@JsonProperty
注解。
集成Filter
在Spring MVC中,DispatcherServlet
只需要固定配置到web.xml
中,剩下的工作主要是专注于编写Controller。但是,在Servlet规范中,可以使用Filter。
如果注册时输入中文会导致乱码,因为Servlet默认按非UTF-8编码读取参数。为了修复这一问题,我们可以简单地使用一个EncodingFilter,在全局范围类给HttpServletRequest
和HttpServletResponse
强制设置为UTF-8编码。
可以自己编写一个EncodingFilter,也可以直接使用Spring MVC自带的一个CharacterEncodingFilter
。配置Filter时,只需在web.xml
中声明即可:
<web-app>
<filter>
<filter-name>encodingFilter</filter-name>
<