java自学阶段二:JavaWeb开发70(项目实战1之黑马tlias智能学习辅助系统)

《项目案例—黑马tlias智能学习辅助系统》
目录:

  1. 学习目标
  2. 前端页面开发
  3. 后端环境搭建
  4. 后端部门管理功能开发(查询部门、删除部门、新增部门、修改部门)
  5. 后端员工管理功能开发(查询员工、删除员工、新增员工、修改员工、文件上传、文件存储)
  6. 登录验证功能开发(登录校验,令牌技术,Filter过滤器统一拦截(JSON数据封装响应),interceptor拦截器(定义、注册配置))
  7. 统一异常处理
  8. 事务处理
  9. AOP
  10. 附录:yml配置、手机访问项目

一:学习目标:
1)后端开发:根据老师提供的接口开发文档,完成对应功能模块接口的开发(部门管理、员工管理的增删改查、阿里云文件上传、Springboot的yml配置、页面登录验证),了解日常工作中的开发流程顺序;
2)前端优化:学有余力的情况下,对比参考老师提供的前端页面进行修改;
3)手机端访问项目;
在这里插入图片描述

页面原型:
在这里插入图片描述
在这里插入图片描述
二、前端页面开发:由老师提供了前端页面。也可以自己写。
1)老师提供的界面(目前是使用老师写的):
在这里插入图片描述
2)前面自己写的…(一坨答辩)–后面开发完成后,需要自己参照着加强前端页面的开发…
在这里插入图片描述
三、后端环境搭建:
理清开发顺序:先理解开发需求—整理开发文档—搭建开发环境—根据开发文档进行功能开发;
1)开发需求+开发文档(老师提供):
在这里插入图片描述
页面原型和接口文档有具体的开发要求;

2)搭建环境:
1.建立Springboot项目,三层架构:
在这里插入图片描述
项目结构如图:
在这里插入图片描述

2.数据库准备:
DDL(定义数据):建立一个tlias数据库;建表:dept(部门表)、emp(员工表);插入数据
在这里插入图片描述

四、部门管理功能开发–四个功能(查询部门、删除部门、增加部门、编辑部门):
1)查询部门:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
2)删除部门:
功能类似,Sql稍稍不同,不再赘述;
注意点:

  • 前端传过来的可能是路径参数,在Controller层需要用@PathVariable注解去接收:
    在这里插入图片描述
  • mapper中,使用到的数据,需要预编译Sql(防止Sql注入),需要用#{ }的方式

在这里插入图片描述
3)新增部门:
功能类似,Sql稍稍不同,不再赘述,需要注意的是,发送过来的数据较多,往往会封装为一个对象,返回数据,也需要封装为一个对象返回。这时候需要使用@RequestBody注解来处理前端发送过来的数据;
在这里插入图片描述
4)修改部门:
功能类似,Sql稍稍不同,不再赘述;

五、员工管理的功能开发–六个功能(查询员工、删除员工、新增员工、修改员工、文件上传、文件存储):
因为员工查询的数据处理较多,这里员工功能接口统一用Mybatis的xml文件映射器来处理sql,与部门管理使用注解的方式不同;
1)查询员工:
查询员工的比较复杂,会涉及到分页查询和条件查询。分页查询有两种解决方法:1.调用两次数据库查询,分别查出总记录数和员工列表;2.利用分页插件PageHelper来完成;
在这里插入图片描述
方法1:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
Xml映射文件:
在这里插入图片描述
ResultType代表的是单条记录返回的类型;

方法2:使用PageHelper插件。
在这里插入图片描述
使用PageHelper的原因是,目前只是一个简单案例,就一个Emp表,需要分页查询就得定义两条查询Sql,如果后面很多表的,那每个表的分页查询都得这么写,并且还封装到PageBean中,那就很麻烦了,所以考虑引入PageHelper插件;
方法二和方法一Controller、Service、Mapper层一样,Service实现类和xml文件不一样,xml文件不用再写limit了;
在这里插入图片描述
在这里插入图片描述
在xml文件中,要把limit这一句给删掉;

注意点:
1)要注意看接口文档,发送的数据不是Json格式,而是直接以get方式来发送,需要全部接收的。不能以JSON对象的写法来接收发过来的参数,不然会提示异常:HttpMessageNotReadableException 是 Spring Framework(特别是 Spring Web MVC 和 Spring Boot 应用程序中)处理 HTTP 请求时可能会抛出的一个异常。这个异常通常发生在 Spring 尝试将接收到的 HTTP 请求消息体转换为 Java 对象时,例如使用 @RequestBody 注解的方法参数时,如果无法正确解析或读取消息内容,就会抛出此异常。
在这里插入图片描述
在这里插入图片描述

以下是可能导致 HttpMessageNotReadableException 的一些常见原因:
1.请求体为空:当一个方法通过 @RequestBody 注解期待接收请求体中的数据,但实际请求中并没有提供任何有效的内容。
2.请求体格式不正确:如果客户端发送的数据格式与控制器期望接收的数据类型(如 JSONXML 等)不符,或者数据结构不符合对应的 Java 类型映射规则。
数据内容本身有语法错误:例如 JSON 格式不完整或包含非法字符。
3.后端的实体类与前端的传入参数数据不一致:如果后端定义的实体类(如 Java 类的字段和类型)与前端发送的数据不匹配,可能会导致反序列化失败。
4.请求方式不正确:如果使用了 @RequestBody 注解但请求方法是 GETGET 请求通常不包含请求体),那么应该使用 POST 或其他支持请求体的方法。
5.跨域问题:如果后端被 @RequestBody 修饰的参数实体类没有实现序列化接口,或者没有正确解决跨域问题,也可能导致此异常。
6.请求体过大:如果请求体的大小超过了服务器配置的限制大小,也可能触发这个异常。
解决这个问题的方法取决于具体的情况,可能需要检查请求体数据、检查后端代码和配置、确保前后端数据格式一致、调整请求方式、解决跨域问题等。

Xml模板:

<?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.itheima.mapper.EmpMapper">

    <!-- 查询用户列表 -->
    <select id="queryEmpList" resultType="com.itheima.pojo.Emp">
--         这里查询出来不就全是emp吗?resultType返回的类型应该是什么?
        SELECT * FROM emp
        <where>
        <if test="name != null and name != '' ">
            name like concat('%',#{name},'%')
        </if>
        <if test="gender != null">
            and gender = #{gender}
        </if>
        <if test="begin != null and end != null">
            and entryDate between #{begin} and #{end}
        </if>
        </where>
        order by update_time desc
        limit #{page},#{pageSize}

    </select>

<!--    &lt;!&ndash; 根据 ID 查询用户 &ndash;&gt;-->
<!--    <select id="selectUserById" resultType="com.example.domain.User" parameterType="int">-->
<!--        SELECT * FROM user WHERE id = #{id}-->
<!--    </select>-->

<!--    &lt;!&ndash; 插入用户 &ndash;&gt;-->
<!--    <insert id="insertUser" parameterType="com.example.domain.User">-->
<!--        INSERT INTO user (name, email, phone) VALUES (#{name}, #{email}, #{phone})-->
<!--    </insert>-->

<!--    &lt;!&ndash; 更新用户 &ndash;&gt;-->
<!--    <update id="updateUser" parameterType="com.example.domain.User">-->
<!--        UPDATE user SET name = #{name}, email = #{email}, phone = #{phone} WHERE id = #{id}-->
<!--    </update>-->

<!--    &lt;!&ndash; 删除用户 &ndash;&gt;-->
<!--    <delete id="deleteUser" parameterType="int">-->
<!--        DELETE FROM user WHERE id = #{id}-->
<!--    </delete>-->

</mapper>

resultType的返回写法:简单来说,就是返回的每一行数据是啥,就要返回啥;
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
2)删除员工:
和前面的删除部门没有太大区别,关键在于按照接口文档,可能是会传批量删除的数据过来(是一个数组Id),这就需要遍历执行删除操作。两个遍历选择:
1.在service层,循环执行java代码;【有个问题就是需要和前端确定传入的格式是int类型数组】
在这里插入图片描述
在这里插入图片描述

2.在xml文件中,执行循环:使用foreach标签
在这里插入图片描述
在这里插入图片描述
3)新增员工:
和新增部门代码、逻辑类型,不再赘述代码细节;
1)多了一点是,要增加文件上传的功能;
2)新增员工,如果员工表是主键自增的,有可能需要拿到自增的id(主键),用于后续的逻辑处理,印象中是有一个注解的

4)修改员工:
不再赘述;
1)需要先调用一次查询,查询回显数据;
2)前端页面修改了数据后,再更新数据;

5)文件上传:
1.前端页面设计页面上传的编写,有三个要求:

  • 提交方式必须为post;
  • 必须要有有file这样的表单项;
  • 必须使用这个属性:enctype=“multipart/form-data”
    在这里插入图片描述
    2.服务端想要接收到,还是和之前一样,定义controller,然后想要接收到文件,需要使用Springboot的一个接口:MultipartFile
    在这里插入图片描述
    3.通过debug可以查看,文件上传后,会在磁盘生成.tmp后缀名的临时文件,执行完成后,会自己删掉;所以如果需要保存下来,可以对这些文件进行操作(有多少个文件,取决于你的前端页面的内容),涉及到了存储方案。
    在这里插入图片描述
    在这里插入图片描述

4.文件存储
1)磁盘本地存储:(容易收到硬件大小的限制,且要自己做好备份和容灾部署)
0.先获取上传的文件后缀;
1.为了防止文件名重复,利用UUID设置唯一文件名:
2.利用MultipartFile的方法:transferTo写入磁盘:
在这里插入图片描述
注意:Springboot有文件上传大小的限制,需要自己去properties中去调整设置,否则会报错
在这里插入图片描述
#配置单个文件最大上传大小
spring.servlet.multipart.max-file-size=10MB
#配置单个请求最大上传大小(一次请求可以上传多个文件)
spring.servlet.multipart.max-request-size=100MB

2)云存储:使用别人公司的云服务(需要自己支付一定的云服务费用)
例如:如果需要使用短信服务,自己写就得自己去对接各大短信运营商;或者调用阿里/腾讯这些的短信云服务,省去自己配置的麻烦;
在这里插入图片描述
在这里插入图片描述
打开官方的SDK示例:
在这里插入图片描述
配置步骤和老师视频有些出入:
1)打开示例文档中的简单上传–文件上传
在这里插入图片描述
2)需要AccessKeyId,往回看文档,发现需要配置Java访问凭证
在这里插入图片描述
有多种方式,这里选择STS临时凭证的方式
在这里插入图片描述
按照步骤来配置:
1.先创建用户,为用户授权、创建角色、为角色配置自定义文件上传策略
2.麻烦的是第三步,文档写得不清不楚,需要调用接口,又不给例子,后来才理解要自己写示例代码,在idea中生成访问凭证的securityToken,accessKeyId、accessKeySecret;
在这里插入图片描述
详见视频:https://help.aliyun.com/zh/oss/developer-reference/use-temporary-access-credentials-provided-by-sts-to-access-oss?spm=api-workbench.Troubleshoot.0.0.533a7185b4T8Cu#section-5xa-zdn-s0q

忍不住想吐槽,写得位置不一样,难受,卡了好久
在这里插入图片描述
在Idea中仿照示例,写生成securityToken,accessKeyId、accessKeySecret的测试代码,执行后,生成这三个:
在这里插入图片描述
3.最后,再写一个上传的类,记得这里的securityToken,accessKeyId、accessKeySecret要用生成的:
在这里插入图片描述
在这里插入图片描述
上传成功:
在这里插入图片描述
项目集成文件上传:
文件存储步骤已经清楚,那就需要与自己的项目集成。
1)构建工具类,写的是仿照官方文件上传示例代码(上面的Demo)的修改版本,并把这个类交给IOC管理。
在这里插入图片描述
2)按照接口文档,写上传的controller,返回url给用户:
在这里插入图片描述
3)联调,前端能够顺利调用,阿里云平台也有数据:
在这里插入图片描述
在这里插入图片描述

六、登录验证功能开发:
在项目中的登录是严格的;需要输入密码后才能登录,并且后续的所有请求都要带上令牌
1)登录功能
在这里插入图片描述
新建一个controller(之所以要新建一个controller,controller对应的其实是一个新的请求,而且不归属于前面的内容,所以新建一个controller)。
注意:
在MVC(Model-View-Controller)架构中,controller负责处理用户的请求,并根据这些请求执行相应的业务逻辑,然后将结果传递给视图进行展示。因此,controller的定义应该与应用程序的业务逻辑或功能模块相对应)

2)登录校验
之所以要有登录校验,是因为前面写的功能都没有添加校验的,那就是没登录,但是只要知道了请求路径,也是可以直接进入界面,这样就不是很好了。
HTTP是无状态的,意思是每一次请求都是独立的
为了起到登录校验的效果,在每一次请求的时候,都得发送一个标记,说明已经登录过了,然后设置统一拦截,所有请求都得经过这个关卡。
在这里插入图片描述
有三种技术:
1.会话技术:所谓会话,就是每一次打开浏览器,然后服务器也没有断开,这之间的通信就是一次会话,一次会话中可以包含多次请求和响应
会话跟踪:服务器需要识别对此请求是否来自同一个浏览器,然后便于后续的多次请求共享数据,重点是共享数据。
会话跟踪方案:
在这里插入图片描述
- 客户端会话跟踪技术:Cookie
1)cookie是存储在客户端/浏览器的;
在这里插入图片描述
2)cookie应用一般分三步:第一步向服务器发起请求时,服务器会自动设置cookie,然后在第二步浏览器再次发起请求时,会自动携带上cookie去请求,第三步,服务器可以获取到再次发送的请求cookie
在这里插入图片描述
Cookie存储的位置:
在这里插入图片描述
关于服务器或浏览器关闭后,cookie是否会自动删除的问题,我们可以从以下几个方面来详细解答:

一、服务器关闭后
当服务器关闭时,它并不会直接影响客户端(如浏览器)上的cookie。这是因为cookie是存储在客户端浏览器上的,而非服务器上。服务器关闭后,已经发送到客户端的cookie仍然会保留在客户端上,直到它们满足被删除的条件。
二、浏览器关闭后
对于会话cookie(Session Cookie):这类cookie在默认情况下,如果没有设置过期时间,那么它们将在用户关闭浏览器后自动删除。也就是说,这类cookie仅在浏览器打开期间有效,一旦关闭浏览器,这些cookie就会被清除。
对于持久化cookie(Persistent Cookie):如果设置了过期时间(通过setMaxAge()设置为正数),那么即使浏览器关闭,cookie也不会被删除,而是在指定的存活时间到期后才会被浏览器自动销毁。

服务端会话跟踪技术:Session
1)Session和cookie不一样,是存储在服务器的;第一步,发送请求,然后会在服务器生成JsessionId,第二步,响应回去给浏览器;第三步,浏览器再次发送请求,携带上对应的JSessionId
在这里插入图片描述
在这里插入图片描述
2)Session其实解决不了跨域的问题;那就是集群的时候不好处理

令牌技术
1)所谓的令牌,其实没有那么神秘,就是一个字符串。逻辑和cookie、session差不多,也是分三步,1.发送请求,然后在服务器生成一个字符串(我们称之为令牌);2.响应回浏览器,浏览器存储起来,这时候不一定是存储在cookie空间,哪里都可以存储,有可能是本地空间等;3.再次请求,携带上这个令牌,名称以token:XXX的方式再次请求
在这里插入图片描述
在这里插入图片描述
2)使用方式
1.先引入依赖

<!--        JWT令牌-->
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>0.9.1</version>
        </dependency>

2.现在测试中测试没问题了,然后可以抽成一个工具类,后续要集成使用,就再使用就好了
在这里插入图片描述
在这里插入图片描述
3.过滤器Filter
在这里插入图片描述
需要注意的是,Filter是javaWeb的,所以你要用Filter就得自己写类,写拦截方法。想要在Springboot项目中使用Filter,需要这几步:
在这里插入图片描述在这里插入图片描述
Springboot有它的扫描机制,只会扫描被Spring框架管理的bean,而filter其实不是属于Springboot的,而是属于javaWeb的,所以你及时放在同级包下也没有用,如果要用就得在Springboot启动类中加上@ServletComponentScan注解,这个注解可以用于自动注册实现了@WebFilter、@WebListener或@WebServlet等Servlet 3.0+规范中定义的注解的组件。

2.filter放行的操作是:

public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
    System.out.println("filter拦截了");
    filterChain.doFilter(servletRequest,servletResponse);
    System.out.println("放行了,走吧");
}

3.filter拦截路径:
在这里插入图片描述
如果配置了多个过滤器,有形成过滤器链,有先后顺序,过滤器执行顺序是一个栈,先校验,后放行。两种方式设置过滤器优先顺序
1)什么都不管,就会以过滤器名称排序
2)在@WebFilter里加入order,order值越小,越先执行该过滤器

import javax.servlet.*;  
import javax.servlet.annotation.WebFilter;  
import java.io.IOException;  
  
@WebFilter(urlPatterns = "/*", order = 1) // 设定顺序为1  
public class MyFirstFilter implements Filter {  
    @Override  
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)  
            throws IOException, ServletException {  
        System.out.println("执行 MyFirstFilter...");  
        chain.doFilter(request, response); // 继续执行过滤器链  
    }  
}

3)Filter与项目登录验证功能集成
1.先要捋顺逻辑,首先判断是否是登录操作,是就放行,不是再进行校验
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
拦截器Interceptor
1)使用Interceptor
Interceptor使用需要两步,1.要先定义拦截器,通过实现HandlerInterceptor接口来定义(需要用@Component注解声明为Springboot中的组件);2.注册拦截器,通过实现WebMvcConfigurer来实现(需要用@Configuration注解声明为配置类)
在这里插入图片描述
在这里插入图片描述

2)拦截路径的分类:
在这里插入图片描述
拦截路径,如果要拦截多个,方法addPathPatterns和excludePathPatterns,参数类型是可变的参数类型,所以随意写;

@Configuration  
public class WebConfig implements WebMvcConfigurer {  
    @Autowired  
    private LoginInterceptor loginInterceptor;  
    @Override  
    public void addInterceptors(InterceptorRegistry registry) {  
        registry.addInterceptor(loginInterceptor)  
                .addPathPatterns("/**") // 拦截所有路径  
                .excludePathPatterns("/depts/**", "/emp/**"); // 排除特定路径及其子路径  
    }  
    // 其他配置...  
}

3)拦截流程:
在这里插入图片描述
拦截的流程,Filter是Web应用架构的,所以设置后,无论如何都会经过它,然后请求会来到Spring框架中,Spring框架中定义了一个DispatcherServlet用来分发请求到对应的controller中,中间就夹着一个拦截器Interceptor;

七、统一异常处理
目前,我们的项目出现异常其实都没有处理。例如Controller调用Service,service调用mapper,然后mapper出现问题,就会一层层往上跑,最后controller也往外抛,就会抛给框架底层,底层会打印信息返回给前端。但是和前端要求返回的格式是不一致的,这样就会无法在前端页面展示给用户。

所以,我们需要一个全局的处理器。
1)定义一个全局处理器,需要利用注解:
@RestControllerAdvice = @Controller+@ResponseBody
2)方法上需要使用注解@ExceptionHandler,定义要捕获的注解类型;
在这里插入图片描述

八、事务处理
程序上面,还有业务这一层。对于不同的业务,事务管理还是很有必要的,例如,删除部门的时候,其实要删除对应部门下的员工才可以。而这时候如果不是同一个事物,就有可能导致员工删了,部门没删;或者部门删了,员工没删;
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
九、AOP
所谓的AOP,我理解是代码写了很多了,然后如果统一要对部分类似代码/同包代码进行处理,如果要全部改一遍很麻烦,不好处理。这时候,就产生了AOP的方法,把要处理的逻辑抽象具体为具体的方法,(要实现这种效果,底层是用到了注解、以及动态代理技术的),然后统一对这部分代码进行逻辑增强。
在这里插入图片描述
在这里插入图片描述
底层实现逻辑:
在这里插入图片描述
AOP的好处:

在这里插入图片描述
AOP关键知识:
1)使用步骤:
1.引入依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

2.定义一个类,使用注解@Aspect,@Component,声明这个类为AOP类,归属于springboot管理;

3.按照模板来写具体要抽取的核心逻辑

@Around("execution(* com.itheima.service.*.*(..))")//这是around的写法
//方法参数是固定的,定义为了proceedingJoinPoint
public Object recordTime(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
    long begin = System.currentTimeMillis();//其他要在这个方法上执行的逻辑
    Object object = proceedingJoinPoint.proceed(); //调用对应匹配到的方法,然后运行
    long end = System.currentTimeMillis();
    log.info(proceedingJoinPoint.getSignature()+"执行耗时: {}ms", end - begin);
    return object;
}

2)AOP的概念:
在AOP中,通知(Advice)表示要在目标方法上执行的额外逻辑,而切面(Aspect)则负责定义通知应该应用到哪些连接点(Join Point)上。连接点是程序执行过程中的一个点,如方法的调用或异常的处理。
在这里插入图片描述
核心概念:
1)通知:
在这里插入图片描述
记住:只有Around才需要自己调一遍proceed,其他的其实没有必要;
在这里插入图片描述
通知顺序
在这里插入图片描述
2)切入点表达式
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
3)连接点
在这里插入图片描述
4)切入点
在这里插入图片描述
5)案例:将案例中 增、删、改 相关接口的操作日志记录到数据库表中
1.定义一个切面类、定义好日志表实体类、以及mapper(插入数据库表的操作):
注意:还要新建一个自定义注解类
在这里插入图片描述
2.在切面类中抓取要记录的日志数据:

//    @Around("execution(* com.itheima.service.impl.*.*(..))")
   @Around("@annotation(com.itheima.anno.Log)")
   //这里使用注解类,是为了方便针对具体的方法使用,而不是放到包这个维度,不好管控
    public Object recordTime(ProceedingJoinPoint proceedingJoinPoint) throws Throwable{
//        proceedingJoinPoint.getThis();
        //记录操作人ID - 当前登录员工ID
        //获取请求头中的jwt令牌, 解析令牌
        String jwt = httpServletRequest.getHeader("token");
        Claims claims = JwtUtils.parseJwt(jwt);
        Integer operateUser = (Integer) claims.get("id");
        //获取操作时间
        LocalDateTime operateTime = LocalDateTime.now();
        //获取操作的类名
        String className = proceedingJoinPoint.getTarget().getClass().getName();
        //获取操作的方法名
        String methodName = proceedingJoinPoint.getSignature().getName();
        //获取方法参数
        Object[] Params = proceedingJoinPoint.getArgs();
        String methodParams = Arrays.toString(Params);
        //获取返回值
        String returnValue = proceedingJoinPoint.getKind();

        long begin = System.currentTimeMillis();
        Object object = proceedingJoinPoint.proceed(); //调用原始方法运行
        long end = System.currentTimeMillis();
        long costTime = end - begin;
        log.info(proceedingJoinPoint.getSignature()+"执行耗时: {}ms", end - begin);
        OperateLog operateLog = new OperateLog(operateUser,operateTime,className,methodName,methodParams,returnValue,costTime);
        LogMapper.insertLog(operateLog);
        return object;
    }

3.具体的类中,需要加上@log注解(好像一般都是加在controller的…是因为这是一切的开始吗?)
在这里插入图片描述

附录1:Springboot的yml配置
在Springboot项目中,经常要在application.properties中写配置;还有另外一种方式写配置,那就是yml文件。
1)编写yml文件
在这里插入图片描述
在这里插入图片描述

yml语法:缩进是严格的,层级不正确有可能读取不了配置;

  • 大小写敏感数值前边必须有空格,作为分隔符
  • 使用缩进表示层级关系,缩进时,不允许使用Tab键,只能用空格(idea中会自动将Tab转换为空格)
  • 缩进的空格数目不重要,只要相同层级的元素左侧对齐即可
  • #表示注释,从这个字符一直到行尾,都会被解析器忽略

在这里插入图片描述

2)写完yml文件后,如果要使用yml文件中的数据,有两种使用方式:
1.利用@Value这个注解,为属性进行单个的赋值:@Value 注解通常用于外部配置的属性注入,具体用法为: @Value(“${配置文件中的key}”)
在这里插入图片描述
类必须交给IOC管理;使用Component管理;
在这里插入图片描述
2.如果感觉写value,要每一个都写一遍前缀太麻烦,还可以全部提到开头,用一个前缀代替:
在这里插入图片描述
附录2:手机访问项目:

如果您已经确认手机和电脑连接的是同一个WiFi网络,并且您尝试通过https://[电脑地址]:90访问项目但无法成功,可能有几个原因:

使用了HTTPS而不是HTTP:如果您的Nginx服务器没有配置SSL证书来支持HTTPS,那么使用https://协议来访问是无法成功的。默认情况下,Nginx不会为90端口配置SSL,除非您明确进行了设置。如果您只是想通过HTTP访问项目,您应该使用http://[电脑地址]:90。

防火墙或安全组策略:电脑的防火墙或路由器的安全策略可能阻止了90端口的外部访问。您需要检查电脑的防火墙设置,确保90端口是开放的。如果您使用的是公司或学校的网络,还可能需要咨询网络管理员。

Nginx配置问题:可能Nginx没有正确配置来监听90端口,或者没有正确设置来提供前端项目的文件。您需要检查Nginx的配置文件,确保server块中的listen指令设置为90,并且root指令指向了正确的项目目录。

网络问题:尽管手机和电脑连接的是同一个WiFi,但有时候网络设置或路由器的问题可能导致它们之间无法正常通信。您可以尝试重启路由器或检查网络的连接情况。

浏览器缓存或DNS问题:有时候,浏览器缓存或DNS缓存可能导致访问问题。您可以尝试清除浏览器缓存或使用其他浏览器尝试访问。

IP地址输入错误:请确保您输入的IP地址是正确的,并且没有输入错误。

为了解决这个问题,您可以按照以下步骤操作:

检查Nginx配置:确保Nginx配置文件中有一个server块监听在90端口,并且项目的根目录设置正确。
重启Nginx服务:在修改Nginx配置文件后,需要重启Nginx服务来使更改生效。
检查防火墙设置:确保电脑的防火墙没有阻止90端口的访问。
尝试使用HTTP:如果您没有配置SSL证书,尝试使用http://[电脑地址]:90来访问项目。
检查网络连接:确保手机和电脑都能正常连接到WiFi网络,并且没有其他网络问题。
如果以上步骤都无法解决问题,您可能需要进一步检查Nginx的错误日志,或者在命令行中使用工具(如curl或telnet)来测试端口是否开放和Nginx是否响应。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值