项目预备与配置
数据库以及其他项目配置
- server:
- port: 9090
- spring:
- datasource:
- url: jdbc:mysql://localhost:3306/lostarknote
- username: root
- password: guxiang
- driver-class-name: com.mysql.cj.jdbc.Driver
- mybatis:
- configuration:
- map-underscore-to-camel-case: true
复制代码 遇到题目:找不到"url"....
可能原因:没有扫描到配置文件(yml),在pom.xml中的build标签中添加以下内容- <resources>
- <resource>
- <directory>src/main/java</directory>
- <includes>
- <include>**/*.yml</include>
- <include>**/*.properties</include>
- <include>**/*.xml</include>
- </includes>
- <filtering>false</filtering>
- </resource>
- <resource>
- <directory>src/main/resources</directory>
- <includes>
- <include>**/*.yml</include>
- <include>**/*.properties</include>
- <include>**/*.xml</include>
- </includes>
- <filtering>false</filtering>
- </resource>
- </resources>
复制代码 启动类相关
@SpringBootApplication:包扫描时,自动扫描启动类所在包及其子包,若需要扫描其他包,需要使用@ComponentScan进行包名指定
Lombok工具:
自动生成getter/setter/toString方法 ,需要引入lombok依赖,然后在实体类上添加@Data注解- <dependency>
- <groupId>org.projectlombok</groupId>
- <artifactId>lombok</artifactId>
- <version>1.18.30</version>
- </dependency>
复制代码 Result实体类
- @NoArgsConstructor
- @AllArgsConstructor
- @Data
- public class Result<T> {
- private Integer code;
- private String message;
- private T data;
- public static <E> Result<E> success(E data)
- {
- return new Result<>(0,"操作成功",data);
- }
- public static Result success(){
- return new Result(0,"操作成功",null);
- }
- public static Result error(String message) {
- return new Result(1,message,null);
- }
- }
复制代码 用户模块
注册功能:
1.密码加密
- public class MD5Util {
- //生成MD5
- public static String getMD5(String message) {
- String md5 = "";
- try {
- MessageDigest md = MessageDigest.getInstance("MD5"); // 创建一个md5算法对象
- byte[] messageByte = message.getBytes("UTF-8");
- byte[] md5Byte = md.digest(messageByte); // 获得MD5字节数组,16*8=128位
- md5 = bytesToHex(md5Byte); // 转换为16进制字符串
- } catch (Exception e) {
- e.printStackTrace();
- }
- return md5;
- }
- // 二进制转十六进制
- public static String bytesToHex(byte[] bytes) {
- StringBuffer hexStr = new StringBuffer();
- int num;
- for (int i = 0; i < bytes.length; i++) {
- num = bytes[i];
- if(num < 0) {
- num += 256;
- }
- if(num < 16){
- hexStr.append("0");
- }
- hexStr.append(Integer.toHexString(num));
- }
- return hexStr.toString().toUpperCase();
- }
- }
复制代码 2.参数校验——Spring Validation
3.全局异常处理器
- @RestControllerAdvice
- public class GobalExceptionHandler {
- @ExceptionHandler(Exception.class)
- public Result handleException(Exception e)
- {
- e.printStackTrace();
- return Result.error(StringUtils.hasLength(e.getMessage())? e.getMessage() : "操作失败!");
- }
- }
复制代码 登录功能
登录认证:JWT令牌
JWT工具类
- public class JWTUtil {
- private static final String SECRET = "guxiang";
- public static String generateToken(Map<String, Object> claims){
- return JWT.create()
- .withClaim("claims", claims)
- .withExpiresAt(new Date(System.currentTimeMillis()* 1000 * 60 * 60 * 24))
- .sign(Algorithm.HMAC256(SECRET));
- }
- public static Map<String, Object> parseToken(String token){
- return JWT.require(Algorithm.HMAC256(SECRET))
- .build()
- .verify(token)
- .getClaim("claims")
- .asMap();
- }
- }
复制代码 JWT验证:从请求头中获取token
- @RestController
- @RequestMapping("/dungeon")
- public class DungeonController {
- @GetMapping("/list")
- public Result<String> list(@RequestHeader("Authorization") String token, HttpServletResponse response) {
- //验证token
- //若能正常解析(不报错),则验证通过
- try {
- Map<String, Object> claims = JWTUtil.parseToken(token);
- return Result.success("副本数据获取成功!");
- }catch (Exception e) {
- response.setStatus(401);
- return Result.error("未登录!");
- }
- }
- }
复制代码 进阶:注册拦截器进行验证。
注册一个拦截器进行token的验证,就不用单独在每个业务代码里进行token验证- @Component
- public class LoginInterceptor implements HandlerInterceptor {
- @Override
- public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
- //令牌验证
- String token = request.getHeader("Authorization");
- //若能正常解析(不报错),则验证通过
- try {
- Map<String, Object> claims = JWTUtil.parseToken(token);
- //放行
- return true;
- }catch (Exception e) {
- response.setStatus(401);
- return false;
- }
- }
- }
复制代码- @Configuration
- public class WebConfig implements WebMvcConfigurer {
- @Autowired
- private LoginInterceptor loginInterceptor;
-
- @Override
- public void addInterceptors(InterceptorRegistry registry) {
- //登录注册不用拦截
- registry.addInterceptor(loginInterceptor).excludePathPatterns("/user/login","/user/register");
- }
- }
复制代码- @RestController
- @RequestMapping("/dungeon")
- public class DungeonController {
- @GetMapping("/list")
- public Result<String> list() {
- //这里不用再验证token,已经统一在拦截器中做验证
- return Result.success("副本数据获取成功!");
- }
- }
复制代码 登录优化——Redis
获取用户信息
ThreadLocal
- 获取用户信息需要通过token中存储的username到数据库中查找,需要解析token。
- 在其他业务可能也需要username的信息,又要解析token,为了避免代码重复,在之前拦截器中解析出的token同一放到线程中(ThreadLocal)。
- public class ThreadLocalUtil {
- //提供ThreadLocal对象
- private static final ThreadLocal THREAD_LOCAL= new ThreadLocal();
- public static <T> T get() {
- return (T) THREAD_LOCAL.get();
- }
- public static void set(Object value) {
- THREAD_LOCAL.set(value);
- }
- public static void remove() {
- THREAD_LOCAL.remove();
- }
- }
复制代码 拦截器中将数据存入ThreadLocal中,请求完成后清除ThreadLocal,防止内存泄漏- @Component
- public class LoginInterceptor implements HandlerInterceptor {
- @Override
- public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
- //令牌验证
- String token = request.getHeader("Authorization");
- //若能正常解析(不报错),则验证通过
- try {
- Map<String, Object> claims = JWTUtil.parseToken(token);
- //将数据存储到ThreadLocal中
- ThreadLocalUtil.set(claims);
- //放行
- return true;
- }catch (Exception e) {
- response.setStatus(401);
- return false;
- }
- }
- @Override
- public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
- //清空ThreadLocal中的数据,防止内存泄露
- ThreadLocalUtil.remove();
- }
- }
复制代码 接口中从ThreadLocal中获取数据- @GetMapping("/userInfo")
- public Result<User> userInfo(@RequestHeader("Authorization") String token) {
- // Map<String, Object> claims = JWTUtil.parseToken(token);
- // String username = (String) claims.get("username");
- Map<String, Object> map = ThreadLocalUtil.get();
- String username = (String) map.get("username");
- User loginUser = userService.findByUsername(username);
- return Result.success(loginUser);
- }
复制代码 @JsonIgnore
更新用户信息
实体类中参数验证
更新用户密码
参数用一个map接收,因为继续的参数名与数据库中不一致
更新用户信息时,参数名与字段名一致,所以用user实体类接收
文章模块
新增文章分类
文章分类列表
@JsonFormat
文章分类详情
更新文章分类
新增文章
自定义校验
文章分页查询
文件上传
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |