概述
SpringBoot
SpringBoot声称可以很简单地创建独立的生产级的直接运行的Spring应用,那我们就来手撕一个试试。
创建项目
打开IntelliJ IDEA,新建项目:Spring Initializr。
配置:
Name: InitProj
Language: Kotlin
Type: Gradle
Sdk: jbr-11
Java: 11
SpringBoot: 2.7.3
Dependences: Web>SpringWeb
start.spring.io 打不开?你可能需要一点上网技术。
配置阿里云仓库
如果你想依赖包下载快一点,建议配置阿里云仓库。
打开 build.gradle.kts 在 repositories 中添加两具仓库:
maven {
setUrl("https://maven.aliyun.com/repository/public/")
}
maven {
setUrl("https://maven.aliyun.com/repository/spring/")
}
HelloWord
创建Kolin类HelloController
@RestController
class HelloController {
@GetMapping("/hello")
fun hello(): String{
return "hello"
}
}
运行启动项目
浏览器输入
http://localhost:8080/hello
Ok,小试水果刀,前菜结束。
响应数据结构化
新需求:返回数据是这样 json
{"code":0,"message":"success","data":"hello"}
我们需要:
一个定义错误信息的 Data Class
data class AError(val code: Int, val msg: String)
一些常见的错误信息
inline val SUCCESS
get() = AError(0, "success")
inline val ERROR_UNKNOWN
get() = AError(-1, "unknown")
inline val PARAMS_NULL
get() = AError(-2, "缺少必填参数")
inline val SESSION_ERROR
get() = AError(-3, "session失效")
一个存储响应结果的 Data Class
data class Result(
var code: Int = 0,
var message: String = "",
var data: Any? = null
)
一些常见的结果
fun succeed(data: Any?) = Result(SUCCESS.code, SUCCESS.msg, data)
fun succeed() = succeed(null)
fun failed(err: AError) = Result(err.code, err.msg, null)
然后修改一下 hello 处理函数
@GetMapping("/hello")
fun hello(): Result{
return succeed("hello")
}
再次运行一下,结果是我们想要的。SpringBoot 帮我们做了比较多的处理,这里不作细论。
异常处理
如果程序发生错误,前端会得到这样的结果:
{
"timestamp": "2022-08-26T14:34:48.440+00:00",
"status": 500,
"error": "Internal Server Error",
"path": "/hello"
}
我们希望得到这样的结果:
{"code":-1,"message":"unknown","data":null}
前端的格式比较统一,方便处理。
首先自定义一个异常
class MyException(val err: AError) : RuntimeException(err.msg)
然后添加一个异常处理组件,SpringBoot 会在异常发生时调用它来处理。
@ControllerAdvice
class ExceptionHandler {
companion object {
private const val TAG = "ExceptionHandler"
}
@ExceptionHandler(Exception::class)
@ResponseBody
fun handle(e: Exception): Result {
val result = if (e is MyException) {
failed(e.err)
} else {
failed(ERROR_UNKNOWN)
}
Log.e(TAG, e)
return result
}
}
这样如果发生我们定义的错误,会返回对应信息;其他错误则返回未知。
测试一下Hello:
@GetMapping("/hello")
fun hello(): Int{
// return 2/0
return failed(PARAMS_NULL)
}
结果是我们想要的。
参数校验
请求参数需要先过滤一遍,防止引入未知错误。
虽然 Spring 有@Valid 注解可以很方便地验证请求参数的合法性,但是我更倾向于自定义验证内容。
首先定义一个抽象类 ARequest,作为所有请求参数的父类。
abstract class ARequest {
// 验证参数
abstract fun validate()
// 检验参数是否为空
fun paramsNotBlank(vararg params: String){
params.forEach {
if(it.isBlank()){
throw MyException(PARAMS_NULL)
}
}
}
}
然后定义一个切面,在特定函数执行前进行参数校验。
@Aspect
@Component
class RequestAspect {
companion object{
private const val TAG = "RequestAspect"
}
@Pointcut("execution(public * *(ARequest+,..))")
fun point(){}
@Before("point()")
fun checkRequest(join: JoinPoint){
join.args.forEach {
if(it is ARequest){
it.validate()
}
}
}
}
面向切面编程需要引入依赖
implementation(“org.springframework.boot:spring-boot-starter-aop:2.7.3”)
切点"execution(public * *(ARequest+,…))"的意思是:在任何类型为public,第一个参数是ARequest的子类的函数处作切点。
本例中如果需要指定打招呼的人名,可以这样定义请求参数:
data class HelloRequest(
var name: String = "",
): ARequest(){
override fun validate() {
paramsNotBlank(name)
}
}
修改 Hello 函数:
@GetMapping("/hello")
fun hello(request: HelloRequest): Result{
return succeed("Hello ${request.name}")
}
不指定name参数时,返回:
{"code":-2,"message":"缺少必填参数","data":null}
指定name 为 Tom , 返回:
{"code":0,"message":"success","data":"Hello Tom"}
总结
SpringBoot 为我们做了相当多的配置工作,使用起来很便捷。本篇文章没有原理解释,更像一道练习题,用来熟悉 SpringBoot 的起手式,更多细节以后探讨。
源码:https://gitee.com/yoshii_x/init-proj.git
最后
以上就是可爱星星为你收集整理的直接上手SpringBoot创建Web项目SpringBoot创建项目总结的全部内容,希望文章能够帮你解决直接上手SpringBoot创建Web项目SpringBoot创建项目总结所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复