这个是采用的springboot配置项目,我先附上需要依赖的包
<properties>
<java.version>1.8</java.version>
<spring-mybatis.version>1.3.2</spring-mybatis.version>
<spring-druid.version>1.1.10</spring-druid.version>
<spring-jdbc.version>2.0.6</spring-jdbc.version>
<mysql-connector.version>8.0.16</mysql-connector.version>
<commons-lang.version>3.8.1</commons-lang.version>
<fastjson.version>1.2.51</fastjson.version>
<jwt.version>3.4.0</jwt.version>
<page-helper.version>1.2.7</page-helper.version>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>${commons-lang.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>${fastjson.version}</version>
</dependency>
<!-- mysql connector -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql-connector.version}</version>
</dependency>
<!-- Mybatis -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>${spring-mybatis.version}</version>
</dependency>
<!-- druid数据库连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.10</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.0.6.RELEASE</version>
</dependency>
<!-- swagger-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.8.0</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.8.0</version>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>3.11.0</version>
</dependency>
<dependency>
<groupId>com.aliyun.api.gateway</groupId>
<artifactId>sdk-core-java</artifactId>
<version>1.1.0</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.3.2</version>
</dependency>
<!--JWT-->
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>${jwt.version}</version>
</dependency>
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>${page-helper.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
顿时傻眼,一看这么多东西,怎么办?兄弟们不要慌,跟着我一步一步来。
首先第一步,我们先写一个简单的controller,先把项目运行起来。
@RestController
public class UserController {
@GetMapping("/user")
public String getUserInfo(@RequestParam("id") Integer id) {
return "cj" + id;
}
}
启动项目,等一会儿将会出现success的提示语。。。。。。。。。。。。。。。
wait、wait自信过头了。。。。。。
server:
port: 8082
tomcat:
uri-encoding: UTF-8
servlet:
session:
timeout: 600000
context-path: /cj-api
spring:
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone:
GMT+8
#应用名称
application:
name: cj-api
datasource:
url: jdbc:mysql://127.0.0.1:3306/test?characterEncoding=utf8&useSSL=true&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true&serverTimezone=Asia/Shanghai
username: root
password: root123
driver-class-name: com.mysql.cj.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource
druid:
initialSize: 2
minIdle: 2
maxActive: 30
常规而言(至少我是这么认为的,有意见的评论区见=。=),后端和前端的数据交互的格式都是采用JSON格式,那么json格式的话,一般都会有固定的几个字段比如:code、data、msg。
code:一般是返回错误码,前端会根据这个错误码进行下一步操作。
data:code成功之后,返回的具体数据,这里一般是个泛型。
msg:错误信息、成功信息(根据code来的)。
/**
* 描述:统一返回前端的实体类
*
* @author caojing
* @create 2020-11-27-13:56
*/
public class ResponseBean<T> {
/**
* 状态码,0 success,1 fail 3第一次登陆
*/
@ApiModelProperty("状态码,0 success,1 fail,2 wait")
private int code = 0;
/**
* 返回信息
*/
@ApiModelProperty("返回信息")
private String msg;
/**
* 返回的数据
*/
@ApiModelProperty("返回数据")
private T data;
public ResponseBean() {
}
public ResponseBean(int code, String msg, T data) {
this.code = code;
this.msg = msg;
this.data = data;
}
public void buildSuccessResponse(T data) {
this.code = 0;
this.data = data;
this.msg = "成功";
}
public void buildFailedResponse() {
this.code = 1;
this.msg = "失败";
}
public void buildFailedResponse(String msg) {
this.code = 1;
this.msg = msg;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
}
package com.cj.demo.bean.user;
/**
* 描述:
*
* @author caojing
* @create 2020-11-27-16:06
*/
public class UserBean {
public UserBean(int id, String name, int age, String email) {
this.id = id;
this.name = name;
this.age = age;
this.email = email;
}
private int id;
private String name;
private int age;
private String email;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
@RestController
public class UserController {
@GetMapping("/user")
public ResponseBean<UserBean> getUserInfo(@RequestParam("id") Integer id) {
ResponseBean responseBean = new ResponseBean();
responseBean.setCode(0);
responseBean.setData(new UserBean(1,"cj",12,"106067690@qq.com") );
responseBean.setMsg("成功");
return responseBean;
}
}
@RestController
这个注解其实就是@controller
+@ResponseBody
,会自动帮我们把实体类转化为json格式。启动项目,如下图所示:
我们再来看下刚才那个接口,让后台报错会怎样?如下所示:
附上全局异常处理类:
package com.cj.demo.controller;
import com.cj.demo.bean.ResponseBean;
import org.apache.shiro.ShiroException;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authz.UnauthorizedException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import javax.servlet.http.HttpServletRequest;
/**
* @author cj
* 异常捕获,遵循restful风格
*/
@RestControllerAdvice
public class ExceptionController {
private Logger logger = LoggerFactory.getLogger(ExceptionController.class);
// /**
// * 捕捉shiro的异常
// */
// @ResponseStatus(HttpStatus.UNAUTHORIZED)
// @ExceptionHandler(ShiroException.class)
// public ResponseBean handle401(ShiroException e) {
// if (e instanceof UnauthorizedException) {
// return Tools.buildResFail("无对应权限");
// } else if (e instanceof AuthenticationException) {
// return Tools.buildResFail(e.getMessage());
// }
// return new ResponseBean(401, "Shiro错误," + e.getMessage(), null);
// }
//
//
// @ResponseStatus(HttpStatus.UNAUTHORIZED)
// @ExceptionHandler(IllegalAccessException.class)
// public ResponseBean handle403() {
// return new ResponseBean(1, "非法访问", null);
// }
/**
* 捕捉其他所有异常
*/
@ExceptionHandler(Exception.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public ResponseBean globalException(HttpServletRequest request, Throwable ex) {
logger.error("异常:", ex);
return new ResponseBean(1, ex.getMessage(), null);
}
private HttpStatus getStatus(HttpServletRequest request) {
Integer statusCode = (Integer) request.getAttribute("javax.servlet.error.status_code");
if (statusCode == null) {
return HttpStatus.INTERNAL_SERVER_ERROR;
}
return HttpStatus.valueOf(statusCode);
}
}
解决方案:采用Validator 注解进行参数校验。
@NotNull
注解。@Valid
。 /**
* 对参数校验的异常处理
* @param e
* @return
*/
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseBean MethodArgumentNotValidExceptionHandler(MethodArgumentNotValidException e) {
// 从异常对象中拿到ObjectError对象
ObjectError objectError = e.getBindingResult().getAllErrors().get(0);
// 然后提取错误提示信息进行返回
return new ResponseBean(1, objectError.getDefaultMessage(), null);
}
这个是加到@RestControllerAdvice
注解的那个类里面。
分页也是我们在后端开发的时候经常遇到的一个功能,那么在不用这些第三方插件的前提下我们是如何操作的呢?
第一步:一般是根据条件查询出对应的数据然后最后加上limit进行分页。
第二步:是同样的sql去除limit只查询出符合条件的总数。
常规是需要这2个sql就可以进行分页了。但这样的话sql会有重复的代码,一种解决方案是利用<sql></sql>
来提取通用的内容。一种是借助第三方插件来实现。
第三方插件的话:我经常使用的是这个PageHelper,当然还有其他的,觉得不错的话,可以在下面评论区提出来。
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>${page-helper.version}</version>
</dependency>
BasePageRequestVO
(任何分页请求的实体类都要继承这个类)package com.cj.demo.bean.request;
import io.swagger.annotations.ApiModelProperty;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
/**
* 描述:
*
* @author caojing
* @create 2019-12-03-11:41
*/
public class BasePageRequestVO {
/**
是否需要分页,默认需要
**/
private Boolean enablePage = true;
/**
第N页
**/
private int pageNum;
/**
每页M条数
**/
private int pageSize;
/**
是否需要统计总数,默认需要
**/
private Boolean enableCount = true;
public Boolean getEnablePage() {
return enablePage;
}
public void setEnablePage(Boolean enablePage) {
this.enablePage = enablePage;
}
public int getPageNum() {
return pageNum;
}
public void setPageNum(int pageNum) {
this.pageNum = pageNum;
}
public int getPageSize() {
return pageSize;
}
public void setPageSize(int pageSize) {
this.pageSize = pageSize;
}
public Boolean getEnableCount() {
return enableCount;
}
public void setEnableCount(Boolean enableCount) {
this.enableCount = enableCount;
}
@Override
public String toString() {
return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);
}
}
新建一个UserRequestVO
类
package com.cj.demo.bean.request;
/**
* 描述:
*
* @author caojing
* @create 2020-12-02-14:29
*/
public class UserRequestVO extends BasePageRequestVO {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return super.toString();
}
}
UserController 增加如下代码
@PostMapping("/user/page")
public ResponseBean<PageInfo<List<UserBean>>> getUserInfoPage(@RequestBody UserRequestVO userRequestVO) {
PageHelper.startPage(userRequestVO.getPageNum(), userRequestVO.getPageSize());
List<UserBean> userBean = userService.selectPage();
PageInfo pageInfo = new PageInfo(userBean);
pageInfo.setList(userBean);
ResponseBean responseBean = new ResponseBean();
responseBean.setData(pageInfo);
responseBean.setCode(0);
return responseBean;
}
我们可以看下mapper的内容:
<select id="selectPage" resultMap="BaseResultMap">
select *
from user
</select>
并没有分页语句,其实上面controller最主要的一句话是:PageHelper.startPage()
这句话后面要紧跟着我们的查询语句,这样就可以实现分页效果啦,可以看下控制台打印的sql语句:
注意:本文不是介绍如何使用PageHelper,所以关于如何集成PageHelper的文明同以及PageHelper的用法大家可以出门右转百度。
其他:
其实更为方便的第三方库的话,我推荐使用 Mybatis-plus这个库,我也是最近才接触到的,他对于单表的操作实在是太方便了,一句sql都不需要要写,而且也自带分页功能。感兴趣的同学可以去看看。那有些杠精儿会问楼主了:你都推荐了,你为啥不用啊?楼主是因为用pageHelper用习惯了,所以没用,开发嘛,哪个用的习惯,用的顺手就用哪个。
basePageRequestVO
这个类。其实写代码本来就是一个归纳总结的过程,整天复制粘贴的话,对自己而言其实没啥提升,我没有贬低复制粘贴这种做法,我自己也是复制粘贴,有现成的代码干嘛不用呢?但我希望是大家用脑子的复制粘贴,别复制粘贴过来,能运行就行。那这样的话,你永远都不会进步。