跳转至

起步配置

  • Maven仓库

Maven Repository: Search/Browse/Explore

  • 阿里云

阿里云登录页

Spring配置yaml

src/main/resources/application.yaml

#mysql
spring:
  datasource:
       url: jdbc:mysql://localhost:3306/tlias_db  # 数据库连接地址
       username: root # 数据库用户名
       password: 1234 # 数据库密码
       driver-class-name: com.mysql.cj.jdbc.Driver # 数据库驱动
#mybatis
mybatis:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl   # 打印sql语句到控制台
    map-underscore-to-camel-case: true #开启驼峰
  mapper-locations: classpath:mapper/*.xml  # 指定mapper的xml映射文件的位置
  type-aliases-package: com.itheima.tliasmanage.pojo  # 指定实体类包名
#端口被占用时使用
#server:
#  port: 9999

MyBatis xml

src/main/resources/mapper/[实体类名称]Mapper.xml

1
2
3
4
5
6
7
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="">

</mapper>

log配置

src/main/resources/logback.xml

<?xml version="1.0" encoding="UTF-8"?>

<!--
    配置1:日志的输出位置
          <appender  class="控制台/文件/数据库/MQ/... ...">
    配置2:日志的输出形式
          <pattern>时间/级别/类名称/线程名称/信息/... ...</pattern>
    配置3:日志的开关
          <root level="开启/关闭/日志级别">
-->
<configuration>
    <!--CONSOLE :表示当前的日志信息是可以输出到控制台的。-->
    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <!--输出流对象 默认 System.out 改为 System.err-->
        <target>System.out</target>
        <encoder>
            <!--格式化输出:
                %d表示日期,
                %thread表示线程名,
                %-5level:级别从左显示5个字符宽度
                %msg:日志消息,
                %n是换行符
                -->
            <pattern>雪之下雪乃=:%d{yyyy-MM-dd HH:mm:ss.SSS} [%-5level]  %c [%thread] : %msg%n</pattern>
        </encoder>
    </appender>

    <!-- File是输出的方向通向文件的 -->
<!--    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">-->
<!--        <encoder>-->
<!--            <pattern>东阳妹妹&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;:%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>-->
<!--            <charset>utf-8</charset>-->
<!--        </encoder>-->
<!--        &lt;!&ndash;日志输出路径&ndash;&gt;-->
<!--        <file>E:/tlias_log/itheima-data.log</file>-->
<!--        &lt;!&ndash;指定日志文件拆分和压缩规则&ndash;&gt;-->
<!--        <rollingPolicy-->
<!--                class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">-->
<!--            &lt;!&ndash;通过指定压缩文件名称,来确定分割文件方式&ndash;&gt;-->
<!--            <fileNamePattern>D:/log/itheima-data-%i-%d{yyyy-MM-dd}-.log.gz</fileNamePattern>-->
<!--            &lt;!&ndash;文件拆分大小&ndash;&gt;-->
<!--            <maxFileSize>1MB</maxFileSize>-->
<!--        </rollingPolicy>-->
<!--    </appender>-->

    <!--
        1、控制日志的输出情况:如,开启日志,取消日志
    -->
    <root level="info">
        <appender-ref ref="CONSOLE"/>
    </root>
</configuration>

阿里云依赖

pom.xml

<!--阿里云oss-->
        <dependency>
            <groupId>com.aliyun.oss</groupId>
            <artifactId>aliyun-sdk-oss</artifactId>
            <version>3.17.4</version>
        </dependency>
        <dependency>
            <groupId>javax.xml.bind</groupId>
            <artifactId>jaxb-api</artifactId>
            <version>2.3.1</version>
        </dependency>
        <dependency>
            <groupId>javax.activation</groupId>
            <artifactId>activation</artifactId>
            <version>1.1.1</version>
        </dependency>
        <!-- no more than 2.3.3-->
        <dependency>
            <groupId>org.glassfish.jaxb</groupId>
            <artifactId>jaxb-runtime</artifactId>
            <version>2.3.3</version>
        </dependency>

阿里云参数配置化

applications.yaml

1
2
3
4
5
aliyun:
  oss:
    endpoint: oss-cn-beijing.aliyuncs.com
    bucketName: hua-bei-huabei
    region: cn-beijing

使用参数

  1. @Value注解
1
2
3
4
5
6
7
8
@Value("${aliyun.oss.endpoint}")
private String endpoint;

@Value("${aliyun.oss.bucketName}")
private String bucketName;

@Value("${aliyun.oss.region}")
private String region;
  1. 创建实体类
1
2
3
4
5
6
7
8
@Data
@Component
@ConfigurationProperties(prefix = "aliyun.oss")
public class AliOSSProperties {
    private String endpoint;
    private String bucketName;
    private String region;
}

使用实体类的参数

1
2
3
4
5
6
String endpoint;
String bucketName;
String region;
endpoint = aliOSSProperties.getEndpoint();
bucketName = aliOSSProperties.getBucketName();
region = aliOSSProperties.getRegion();

JWT令牌

1
2
3
4
5
6
<!--jjwt令牌生成和解析-->
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>0.9.1</version>
        </dependency>

令牌工具类

src/main/java/com/itheima/tliasmanage/util/JwtUtils.java

public class JwtUtils {

    private static String signKey = "SVRIRUlNQQ==";
    private static Long expire = 43200000L;

    /**
     * 生成JWT令牌
     * @return
     */
    public static String generateJwt(Map<String,Object> claims){
        String jwt = Jwts.builder()
                .addClaims(claims)
                .signWith(SignatureAlgorithm.HS256, signKey)
                .setExpiration(new Date(System.currentTimeMillis() + expire))
                .compact();
        return jwt;
    }

    /**
     * 解析JWT令牌
     * @param jwt JWT令牌
     * @return JWT第二部分负载 payload 中存储的内容
     */
    public static Claims parseJWT(String jwt){
        Claims claims = Jwts.parser()
                .setSigningKey(signKey)
                .parseClaimsJws(jwt)
                .getBody();
        return claims;
    }
}

过滤器

src/main/java/com/itheima/tliasmanage/filter/LoginFilter.java

在启动类添加@ServletComponentScan

@ServletComponentScan 是Spring Boot注解,用于自动扫描和注册Servlet、Filter、Listener等Web组件。它会扫描指定包路径下的Web组件,并将其自动注册到Servlet容器中,简化了传统web.xml配置方式。

在过滤器类添加@WebFilter("/*")注解,拦截所有地址,重写doFilter方法

@Slf4j
@WebFilter("/*")
public class LoginFilter implements Filter {
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;

        //获取请求路径
        String url = request.getRequestURL().toString();
        log.info("filter过滤请求路径{}",url);
        if(url.contains("/login")){
            log.info("filter过滤登录请求,直接放行");
            filterChain.doFilter(request,response);
            return;
        }
        String token = request.getHeader("token");

        if(token==null){
            log.info("filter过滤请求,没有令牌,直接封装未授权的响应信息");
            response.setStatus(401);
            return;
        }
        try {
            JwtUtils.parseJWT(token);
        }catch (Exception e){
            log.info("filter过滤请求,令牌无效,直接封装未授权的响应结果");
            response.setStatus(401);
            return;
        }
        log.info("filter过滤请求,令牌有效,直接放行");
        filterChain.doFilter(request,response);

    }

}

拦截器

src/main/java/com/itheima/tliasmanage/Interceptor/LoginInterceptor.java

WebConfig.class 配置文件

/**
 * springmvc配置类:
 *     配置拦截器、异常处理、视图解析器、消息转换器
 */
@Configuration
public class WebConfig  implements WebMvcConfigurer {
    @Autowired
    private LoginInterceptor loginInterceptor;
    //注册拦截器到springmvc框架中
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //使用方法提供的拦截器注册器进行注册
        registry.addInterceptor(loginInterceptor)
                //配置拦截器:拦截的路径
                .addPathPatterns("/**")//拦截所有请求
                .excludePathPatterns("/login");
    }
}

登录拦截流程

@Slf4j
@Component
public class LoginInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        String token = request.getHeader("token");

        if(token==null){
            log.info("LoginInterceptor拦截请求,没有令牌,直接封装未授权的响应信息");
            response.setStatus(401);
            return false;
        }
        try {
            JwtUtils.parseJWT(token);
        }catch (Exception e){
            log.info("LoginInterceptor拦截请求,令牌无效,直接封装未授权的响应结果");
            response.setStatus(401);
            return false;
        }
        log.info("LoginInterceptor拦截请求,令牌有效,直接放行");
        return true;

    }
}

image

image

image

分页插件:PageHelper

1
2
3
4
5
6
        <!--分页插件PageHelper-->
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper-spring-boot-starter</artifactId>
            <version>2.1.1</version>
        </dependency>

引入Element-Plus

src\main.js

import { createApp } from 'vue'
import { createPinia } from 'pinia'

import App from './App.vue'
import router from './router'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import zhCn from 'element-plus/es/locale/lang/zh-cn'
import * as ElementPlusIconsVue from '@element-plus/icons-vue'

import './assets/main.css'

const app = createApp(App)

app.use(createPinia())
app.use(router)
app.use(ElementPlus, {locale: zhCn})
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
  app.component(key, component)
}

app.mount('#app')

封装axios

以部门管理为例

src\utils\request.js

/* 处理请求的工具类:统一配置请求配置信息,请求的拦截器(请求和响应) */
import axios from 'axios'

/* 1.创建axios实例 */
const request = axios.create({
  baseURL: '/api', // 在ajax请求路径中,追加/api,标识当前请求是后台接口请求
  timeout: 8888 // 请求超时时间
});


/* 2.响应拦截器 :处理响应数据,简化响应数据处理操作*/
request.interceptors.response.use(
    // 成功回调
    response => {
        return response.data ;// ajax请求成功,将封装了响应结果数据的result对象的data属性返回
    },
    // 失败回调
    error => {
        return Promise.reject(error);// ajax请求失败,将错误对象原封不动的返回给后续处理者进行处理
    }
);
/* 3.请求拦截器:拦截ajax请求,在ajax请求发送出去之前,添加令牌到请求头中*/
request.interceptors.request.use(
    (config) => {
        // 获取令牌
        const loginUserInfoStr = localStorage.getItem('yuge');
        const loginUser = JSON.parse(loginUserInfoStr);


        if(loginUser && loginUser.token){
            // 添加令牌
            config.headers['token'] = loginUser.token;
        }

        return config;// 请求发送出去
    },
    (error) => {
        return Promise.reject(error);
    }
);

/* 3.导出封装好的axios对象 */
export default request;

src\api\dept.js

//1.导入axios对象
import request from "../utils/request";
//2.定义请求获取所有部门信息的方法

//查询所有部门信息
export const queryAllDeptApi = () => request.get("/depts");
//添加部门
export const addDeptApi = (data) => request.post("/depts", data);
//通过id查询部门
export const queryDeptByIdApi = (id) => request.get(`/depts/${id}`);
//修改部门
export const updateDeptApi = (data) => request.put(`/depts`, data);
//删除部门
export const deleteDeptById = (id) => request.delete(`/depts/?id=${id}`);