1.软件的下载
已经在视频详细讲解了。
2.spring boot项目的搭建和介绍
大家好,这门课是快速入门spring boot项目实战的课程,我会把项目常用的知识点进行讲解,让大家可以快速的上手项目实战。
首先,来说一下什么是spring boot,简而言之是一个快速开发Java项目,避免繁琐配置文件的一个框架,目前是公司的主流框架,
这门课我会带大家搭建一个项目,然后教大家接口代码的编写以及返回数据的格式,拦截器的使用,AOP的使用,全局异常的处理,
整合mybatis框架操作数据库的数据,这些大家掌握了以后基本的增删改查操作就没有问题了,然后我会录制vue2的教程,学完以后
大家对于知识点就掌握的差不多了,接下来我会录制一个权限系统脚手架,整合上述的知识点进行项目实战,学完以后大家的水平就可以
独立开发学校布置的项目作业了。好的,现在我们创建第一个spring boot项目。打开Idea工具
1.选择新建项目
2.选择创建spring boot项目,选择Spring Initializr以后应该是默认的配置不需要改动
3.配置项目
4.选择依赖,这里可以直接下一步,依赖我已经准备好了
5.选择项目存放的目录,大家尽量选择英文的,点击Finish完成创建
6.介绍项目的结构
本项目pom.xml文件的依赖,大家复制进去就好了
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.38</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.3.0</version>
</dependency>
</dependencies>
标题 3.统一返回结果
解释:项目中后端需要给前端返回数据,所以需要统一格式,编写一个返回类,有状态码, 返回信息,返回数据等最基本的内容
package com.example.demo1.common;
import lombok.AllArgsConstructor;
import lombok.Data;
@Data
@AllArgsConstructor
public class Result {
private int code; //状态码
private String msg; //返回信息
private Object data;//返回数据
public static Result success(String msg){ //成功不需要返回数据
Result result = new Result(200,msg,null);
return result;
}
public static Result success(String msg,Object data){ //成功需要返回数据
Result result = new Result(200,msg,data);
return result;
}
public static Result fail(String msg){ //失败,默认状态码是500
Result result = new Result(500,msg,null);
return result;
}
public static Result fail(int code,String msg){ //失败,自定义状态码
Result result = new Result(code,msg,null);
return result;
}
}
编写一个接口看看返回结果
```java
@RestController //代表这个类是controller类,归spring容器负责并且是返回json的数据
@RequestMapping("/test") //映射路径
public class TestController {
@RequestMapping("/test")
public Result test(){
System.out.println("123");
return Result.success("helloworld","你好");
}
}
页面测试结果
到这里大家初步体验了一下项目的接口编写,接下来进入拦截器的讲解。
4.拦截器
拦截器就是在处理请求之前的操作,可以理解为去看电影,普通用户必须有电影票才可以进去,检票人员就是拦截器,是否放行的条件
就是你是否有电影票,有放行,没有不放行,接下来编写一个拦截器,看看代码是怎么用的。
拦截器代码
@Component
public class MyHandlerInterceptor implements HandlerInterceptor {
/**
preHandle:在业务处理器处理请求之前被调用。预处理,可以进行编码、安全控制、权限校验等处理;
postHandle:在业务处理器处理请求执行完成后,生成视图之前执行。后处理(调用了Service并返回ModelAndView,但未进行页面渲染),有机会修改ModelAndView (这个博主就基本不怎么用了);
afterCompletion:在DispatcherServlet完全处理完请求后被调用,可用于清理资源等。返回处理(已经渲染了页面)*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String requestURI = request.getRequestURI();
StringBuffer requestURL = request.getRequestURL();
System.out.println(requestURI);
System.out.println(requestURL);
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
}
编写以后需要注册拦截器,这样才可以在项目中使用
@Configuration
public class MyHandlerConfig implements WebMvcConfigurer {
@Autowired
private MyHandlerInterceptor myHandlerInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(myHandlerInterceptor).addPathPatterns("/**"); //代表所有的请求都会被拦截
}
}
这样一个拦截器就写好了,大家想做什么操作就可以在MyHandlerInterceptor 类的三个方法进行操作,其中preHandle用的比较多,比如鉴定用户有没有权限访问这个接口,后面项目实战我会结合springsecurity详细介绍,大家在这里只需要有一个概念就好了。
5.aop切面操作
1.介绍AOP:Aspect Oriented Programming 的缩写,意为:面向切面编程。面向切面编程的目标就是分离关注点。什么是关注点呢?
就是关注点,就是你要做的事情。比如日志操作,需要为一些方法的调用记录日志信息,所以将记录日志这个操作抽离出来
作为一个独立的操作,这样既不改变原来的方法又实现了额外的功能。
这里主要介绍几个常用的注解及使用:
1.@Pointcut 注解:用来定义一个切面(切入点),即上文中所关注的某件事情的入口。切入点决定了连接点关注的内容,使得我们可以控制通知什么时候执行。其中常用的表达式有两种:一个是使用 execution(),另一个是使用 annotation()。
execution() 为表达式主体
第一个 * 号的位置:表示返回值类型,* 表示所有类型
包名:表示需要拦截的包名,后面的两个句点表示当前包和当前包的所有子包,com.itcodai.course09.controller 包、子包下所有类的方法
第二个 * 号的位置:表示类名,* 表示所有类
*(..) :这个星号表示方法名,* 表示所有的方法,后面括弧里面表示方法的参数,两个句点表示任何参数。
annotation() 方式是针对某个注解来定义切面,比如我们对具有@GetMapping注解的方法做切面
@Pointcut("@annotation(org.springframework.web.bind.annotation.GetMapping)")
public void annotationCut() {}
2.@Before:在做某件事之前做的事。
3.@After:在做某件事之后做的事。
4.@AfterReturning:在做某件事之后,对其返回值做增强处理。
5.@AfterThrowing:在做某件事抛出异常时,处理。
2.定义一个切面类
@Aspect //代表是切面类
@Component //将这个类交给spring容器管理
public class LogAspectHandler {
/**
* 定义一个切面,拦截com.itcodai.course09.controller包和子包下的所有方法
*/
@Pointcut("execution(* com.example.demo1.controller..*.*(..))")
public void pointCut() {}
/**
* 在上面定义的切面方法之前执行该方法
* @param joinPoint jointPoint
*/
@Before("pointCut()")
public void doBefore(JoinPoint joinPoint) {
logger.info("====doBefore方法进入了====");
// 获取签名
Signature signature = joinPoint.getSignature();
// 获取切入的包名
String declaringTypeName = signature.getDeclaringTypeName();
// 获取即将执行的方法名
String funcName = signature.getName();
logger.info("即将执行方法为: {},属于{}包", funcName, declaringTypeName);
// 也可以用来记录一些信息,比如获取请求的url和ip
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
// 获取请求url
String url = request.getRequestURL().toString();
// 获取请求ip
String ip = request.getRemoteAddr();
logger.info("用户请求的url为:{},ip地址为:{}", url, ip);
}
6.全局异常处理
异常的意思很明显,就是程序发生了不符合期望的问题,就好像人生病,我给大家演示一个方法里面的异常,在TestController类的test方法制造一个异常,如图:
在页面调用这个请求,如图:
这样页面结果就不是很友好了,所以需要处理一下,让页面显示的人性化,至少用户看得懂,可以使用全局异常处理,
代码:
@ControllerAdvice
@ResponseBody
public class GlobalExceptionHandler {
private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);
/**
* 系统异常 预期以外异常
* @param ex
* @return
*/
@ExceptionHandler(Exception.class) //代表发生Exception的异常都会在这里被处理返回结果信息。
@ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
public Result handleUnexpectedServer(Exception ex) {
logger.error("系统异常:", ex);
return Result.fail(500, "系统发生异常");
}
}
加了全局异常处理以后的页面返回信息:
7.整合mybatis操作数据库的数据
MyBatis 介绍
MyBatis 框架是一个持久层框架,用来操作数据库的。Mybatis 可以让开发者的主要精力放在 sql 上,
通过 Mybatis 提供的映射方式,自由灵活的生成满足需要的 sql 语句。
7.1 MySQL数据库创建数据库,数据库下创建user表,这是最基本的一张数据表,接下来编写接口实现数据库数据的增删改查
CREATE TABLE `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(255) DEFAULT NULL,
`password` varchar(255) DEFAULT NULL,
`address` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4;
7.2 java项目编写接口,实现增删改查操作。项目中采用的是controller层接收请求并且调用service层方法,service层写业务逻辑调用mapper层,mapper层操作数据库改变数据。
UserController类
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
@RequestMapping("/findById")
public Result findById(int id){
User user = userService.findUserById(id);
if(null != user){
return Result.success("查询成功",user);
}else{
return Result.fail(500,"不存在用户");
}
}
@RequestMapping("/list")
public Result list(){
List<User> list = userService.list();
return Result.success("查询成功",list);
}
@RequestMapping("/add")
public Result add(@RequestBody User user){
int add = userService.add(user);
if(add > 0){
return Result.success("增加成功");
}else{
return Result.fail(500,"增加失败,请联系管理员");
}
}
@RequestMapping("/edit")
public Result edit(@RequestBody User user){
int edit = userService.edit(user);
if(edit > 0){
return Result.success("编辑成功");
}else{
return Result.fail(500,"编辑失败,请联系管理员");
}
}
@RequestMapping("/deleteById")
public Result deleteById(int id){
int delete = userService.deleteById(id);
if(delete > 0){
return Result.success("删除成功");
}else{
return Result.fail(500,"删除失败,请联系管理员");
}
}
}
UserService service接口类
public interface UserService {
public User findUserById(int id);
List<User> list();
int add(User user);
int edit(User user);
int deleteById(int id);
}
UserServiceImpl service实现类
@Service
public class UserServiceImpl implements UserService {
@Resource
private UserMapper userMapper;
@Override
public User findUserById(int id) {
return userMapper.findUserById(id);
}
@Override
public List<User> list() {
return userMapper.list();
}
@Override
public int add(User user) {
return userMapper.add(user);
}
@Override
public int edit(User user) {
return userMapper.edit(user);
}
@Override
public int deleteById(int id) {
return userMapper.deleteById(id);
}
}
UserMapper接口类
public interface UserMapper {
public User findUserById(@Param("id") int id);
List<User> list();
int add(User user);
int edit(User user);
int deleteById(int id);
}
mapper接口对应的mapper文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.demo1.mapper.UserMapper">
<resultMap id="BaseResultMap" type="com.example.demo1.entity.User">
<id column="id" jdbcType="BIGINT" property="id" />
<result column="user_name" jdbcType="VARCHAR" property="username" />
<result column="password" jdbcType="VARCHAR" property="password" />
<result column="address" jdbcType="VARCHAR" property="address" />
</resultMap>
<insert id="add">
insert into user(username,password,address) values(#{username},#{password},#{address})
</insert>
<update id="edit">
update user set username = #{username},password = #{password},address = #{address}
</update>
<delete id="deleteById">
delete from user where id = #{id}
</delete>
<select id="findUserById" resultType="com.example.demo1.entity.User">
select * from user where id = #{id}
</select>
<select id="list" resultType="com.example.demo1.entity.User">
select * from user
</select>
</mapper>
大家要配置一下mybatis的一个插件,更好的实现mapper接口和mapper文件的来回切换,安装以后重启IDEA就可以了,如图:
最后大家需要配置一下配置文件,
配置文件信息:
# 服务端口号
server:
port: 8080
# 数据库地址
spring:
datasource: # 数据库配置
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/test?useSSL=false&useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&autoReconnect=true&failOverReadOnly=false&maxReconnects=10
username: root
password: root
hikari:
maximum-pool-size: 10 # 最大连接池数
max-lifetime: 1770000
mybatis:
# 指定别名设置的包为所有entity
type-aliases-package: com.example.demo1.entity
configuration:
map-underscore-to-camel-case: true # 驼峰命名规范
mapper-locations: # mapper映射文件位置
- classpath:mapper/*.xml