Restful风格Web API构建流程
1.技术栈
框架类型 | 框架名称 |
---|---|
基本框架 | SpringBoot |
持久层 | Spring JPA |
关系型数据库 | Mysql |
缓存数据库 | Redis |
渲染引擎 | Thymeleaf |
权限控制框架 | Spring Security |
2.编写Restful风格接口类
2.1 添加ResponseUtil类(用来返回Resuful风格Json数据)
/**
* @Describe: 类描述
* @Author: tyf
* @CreateTime: 2021/11/15
**/
public class ResponseUtil {
public static <T> void restResponse(HttpServletResponse resp, HttpStatus status, RestResult<T> responseVo) throws IOException {
resp.setStatus(status.value());
resp.setContentType(MediaType.APPLICATION_JSON.toString());
resp.getOutputStream().write(new ObjectMapper().writeValueAsBytes(responseVo));
}
}
2.2添加ResultEnum
枚举类(用来返回服务状态)
/**
* @Describe: 类描述
* @Author: tyf
* @CreateTime: 2021/11/15
**/
@Getter
public enum ResultEnum {
INTERNAL_WRONG(500, "内部错误!");
private final Integer resultCode;
private final String resultMsg;
ResultEnum(Integer resultCode, String resultMsg) {
this.resultCode = resultCode;
this.resultMsg = resultMsg;
}
}
2.3添加RestResult
类(Restful风格返回体)
@Data
@JsonInclude(JsonInclude.Include.NON_NULL)
public class RestResult<T> {
private Integer code;
private String message;
private T data;
private HttpStatus httpStatus;
public RestResult(Integer code, String message) {
this.code = code;
this.message = message;
}
public RestResult(Integer code, T data) {
this.code = code;
this.data = data;
}
public RestResult(HttpStatus status, T data){
this.httpStatus = status;
this.data = data;
}
public static <T> RestResult<T> success(Integer code, T data) {
return new RestResult<>(code, data);
}
public static <T> RestResult<T> success(T data) {
return new RestResult<>(200, data);
}
public static <T> RestResult<T> success(Integer code, String message) {
return new RestResult<>(code, message);
}
public static <T> RestResult<T> success(ResultEnum resultEnum) {
return new RestResult<>(resultEnum.getResultCode(), resultEnum.getResultMsg());
}
public static <T> RestResult<T> error(Integer code, String message) {
return new RestResult<>(code, message);
}
public static <T> RestResult<T> error(Integer code, T data) {
return new RestResult<>(code, data);
}
public static <T> RestResult<T> error(String message) {
return new RestResult<>(500, message);
}
public static <T> RestResult<T> error(ResultEnum resultEnum) {
return new RestResult<>(resultEnum.getResultCode(), resultEnum.getResultMsg());
}
public static <T> RestResult<T> success(HttpStatus status, T data){
return new RestResult<>(status, data);
}
}
3. 引入相关依赖以及配置基本环境
3.1 编辑Maven配置文件pom.xml
-
添加父文件项目约束
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.5.6</version> <relativePath/> <!-- lookup parent from repository --> </parent>
-
添加依赖
<dependencies> <!--引入jpa依赖--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <!--引入jdbc驱动器--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency> <!--引入Spring Security--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <!--引入渲染引擎--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> <!--基础web框架--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!--渲染引擎结合前端完成操作--> <dependency> <groupId>org.thymeleaf.extras</groupId> <artifactId>thymeleaf-extras-springsecurity5</artifactId> </dependency> <!--待选:Excel处理--> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>5.0.0</version> </dependency> <!--热更新--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency> <!--连接器--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> <!--类管理模块--> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <!--测试框架--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies>
3.2 配置项目配置文件application.yml
spring:
imageProxy: https://pic1.xuehuaimg.com/proxy/ #配置图床
datasource: #配置数据源
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/sms?characterEncoding=utf8&serverTimezone=Asia/Shanghai
username: sms
password: 123456
jpa: #配置jpa
hibernate:
ddl-auto: update #打开项目自动更新
show-sql: true #显示sql调用语句,建议produce阶段关闭
database-platform: org.hibernate.dialect.MySQL8Dialect
server:
port: 8083 #配置端口号
3.3(可选)配置SpringSecurity
3.3.1 配置文件
/**
* @Describe: 类描述
* @Author: tyf
* @CreateTime: 2021/11/15
**/
@Configuration
@EnableWebSecurity
/*开启方法权限认证*/
@EnableGlobalMethodSecurity(securedEnabled=true)
public class SecurityConfigurer extends WebSecurityConfigurerAdapter {
// private final TigerLogoutSuccessHandler logoutSuccessHandler = new TigerLogoutSuccessHandler("/login");
public static final String[] NO_AUTH_LIST={
"/login",
"/register",
"/static/**",
"/img/**",
"/css/**",
"/js/**"
};
@Override
public void configure(HttpSecurity http) throws Exception {
http.csrf().disable().formLogin().loginPage("/login").loginProcessingUrl("/login").usernameParameter(
"username").permitAll()
//失败处理
.failureHandler((req, resp, e) -> ResponseUtil.restResponse(resp, HttpStatus.FORBIDDEN, RestResult.error(403, e.getMessage())))
//成功处理
.successHandler((req ,resp, e)-> ResponseUtil.restResponse(resp, HttpStatus.OK,
RestResult.success(200, "登录成功!"))
.permitAll()
.and().exceptionHandling()
//请求登录处理,改变默认跳转登录页
.authenticationEntryPoint((req, resp, e) -> resp.sendRedirect("/login"))
//没有权限访问
.accessDeniedHandler((req, resp, e) -> ResponseUtil.restResponse(resp, HttpStatus.FORBIDDEN, RestResult.error(403, "抱歉,你当前的身份无权访问")))
//设置最大一人同时登陆
.and().sessionManagement().maximumSessions(1)
.expiredSessionStrategy(s -> ResponseUtil.restResponse(s.getResponse(), HttpStatus.FORBIDDEN, RestResult.error(499, "您的账号在别的地方登录,当前登录已失效")))
.and()
//设置登出
.and().logout().logoutUrl("/logout").logoutSuccessUrl("/login").deleteCookies("JSESSIONID").permitAll()
.and().authorizeRequests().antMatchers(NO_AUTH_LIST).permitAll()
.antMatchers("/*.svg","/*.png","/*.js","/*.css").permitAll()
.and().authorizeRequests().anyRequest().authenticated();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
3.3.2 自定义Detail接口
/**
* @Describe: 类描述
* @Author: tyf
* @CreateTime: 2021/11/15
**/
public class TeacherDetail extends Teacher implements UserDetails{
public TeacherDetail(Teacher teacher){
BeanUtils.copyProperties(teacher, this);
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return null;
}
@Override
public String getPassword() {
return super.getPassword();
}
@Override
public String getUsername() {
return super.getName();
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
}
3.3.3 实现UserDetailService接口
/**
* @Describe: 类描述
* @Author: tyf
* @CreateTime: 2021/11/15
**/
@Service
public class TeacherServiceImpl implements TeacherService, UserDetailsService {
@Resource
private TeacherMapper teacherMapper;
@Override
public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
Teacher teacher = new Teacher();
teacher.setName(s);
Example<Teacher> teacherExample = Example.of(teacher);
Optional<Teacher> resultTeacher = teacherMapper.findOne(teacherExample);
if(resultTeacher.isPresent()){
return new TeacherDetail(resultTeacher.get());
}
return null;
}
}
4.(可选)其他配置
@Component
public class WebMvcConfigurerAdapter implements WebMvcConfigurer {
@Resource(name="thymeleafViewResolver")
private ThymeleafViewResolver thymeleafViewResolver;
@Value("${spring.imageProxy}")
private String imageProxy = "";
//Thymeleaf增加全局变量。用来图像加速等;
@Override
public void configureViewResolvers(ViewResolverRegistry registry) {
if (thymeleafViewResolver != null) {
Map<String, Object> vars = new HashMap<>(1);
vars.put("imageProxy", imageProxy);
thymeleafViewResolver.setStaticVariables(vars);
}
WebMvcConfigurer.super.configureViewResolvers(registry);
}
}
5.开始编写
- Mapper
- Service
- Controller
附录
1.目录结构
│ StudentMannagerSystemApplication.java
│
├─conf
│ SecurityConfigurer.java
│ WebMvcConfigurerAdapter.java
│
├─controller
│ ScoreController.java
│ StudentController.java
│ TeacherController.java
│
├─enums
│ ResultEnum.java
│
├─mapper
│ ScoreMapper.java
│ StudentMapper.java
│ TeacherMapper.java
│
├─model
│ RestResult.java
│ TeacherDetail.java
│
├─pojo
│ Score.java
│ Student.java
│ Teacher.java
│
├─service
│ │ ScoreService.java
│ │ StudentService.java
│ │ TeacherService.java
│ │
│ └─impl
│ ScoreServiceImpl.java
│ StudentServiceImpl.java
│ TeacherServiceImpl.java
│
└─tools
PasswordTools.java
ResponseUtil.java