软件测试最全【总结】网页状态码——200正常、302重定向(3),软件测试高级开发工程师面试题

img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上软件测试知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

需要这份系统化的资料的朋友,可以戳这里获取

400异常----传参相关的异常

get方法长度限制

在这里插入图片描述

400异常,加了@RequestParam(value = “name”) 必须传值

在这里插入图片描述

400异常,后端类型是Integer,前端传的是string,转换失败

在这里插入图片描述

400异常,日期格式转换失败

Failed to convert from type [java.lang.String] to type [java.util.Date] for value ‘2021-5-28’; nested exception is java.lang.IllegalArgumentException]

在这里插入图片描述

404异常----页面找不到

在这里插入图片描述

302重定向—地址变化

在这里插入图片描述

【bug】302重定向,ERR_TOO_MANY_REDIRECTS,如果配置类中的,excludePathPatterns忘记加第一个反斜杠 /

报错:ERR_TOO_MANY_REDIRECTS

原因:.excludePathPatterns里面的路径反斜杠没加

在这里插入图片描述

304—客户端有缓存

访问静态资源时,如果服务器认为静态文件没有变,就会返回304状态码

在这里插入图片描述

再次访问时,服务器认为自己的图片没变,所以报304

在这里插入图片描述

存在问题,如果验证码是一张图片,那浏览器清理的缓存,结果用户请求服务器的静态图片时,就拿不到了,解决方法,骗一下服务器,每次加一个?,服务器就会再次发一下

在这里插入图片描述

405异常:服务器只能处理post,浏览器请求的是get方法

在这里插入图片描述

网页状态码415

报错信息:

spring后台的报错:

Resolved [org.springframework.web.HttpMediaTypeNotSupportedException: Content type ‘application/x-www-form-urlencoded;charset=UTF-8’ not supported]

浏览器的报错:

在这里插入图片描述

报错原因:传的是字符串,接收的时候加了@RequestBody,表示用对象接收,就报415异常

在这里插入图片描述

解决方案:

// public ResData queryById(@RequestBody Integer id){ // TODO:415异常
    public ResData queryById(Integer id){

// axios.post("/build/id",this.id)// TODO:415异常
axios.get("/build/id?id="+this.id)

深入理解axios的所谓的post请求:

在post请求中,通过用new URLSearchParams(),发送post请求,其实本质是以String类型的键值对发送给后端的

                let params = new URLSearchParams();
                let listParam = {"buildingIdList":this.selectedBuildingList}
                params.set("buildingList",this.selectedBuildingList)
                params.set("areaMin",this.areaMin)
                params.set("areaMax",this.areaMax)
                params.set("areaOrderASC",this.areaOrderASC)
                params.set("areaOrderDESC",this.areaOrderDESC)
                console.log(listParam)
                console.log(params)
                axios.post("/owner/query/house",params)

<string,string>类型的键值对

在这里插入图片描述

在这里插入图片描述

通常看到的表单数据是这样,

在这里插入图片描述

本质其实就是下面这个,和get请求就差一个?,区别是一个是拼在浏览器的地址栏的路径上,另一个是放在请求头里面;

在这里插入图片描述

所以在上面的请求中,报错了,415异常

在这里插入图片描述

Spring后台的信息:

Using 'application/json', given [application/json, text/plain, \*/\*] and supported [application/json, application/\*+json, application/json, application/\*+json]

在这里插入图片描述

Using ‘application/json’, given [application/json, text/plain, /] and supported [application/json, application/+json, application/json, application/+json]

在这里插入图片描述

这个错误通常出现在尝试使用 “application/json” 作为响应类型的API端点上。它是一个比较普遍的错误,通常是由于客户端在发送请求时没有正确设置请求头导致的。

这个错误信息的含义是,虽然该API端点支持 “application/json” 响应类型,但客户端发出的请求头中可能没有包含正确的 “Accept” 值。“Accept” 值指定了客户端能够接受的 MIME 类型。在这个例子中,客户端似乎已经将请求头中的 “Accept” 设置为 “text/plain” 或 “/”,但是服务器只支持 “application/json” 响应类型,因此会出现这个错误。

要解决这个问题,您需要确保客户端请求头中的 “Accept” 值设置为 “application/json”,或者可以同时支持多种响应类型。如果您正在使用 JavaScript 中的 XMLHttpRequest 或 Fetch API,则可以使用以下代码来设置请求头:

// 对于 XMLHttpRequest
xhr.setRequestHeader("Accept", "application/json");

// 对于 Fetch API
fetch(url, {
  headers: {
    "Accept": "application/json"
  }
});


这样设置请求头之后,应该就能够成功地获得 “application/json” 响应类型了。

上述问题解决方案

在这里插入图片描述

这种方式会报异常!!!

    /\*\*
 \* 查询所有空闲的房子,显示到左边的框里面 TODO:后面再全查询的基础上进行
 \*/
    List<House> queryAllNoIntoHouse(
            @Param("buildingIdList") List<Integer> buildingIdList, // 楼栋
            @Param("storey") Integer storey, // 楼层
            @Param("areaMin") Double areaMin, // 面积
            @Param("areaMax") Double areaMax, // 面积
            @Param("areaOrderASC") Boolean areaOrderASC,
            @Param("areaOrderDESC") Boolean areaOrderDESC,// 排序
            @Param("status") Boolean... status // 如果为false,则可以查询到非空闲房子,其他情况 都是查询空闲房子

    );

SQL语句 <where,choose,when,otherwise,foreach,if>

    <select id="queryAllNoIntoHouse" resultType="house">
        SELECT
        c_house.id,
        c_owner_house.ownerId,
        c_building.num,c_building.floors,c_building.unit,
        c_house.storey,c_house.roomNum,c_house.area,c_house.into_date,c_house.status,c_house.building_id,
        user_owner.realname AS ownerName

        FROM c_house
        LEFT JOIN c_building ON c_building.id = c_house.building_id
        LEFT JOIN c_owner_house ON c_owner_house.houseId = c_house.id
        LEFT JOIN user_owner ON user_owner.id = c_owner_house.ownerId

        <where>
            <choose>
                <when test="buildingIdList!=null and buildingIdList.size()>0">
                    building_id IN
                    <foreach collection="buildingIdList" open="(" separator="," close=")" item="id">
                        #{id}
                    </foreach>
                </when>
                <otherwise>
<!-- 默认全查-->
                </otherwise>
            </choose>

            <if test="storey!=null">
                AND c_house.storey=#{storey}
            </if>
            <if test="areaMin!=null">
                AND c_house.area &gt;= #{areaMin}
            </if>
            <if test="areaMax!=null">
                AND c_house.area &lt;= #{areaMax}
            </if>
            <choose>
                <when test="status!=null and status.length>0 and !status[0]">
                    <!-- 如果为false,则可以查询到非空闲房子-->
                </when>
                <otherwise>
                    AND !status
                </otherwise>
            </choose>
        </where>
        <if test="areaOrderASC">
            ORDER BY c_house.area
        </if>
        <if test="areaOrderDESC">
            ORDER BY c_house.area DESC
        </if>
    </select>

前后端交互controller层,用专门前后端交互的实体类接收参数

// 2.处理搜索请求
    // 默认显示所有可以选择的房间,放到左侧的框里,如果选择,双击,这条数据跳到右边的框里
    @RequestMapping("/query/house")
    @ResponseBody
    public ResData queryHouse(
// @RequestParam(value = "buildingList", defaultValue = "List[]") List<Building> buildingList, // 楼栋
// Integer storey, // 楼层,没有用到
// Double areaMin,
// Double areaMax,
// @RequestParam(value = "areaOrderASC",defaultValue = "false") Boolean areaOrderASC,
// @RequestParam(value = "areaOrderDESC",defaultValue = "false") Boolean areaOrderDESC
            @RequestBody HouseFront houseFront
            ){
        Double areaMax = houseFront.getAreaMax();
        Double areaMin = houseFront.getAreaMin();
        Boolean areaOrderASC = houseFront.getAreaOrderASC();
        Boolean areaOrderDESC = houseFront.getAreaOrderDESC();
        Integer storey = houseFront.getStorey();
        List<Building> buildingList = houseFront.getBuildingList();
        List<Integer> buildingIds = buildingList.stream().map(Building::getId).collect(Collectors.toList());

        System.out.println("查询条件:"
                +areaMin+"/"
                +areaMax+"/"
                +buildingIds+"/"
                +storey+"/"
        );

        // 大小的问题
        if (!StringUtils.isBlank(areaMin) && !StringUtils.isBlank(areaMax)){
            if (areaMin.compareTo(areaMax)>0){
                return new ResData(1002, "最小面积不能大于最大面积", null);
            }
        }
        // 这个排序顺序不能两个都是true
        if (areaOrderASC && areaOrderDESC){
            return new ResData(1003, "排序条件冲突", null);
        }

        List<House> list = houseService.queryAllNoIntoHouse(buildingIds, storey, areaMin, areaMax, areaOrderASC, areaOrderDESC, true);
        list.forEach(System.out::println);
        return new ResData(200, "ok", list);
    }

前端代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>新增业主</title>
    <link rel="stylesheet" href="/bootstrap/css/bootstrap.min.css">
    <script src="/js/jquery-3.5.1.js"></script>
    <script src="/bootstrap/js/bootstrap.js"></script>
    <script src="/js/axios.min.js"></script>
    <script src="/js/vue.min-v2.5.16.js"></script>
</head>
<body>
<div id="app">
    <br>
    录入业主基础信息:<br>
    用户名:&nbsp;&nbsp; <input type="text" v-model="username">
    真实姓名:<input type="text" v-model="realname">
    电话号码:<input type="text" v-model="tel"><br>

    身份证号:<input type="text" v-model="identity">
    性别:
    <input type="radio" v-model="gender" value="男">男
    <input type="radio" v-model="gender" value="女">女
    <br>
    备注信息:<textarea v-model="notes" rows="3" cols="22"></textarea><br>
    <br>
    录入选房信息:<br>
    <div>
<!--        搜索所有可以选择的房子-->
        楼栋编号:
        <select v-model="buildingId">
            <option value="">--请选择楼栋--</option>
            <option v-for="building in buildingList" :value="building.id">{{building.num}}-{{building.unit}}</option>
        </select>
        <button @click="addBuildingId">添加楼栋</button>
        <button @click="resetSelectBuildsBtn">重选楼栋</button>
        <br>

        选中的楼栋为:
        <select multiple style="width: 100px" @dbclick="removeSelectedBuildingsBtn">
            <option v-for="building in selectedBuildingList" :value="building.id">{{building.num}}-{{building.unit}}</option>
        </select>
        楼层:
        <select v-model="selectFloor">
            <option value="">-选择楼层--</option>
            <option v-for="floors in floorList" :value="floors">{{floors}}层</option>
        </select>
        面积:
        <input type="text" v-model="areaMin" style="width: 50px" placeholder="小">---
        <input type="text" v-model="areaMax" style="width: 50px" placeholder="大">

        <button @click="areaASC">面积升序</button>
        <button @click="areaDESC">面积降序</button>

        <button @click="searchHouseBtn">搜索房子</button>
        <button @click="searchHouseBtnClr">重置搜索</button><br>
    </div>


<!--    TODO:可以选的房子的左侧的框-->
<!--    canSelectHouse-->
    可选的房子为:
    <select multiple style="width: 200px" @dblclick="selectHouseDbc">
        <option v-for="house in canSelectHouse" :value="house.id">
            {{house.num}}--{{house.unit}}--{{house.roomNum}}--{{house.area}}
        </option>
    </select>

    选中的房子为:
    <select  multiple style="width: 200px" @dblclick="removeSelectedHouseDbc">
        <option v-for="house in selectedHouse" :value="house.id">
            {{house.num}}--{{house.unit}}--{{house.roomNum}}--{{house.area}}平米
        </option>
    </select>
    <br>
    <button @click="add">添加</button>
    <button @click="reset">重置</button><br>
    <br>
</div>

<script>
    let app = new Vue({
        el:"#app",
        data:{
            // 首先是用户的基础信息
            username:"",
            realname:"",
            tel:"",
            gender:"男",
            identity:"",
            buildingId:"",
            houseId:"",
            notes:"",

            // 然后是查询的数据
            // 然后是选中的楼栋的id,1栋1单元...
            floorList : Array.from({ length: 12 }, (v, i) => i + 1), // 最大有12层楼,因此这里可以选择1到12
            selectedBuildingList:[], // List<Building> buildingList, // 楼栋
            selectFloor:"", // 楼层
            areaMin:"", // 面积
            areaMax:"", // 面积
            // 和排序相关的
            areaOrderASC:false,
            areaOrderDESC:false,

            // 在左侧边框里面显示可以选择的所有房间信息
            canSelectHouse:[],

            // 在右侧框里面显示已经选择的所有房间信息
            selectedHouse:[],

            buildingList:[]
        },
        methods:{
            searchHouseBtnClr(){
                // 重置搜索
                this.selectedBuildingList =[]
                this.buildingId = ""
                this.selectFloor="" // 楼层
                this.areaMin="" // 面积
                this.areaMax="" // 面积
                    // 和排序相关的
                this.areaOrderASC=false
                this.areaOrderDESC=false
                this.queryHouse();

            },
            // 如果选中了一个楼栋,就添加一个楼栋来,如果有重复的就不添加
            addBuildingId(){
                let selected = this.buildingList.find(b=>b.id===this.buildingId)
                // 这个selected是一个 building对象
                console.log(selected)
                // 只有selected里面有值,并且没有重复的时候才能添加进来
                if (selected && !this.selectedBuildingList.find(b=>b.id===selected.id)){
                    this.selectedBuildingList.push(selected)
                }
            },
            // 如果双击选中的楼栋,则删除已经选中的楼栋
            removeSelectedBuildingsBtn(event){
                const optionValue = event.target.value; // 获取双击的对象的值
                this.selectedBuildingList = this.selectedBuildingList.filter(building=>building.id != optionValue)
            },

            // 在可选的房子的框里面双击,则在选中的房子的框里面加这个房子,并且在可选的房子的框里面删除被选的房子
            selectHouseDbc(event){
                const optionValue = event.target.value; // 获取双击的对象的值
                // TODO:注意两点,这个过滤后的还是一个集合,需要获取第一个元素,另外要用== 不要用===
                const house = this.canSelectHouse.filter(house=>house.id == optionValue)[0]
                console.log(house)
                this.selectedHouse.push(house)
                this.canSelectHouse = this.canSelectHouse.filter(house=>house.id != optionValue)
                console.log(this.canSelectHouse)
                console.log(this.selectedHouse)
            },

            removeSelectedHouseDbc(event){
                const optionValue = event.target.value; // 获取双击的对象house
                console.log(optionValue)
                const house = this.selectedHouse.filter(house=>house.id == optionValue)[0]
                this.selectedHouse = this.selectedHouse.filter(house=>house.id !=optionValue)
                this.canSelectHouse.push(house)
            },

            //如果选中了一个房子,就添加一个进来,如果有重复的就不添加
            addHouseId(){
                const selectedOption = this.allhouseList.find(house=>house.id===this.houseId);

                if (selectedOption && !this.houseList.find(house => house.id === selectedOption.id)) {
                    this.houseList.push(selectedOption);
                }
            },

            removeSelectedOption(event) {
                const optionValue = event.target.value;//获取双击的对象的值
                console.log(optionValue);
                this.houseList = this.houseList.filter(house => house.id != optionValue);
            },

            add(){
                let param = {};
                param.username = this.username;
                param.realname = this.realname;
                param.tel = this.tel;
                param.gender = this.gender;
                param.identity = this.identity;
                param.notes = this.notes;
                param.houseList = this.selectedHouse;

                axios.post("/owner/add",param)
                    .then(response=>{
                        if(response.data.code==200)


![img](https://img-blog.csdnimg.cn/img_convert/46f34b34a5d091288db3bd466f3ad8c9.png)
![img](https://img-blog.csdnimg.cn/img_convert/72c3f09356014ddb34ab26a66e7e80d0.png)
![img](https://img-blog.csdnimg.cn/img_convert/64505794b073f3639827b2c0ca9df466.png)

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上软件测试知识点,真正体系化!**

**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新**

**[需要这份系统化的资料的朋友,可以戳这里获取](https://bbs.csdn.net/forums/4f45ff00ff254613a03fab5e56a57acb)**

identity;
                param.notes = this.notes;
                param.houseList = this.selectedHouse;

                axios.post("/owner/add",param)
                    .then(response=>{
                        if(response.data.code==200)


[外链图片转存中...(img-eqk7cMVH-1715554841253)]
[外链图片转存中...(img-ysaCZ2P3-1715554841253)]
[外链图片转存中...(img-cHXzc6xI-1715554841253)]

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上软件测试知识点,真正体系化!**

**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新**

**[需要这份系统化的资料的朋友,可以戳这里获取](https://bbs.csdn.net/forums/4f45ff00ff254613a03fab5e56a57acb)**

  • 30
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值