springboot基本语法及应用
以下解析和应用均针对前后端分离的springboot
1. 各个层级解析
分成了几个层级:
1.1 层级关系
参考:层级关系解析
1.2 层级作用
参考:层级作用
- entity层
同类: model层 = entity层 = domain层
作用: 用于存放我们的实体类,与数据库中的属性值基本保持一致。
- mapper层
同类: mapper层 = dao层
作用: 对数据库进行数据持久化操作,他的方法语句是直接针对数据库操作的
- service层
同类: 只有一个 service层
作用: service层 是针对 controller层的 controller,也就是针对我们使用者。
service的 impl 是把mapper和service进行整合的文件。
- controller层
同类: controller层 = web 层
作用: 控制器,导入service层,因为service中的方法是我们使用到的,controller通过接收前端传过来的参数进行业务操作,再将处理结果返回到前端。
2. 数据库:MyBatis
增删改查语法:
<?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.main.datainfo.mapper.UserMapper">
<select id="getAllUsers" resultType="User">select * from user</select>
<select id="getUserByPhone" resultType="User">select * from user where phone=#{phone}</select>
<insert id="insertUser">
insert into user(name,password,phone,job,question,answer, tags)
values (#{name},#{password},#{phone},#{job},#{question},#{answer},#{tags})
</insert>
<update id="updatePasswd">
update user set password = #{new_password} where phone = #{phone}
</update>
</mapper>
其中,id要和Mapper中的id相对应
2.1 踩坑
2.1.1 查询出来结果为null或0
数据库字段名设置成了带下划线的:user_id,查询结果为0,改成varchar类型的查询结果为null,结果发现是MyBatis机制的问题。要么自己设置resultMap,要么去掉下划线。
参考:[MyBatis踩坑]正确执行sql并在控制台打印,取值却为[null]==>带下划线的字段名
2.2 应用
2.2.1 浏览文章记录查询
具体需求:
查询某用户浏览文章的信息。
需要注意:
可能某用户在前一个时刻浏览了这篇文章,后一个时刻再次浏览了这个文章,表中只出现这个文章一次,且是最新的浏览结果。
注:用到了PageHelper工具。
查询语句如下:
<select id="getBehaviorsByUserIDAndType" resultType="com.main.datainfo.entity.Behavior">
select * from behavior where id in (
select max(id) from behavior
where userID=#{userID} and type=#{type} group by articleID order by time desc
) order by time desc
</select>
参考:PageHelper的基本使用
用到PageHelper的语句如下:
@Override
public List<Behavior> getBehaviorsByUserIDAndTypeByPage(int userID, int type, int pageNum,int pageSize){
PageHelper.startPage(pageNum, pageSize);
return behaviorMapper.getBehaviorsByUserIDAndType(userID, type);
}
3. 权限管理
非常全:一看就懂!基于Springboot 拦截器的前后端分离式登录拦截
3.1 创建拦截器
package com.main.datainfo.interceptor;
import com.main.datainfo.entity.User;
import com.main.datainfo.service.AuthService;
import com.main.datainfo.utils.HttpContextUtil;
import com.main.datainfo.utils.Result;
import com.main.datainfo.utils.TimeUtil;
import com.main.datainfo.utils.TokenUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import com.alibaba.fastjson.JSON;
import org.apache.commons.lang.StringUtils;
import org.springframework.web.servlet.ModelAndView;
import java.time.LocalDateTime;
public class AuthInterceptor implements HandlerInterceptor {
@Autowired
private AuthService authService;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException {
String token = TokenUtil.getRequestToken(request);
//如果token为空
if (StringUtils.isBlank(token)) {
setReturn(response,400,"用户未登录,请先登录");
return false;
}
//1. 根据token,查询用户信息
User user = authService.findByToken(token);
//2. 若用户不存在,
if (user == null) {
setReturn(response,400,"用户不存在");
return false;
}
//3. token失效
if (TimeUtil.StringToLocalDateTime(user.getExpireTime()).isBefore(LocalDateTime.now())) {
setReturn(response,400,"用户登录凭证已失效,请重新登录");
return false;
}
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
}
//返回错误信息
private static void setReturn(HttpServletResponse response, int status, String msg) throws IOException {
HttpServletResponse httpResponse = (HttpServletResponse) response;
httpResponse.setHeader("Access-Control-Allow-Credentials", "true");
httpResponse.setHeader("Access-Control-Allow-Origin", HttpContextUtil.getOrigin());
//UTF-8编码
httpResponse.setCharacterEncoding("UTF-8");
response.setContentType("application/json;charset=utf-8");
Result build = Result.build(status, msg);
String json = JSON.toJSONString(build);
httpResponse.getWriter().print(json);
}
}
3.2 注册拦截器:Config类
import com.main.datainfo.interceptor.AuthInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
InterceptorRegistration registration = registry.addInterceptor(new AuthInterceptor());
registration.addPathPatterns("/**");//所有路径都被拦截
registration.excludePathPatterns("/login");//login不被拦截
}
}
3.3 service和serviceImpl类
package com.main.datainfo.service;
import com.main.datainfo.entity.User;
public interface AuthService {
User findByPhone(String phone);
User findByToken(String token);
String createToken(User user);
//根据token去修改用户token ,使原本token失效
void logout(String token);
}
用到了UserMapper中的一些查询操作
package com.main.datainfo.service.impl;
import com.main.datainfo.entity.User;
import com.main.datainfo.mapper.UserMapper;
import com.main.datainfo.service.AuthService;
import com.main.datainfo.utils.TimeUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
import java.util.UUID;
@Service
public class AuthServiceImpl implements AuthService {
@Autowired
private UserMapper userMapper;
@Override
public User findByPhone(String phone) {
return userMapper.getUserByPhone(phone);
}
@Override
public User findByToken(String token) {
return userMapper.getUserByToken(token);
}
//12小时后失效
private final static int EXPIRE = 12;
@Override
public String createToken(User user) {
//用UUID生成token
String token = UUID.randomUUID().toString();
//当前时间
LocalDateTime now = LocalDateTime.now();
//过期时间
LocalDateTime expireTime = now.plusHours(EXPIRE);
//保存到数据库
user.setLoginTime(TimeUtil.LocalDateTimetoString(now));
user.setExpireTime(TimeUtil.LocalDateTimetoString(expireTime));
user.setToken(token);
userMapper.updateLoginInfo(user);
return token;
}
@Override
public void logout(String token) {
User user = userMapper.getUserByToken(token);
//用UUID生成token
token = UUID.randomUUID().toString();
//修改用户的token使原本的token失效,前端需配合将token清除
user.setToken(token);
userMapper.updateLoginInfo(user);
}
}
3.4 Controller类
package com.main.datainfo.controller;
import com.main.datainfo.entity.Token;
import com.main.datainfo.entity.User;
import com.main.datainfo.service.AuthService;
import com.main.datainfo.utils.Result;
import com.main.datainfo.utils.TokenUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
@RestController
@RequestMapping
public class AuthController {
@Autowired
AuthService authService;
@RequestMapping("/login")
public Result login(HttpServletRequest request) {
String phone = request.getParameter("phone");
String password = request.getParameter("password");
//System.out.println(phone+" "+password);
//用户信息
User user = authService.findByPhone(phone);
//账号不存在、密码错误
if (user == null || !user.getPassword().equals(password)) {
return Result.build(400, "用户名或密码错误");
} else {
//生成token,并保存到数据库
String token = authService.createToken(user);
Token tokenVO = new Token();
tokenVO.setToken(token);
return Result.ok(tokenVO);
}
}
@PostMapping("/logout")
public Result logout(HttpServletRequest request) {
//从request中取出token
String token = TokenUtil.getRequestToken(request);
authService.logout(token);
return Result.ok();
}
@RequestMapping("/test")
public Result test() {
return Result.ok("恭喜你,验证成功啦,我可以返回数据给你");
}
}
4. 文件预览
参考我的其他博文:
[1] 【后端学习】SpringBoot网站后端将Word或其他Office文件转成pdf再按页转成图片在前端展示(linux)
[2] 【后端学习】springboot后端把ppt文件转成pdf