web全栈:java微服务vue列表查询分页组件开发CMS2

Java
427
0
0
2023-05-25

1.前端集成axios,npm安装,前后端交互

 asus@LAPTOP-CQRDCFKL MINGW64 /d/DEV_CODE/Intelligy_idead_code/spring/springcloud/yameng-cevent-source-cloudcenter/cevent-source-cloudcenter/cevent-ymcms-admin (master)
$ npm install axios --save-dev  #安装生产/开发插件及依赖= -D
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@2.3.2 (node_modulesfsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@2.3.2: wanted {"os":"darwin","arch":"any"} (current: {"os":"win32","arch":"x64"})
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@1.2.13 (node_moduleswatchpack-chokidar2node_modulesfsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.2.13: wanted {"os":"darwin","arch":"any"} (current: {"os":"win32","arch":"x64"})
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@1.2.13 (node_moduleswebpack-dev-servernode_modulesfsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.2.13: wanted {"os":"darwin","arch":"any"} (current: {"os":"win32","arch":"x64"})
+ axios@0.21.1
added 1 package from 1 contributor in 10.191s

63 packages are looking for funding
  run `npm fund` for details  


web全栈:java微服务vue列表查询分页组件开发CMS2 axios

2.axios调用后端接口后,浏览器 cors (cross origin resource sharing跨原始站点资源共享=跨域问题


web全栈:java微服务vue列表查询分页组件开发CMS2 postman测试后端接口


请求CORS跨域

3.后端解决跨域:server-common公共跨域配置config

 package cevent.source.cloudcenter.server.config;/**
 * Created by Cevent on 2021/3/14.
 */
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 * @author cevent
 * @description 跨域问题CORS-cross origin resource sharing跨原始站点资源共享问题,即跨域问题
 * @date 2021/3/14 17:24
 */@Configuration
public class CorsConfig implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        //请求路径限制
        registry.addMapping("/**")
                .allowedOriginPatterns("*")
                .allowedHeaders(CorsConfiguration.ALL)
                .allowedMethods(CorsConfiguration.ALL)
                .allowCredentials(true)
                .maxAge(3600);//1小时无需再次检测(发送OPTIONS请求)
    }
}  

异常apache异常: annot contain the special value “*”

org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.IllegalArgumentException: When allowCredentials is true, allowedOrigins cannot contain the special value “*” since that cannot be set on the “Access-Control-Allow-Origin” response header. To allow credentials to a set of origins, list them explicitly or consider using “allowedOriginPatterns” instead.

org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1014)


web全栈:java微服务vue列表查询分页组件开发CMS2 springboot版本问题,需更新originPatterns


web全栈:java微服务vue列表查询分页组件开发CMS2 浏览器跨域CORS解决

4.前端module遍历后端响应list


web全栈:java微服务vue列表查询分页组件开发CMS2 module遍历后端传入数据解构


实现列表查询效果图

5.gateway路由跨域CORS配置SpringApplication

 package cevent.source.cloudcenter.gateway;/**
 * Created by Cevent on 2021/2/19.
 */
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.context.annotation.Bean;
import org.springframework.core.env.Environment;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.reactive.CorsWebFilter;
import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource;
import org.springframework.web.util.pattern.PathPatternParser;

/**
 * @author cevent
 * @description
 * @date 2021/2/19 15:54
 */@SpringBootApplication
@EnableEurekaClient
public class GatewayApplication {
    private static final Logger LOG= LoggerFactory.getLogger(GatewayApplication.class);

    public static void main(String[] args) {
        SpringApplication application=new SpringApplication(GatewayApplication.class);
        Environment environment=application.run(args).getEnvironment();
        LOG.info("路由模块gateway启动");
        LOG.info("gateway地址:t {}",environment.getProperty("server.port"));
    }

    /**
     * CORS-cross origin resource sharing跨域配置
     */    @Bean
    public CorsWebFilter corsWebFilter(){
        CorsConfiguration corsConfiguration=new CorsConfiguration();
        corsConfiguration.setAllowCredentials(Boolean.TRUE);
        corsConfiguration.addAllowedMethod("*");
        corsConfiguration.addAllowedHeader("*");
        //注意springboot新版本取消了addAllowedOrigin,要使用addAllowedOriginPattern
        corsConfiguration.addAllowedOriginPattern("*");
        corsConfiguration.setMaxAge(3600L);
        UrlBasedCorsConfigurationSource corsConfigurationSource=new UrlBasedCorsConfigurationSource(new PathPatternParser());
        corsConfigurationSource.registerCorsConfiguration("/**",corsConfiguration);
        //返回对象CorsWebFilter
        return new CorsWebFilter(corsConfigurationSource);
    }
}  

6.common中注释springboot单应用cors跨域配置


web全栈:java微服务vue列表查询分页组件开发CMS2 CORS-springboot单应用注销


web全栈:java微服务vue列表查询分页组件开发CMS2 注解CORS

axios请求:this.$axios.get(‘ ‘).then((resp)=>{ resp.data })


web全栈:java微服务vue列表查询分页组件开发CMS2 axios请求成功

7.扩展:集成mybatis分页插件pageHelper



  • 主pom引入github.pageHelper
 <!--集成mybatis-pageHelper分页插件-->
<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper-spring-boot-starter</artifactId>
    <version>1.2.10</version>
</dependency>  
  • server-common继承


web全栈:java微服务vue列表查询分页组件开发CMS2 引入主pom

  • server-common的 modules ervice增加page分页方法


web全栈:java微服务vue列表查询分页组件开发CMS2 ForEach与for方法对比


forEach->module

 //3.分页查询:pageHelper测试
public List<ModuleDto>  moduleDtoListPage(){

    PageHelper.startPage(1,5);
    ModuleExample moduleExample=new ModuleExample();
    moduleExample.setOrderByClause("uni_id desc");
    List<Module> moduleList=moduleMapper.selectByExample(moduleExample);
    List<ModuleDto> moduleDtoList=new ArrayList<>();
    //forEach方法
    moduleList.stream().forEach(module->{
        ModuleDto moduleDto=new ModuleDto();
        BeanUtils.copyProperties(module,moduleDto);
        moduleDtoList.add(moduleDto);
    });

    return moduleDtoList;
}  
  • business的controller新增分页请求
 //3.分页请求
@RequestMapping("/dtoListPage")
public List<ModuleDto> getDtoPage(){
    return moduleService.moduleDtoListPage();
}  
  • postman测试


web全栈:java微服务vue列表查询分页组件开发CMS2 分页测试


web全栈:java微服务vue列表查询分页组件开发CMS2 日志输出


web全栈:java微服务vue列表查询分页组件开发CMS2 分页方法前端测试

  • server-common分页dto配置


controller-pageDto

  • server-common分页service生成前端传参,后端pageInfo处理存入pageDto=》list数组对象
 /*4.分页查询:pageDto保存数据
    list数据集合:listPageData
    当前页码:currentPage
    每页行数:size
    总计函数:totalSize
    前端可返回pageDto,无需返回值
 */public void getModulePageDtoList(PageDto pageDto){
    //1.分页设置(前端传入当前页和每页行数params),起始页,每页行数size
    PageHelper.startPage(pageDto.getCurrentPage(),pageDto.getSize());

    ModuleExample moduleExample=new ModuleExample();
    moduleExample.setOrderByClause("id asc");
    List<Module> moduleList=moduleMapper.selectByExample(moduleExample);
    //2.将mapper查询结果复制到pageInfo
    PageInfo<Module> pageInfo=new PageInfo<>(moduleList);
    //3.pageInfo计算处理处理=>后分页的总行数set到pageDto做记录
    pageDto.setTotalSize(pageInfo.getTotal());

    List<ModuleDto> moduleDtoList=new ArrayList<>();
    moduleList.stream().forEach(module->{
        ModuleDto moduleDto=new ModuleDto();
        BeanUtils.copyProperties(module,moduleDto);
        moduleDtoList.add(moduleDto);
    });
    //4.将dtoList放入pageDto的listPageData
    pageDto.setListPageData(moduleDtoList);

}  
  • server-common分页-business-controller实现
 //3.分页请求(原生pageHelper传参)
@RequestMapping("/dtoListPage")
public List<ModuleDto> getDtoPage(){
    return moduleService.moduleDtoListPage();
}

//4.前端分页设置,后端pageInfo处理(前后端分页交互)
@RequestMapping("/pageList")
public PageDto list(PageDto pageDto){
    moduleService.getModulePageDtoList(pageDto);
    return pageDto;
}  
  • postman请求测试

http:{{source-cloudcenter}} /business/admin/module/pageList?currentPage=1&size=3


web全栈:java微服务vue列表查询分页组件开发CMS2 分页测试

结果pageList输出:http:


web全栈:java微服务vue列表查询分页组件开发CMS2 浏览器响应结果

8.前端module –》post请求

axios默认以流的方式传递给后端数据。Data{param:value}的方法,后端(接收的是表单)无法接收


web全栈:java微服务vue列表查询分页组件开发CMS2 axios流方式传输参数


web全栈:java微服务vue列表查询分页组件开发CMS2 request payload传参

9.前端分页组件:post传参:两种提交数据方式-前后端结构-流


流传参结构

 <template>
    <div class="pageNav" aria-label="分页">

        <div class="pageChoose">
            <el-button type="primary" plain :disabled="page===1" @click="selectPage(1)">首页</el-button>
            <el-button type="primary" icon="el-icon-caret-left" circle
                       :disabled="page===1" @click="selectPage(page-1)"></el-button>
            <el-button type="primary" plain v-for="p in pages" :key="p" @click="selectPage(p+1)">{{p+1}}
            </el-button>
            <el-button type="primary" icon="el-icon-caret-right" circle
                       :disabled="page===pageTotal" @click="selectPage(page+1)"></el-button>
            <el-button type="primary" plain :disabled="page===pageTotal" @click="selectPage(pageTotal)">尾页</el-button>
        </div>

        <div class="pageSize">
            <el-cascader class="sizeNum" placeholder="每页显示5行" :options="options" :show-all-levels="false"
                         filterable v-model="size" @change="handleChange"></el-cascader>
            <el-button type="primary" plain>共{{totalSize}}条</el-button>
        </div>

        <div class="goPage">
            <span>前往</span>
            <el-input class="goPageNum" v-model="input" placeholder="1" @change="inputValue"></el-input>
            <el-button v-model="input" id="goBtn" type="primary" plain @click="selectPage(input)">GO</el-button>
        </div>

    </div>
</template>

<script>
    export default {
        name: "PageHelper",
        //父组件传递的参数list函数
        props: {
            list: {
                type: Function,
                default: null
            },
            //显示的页码数,共50页,显示5页,其他用...表示
            itemCount: Number,
        },
        data() {
            return {
                message: '欢迎使用cevent分页',
                /*变量名与PageDto一致,和父组件传入的参数一直,否则造成NaN等解析异常
                    当前页码:currentPage -->父组件page
                    每页条数:size
                    总条数(pageInfo处理的total属性为long):totalSize
                    查询记录放入list:listPageData
                    自定义总页码:pageTotal
                    自定义分页数组:pages
                 */                page: 0,
                size: 5,
                totalSize: 0,
                pageTotal: 0,
                pages: [],
                options: [{
                    value: 5,
                    label: '每页显示5行',
                }, {
                    value: 10,
                    label: '每页显示10行',
                }, {
                    value: 20,
                    label: '每页显示20行',
                }, {
                    value: 50,
                    label: '每页显示50行',
                }, {
                    value: 100,
                    label: '每页显示100行',
                }],
                input: null,
            }
        }
        ,
        mounted() {
            console.log(this.message);
        }
        ,
        methods: {
            handleChange(value) {
                console.log("改变的opts:",value[0]);
                this.size=value[0];
            },
            inputValue() {
                let goBtn=document.getElementById("goBtn");
                console.log("输入的内容:", this.input);
            },
            /**
             * 渲染分页组件
             */            render(page, totalSize) {
                this.page = page; //当前页
                this.totalSize = totalSize; //总条数 / 每页显示条数size
                this.pageTotal = Math.ceil(totalSize / this.size);
                //默认分页后显示的页码数:10
                this.pages = this.getPageItems(this.pageTotal, page, this.itemCount || 10);
            },
            //查询每一页
            selectPage(page) {
                let _this = this;
                if (page < 1) {
                    page = 1;
                }
                //如果传入的当前页>总页码
                if (page > _this.pageTotal) {
                    page = _this.pageTotal;
                }
                if (this.page !== page) {
                    _this.page = page;
                    if (_this.list) {
                        _this.list(page);
                    }
                }
            },
            //当前显示的页码
            getPageItems(totalSize, current, length) {
                let items = [];
                if (length >= totalSize) {
                    for (let i = 0; i < totalSize; i++) {
                        //总条数放入items,遍历页码
                        items.push(i);
                    }
                } else {
                    let base = 0;
                    //前移:向下取整
                    if (current - 0 > Math.floor((length - 1) / 2)) {
                        //后移:向上取整
                        base = Math.min(totalSize, current - 0 + Math.ceil((length - 1) / 2)) - length;
                    }
                    //条数集合
                    for (let i = 1; i <= length; i++) {
                        items.push(base + i);
                    }
                }
                return items;
            },
            //3.添加class
            addClass(node, className) {
                let reg = new RegExp("b" + className + "b");
                if (!reg.test(node.className)) {
                    node.className += (" " + className);
                }
            },

            //4.移除class
            removeClass(node, className) {
                if (node.className) {
                    let reg = new RegExp("b" + className + "b");
                    let classes = node.className;
                    node.className = classes.replace(reg, "");
                    if (/^s*$/g.test(node.className)) {
                        node.removeAttribute("class");
                    }
                } else {
                    node.removeAttribute("class");
                }
            }
        }
    }
</script>

<style scoped>
    .pageNav {

    }

    .pageChoose {
        float: left;
        margin-top: 5px;
    }

    .pageSize {
        float: left;
        margin-top: 5px;
    }

    .sizeNum {
        margin: 0 5px;
    }

    .goPage {
        margin: 5px 0 5px 5px;
        float: left;
    }

    .goPageNum {
        width: 40px;
        margin: 0 5px;

    }

    /*跳转页*/</style>  

10.前端module调用分页pageHelper


调用分页解析

 <template>
    <div class="moduleTable">
        <div class="">
            <el-divider class="topLine"><i class="lineIcon el-icon-document-copy"></i><span
                    class="lineTitle">模块列表</span></el-divider>
        </div>

        <div class="batchOPT">
            <el-button class="batchBTN" @click="toggleSelection([modules[1],modules[2]])">批量删除</el-button>
        </div>
        <!--:data绑定data中预设的参数
        单行显示:show-overflow-tooltip="true"
        如果为tr,则需要v-for="(module,index) of modules" :key="index"
        -->
        <el-table
                ref="multipleTable"
                tooltip-effect="dark"
                @selection-change="handleSelectionChange"
                :data="modules"
                :show-overflow-tooltip="true"
                border
                style="width: 100%"
                class="previous-row"
                :header-cell-style="{backgroundImage:'linear-gradient(#ff6e02,#ff6d00)',color:'#ffffff',}"
        >
            <el-table-column type="selection" width="35">
            </el-table-column>
            <el-table-column
                    sortable
                    fixed
                    prop="uniId"
                    label="ID"
                    width="60">
            </el-table-column>
            <el-table-column
                    sortable
                    fixed
                    prop="name"
                    label="模块名称"
                    width="110">
            </el-table-column>
            <el-table-column
                    sortable
                    :show-overflow-tooltip="true"
                    prop="seoTitle"
                    label="SEO标题"
                    width="110">
            </el-table-column>
            <el-table-column
                    sortable
                    :show-overflow-tooltip="true"
                    prop="seoKeyword"
                    label="SEO关键字"
                    width="120">
            </el-table-column>
            <el-table-column
                    sortable
                    :show-overflow-tooltip="true"
                    prop="seoDescription"
                    label="SEO描述"
                    width="110">
            </el-table-column>
            <el-table-column
                    sortable
                    prop="parentId"
                    label="父ID"
                    width="75">
            </el-table-column>
            <el-table-column
                    sortable
                    prop="typeId"
                    label="模块类型"
                    width="110">
            </el-table-column>
            <el-table-column
                    sortable
                    prop="modulePath"
                    label="模块路径"
                    width="110">
            </el-table-column>
            <el-table-column
                    sortable
                    prop="sort"
                    label="排序"
                    width="75">
            </el-table-column>
            <el-table-column
                    sortable
                    prop="iCreateTime"
                    label="创建时间"
                    width="120">
            </el-table-column>
            <el-table-column
                    sortable
                    prop="iUpdateTime"
                    label="更新时间"
                    width="120">
            </el-table-column>
            <el-table-column
                    fixed="right"
                    label="操作"
                    width="200">
                <template slot-scope="scope">
                    <el-button @click="handleClick(scope.row)" type="text" size="small">查看</el-button>
                    <el-button type="text" size="small">编辑</el-button>
                    <el-button type="text" size="small">删除</el-button>
                    <el-button type="text" size="small">排序</el-button>
                </template>
            </el-table-column>
        </el-table>

        <div class="pageHelper">
            <el-button class="flushBTN" type="primary" @click="pageList(1)">刷新数据</el-button>
            <!--子组件内部的方法list通过$emit发射给父组件:list="父组件定义的方法"-->
            <page-helper ref="pageHelper" :list="pageList"></page-helper>

        </div>
    </div>
</template>

<script>
    import PageHelper from "../../components/PageHelper";
    export default {
        name: "ModuleSet",
        //引用组件
        components:{PageHelper},
        data() {
            return {
                message: '这里是大模块内容页',
                modules:[]
            }
        },
        mounted() {
            console.log(this.message);
            //调用admin父组件,激活父组件样式
            //this.$parent.activeBar("business-module-set");
            //1.普通列表查询
            this.list();
            //2.分页列表查询,默认初始化执行第一页
            this.pageList(1);
        },
        methods: {
            handleClick(row) {
                console.log(row);
            },
            //多选的方法
            toggleSelection(rows) {
                if (rows) {
                    rows.forEach(row => {
                        this.$refs.multipleTable.toggleRowSelection(row);
                    });
                } else {
                    this.$refs.multipleTable.clearSelection();
                }
            },
            handleSelectionChange(val) {
                this.multipleSelection = val;
            },
            //list查询
            list() {
                this.$axios.get('#39;)
                    .then((responseData) => {
                    console.log("模块列表:",responseData);
                    //将后端返回的data绑定如return预设的参数中
                    //this.modules=responseData.data;
                    console.log("这里的modules:",this.modules);
                    })
            },
            //查询当前页,需要设置变量传入pageHelper分页插件
            pageList(page){
                //post传递参数一:表单方式formData
                //post传递参数二:流方式,axios默认以流的方式传递给后端数据
                // 前端发送流:data {param:value,param:value}
                // 后端接收流:(@RequestBody 分页Dto)
                this.$axios.post('#39;,{
                    currentPage:page, //向后端发送参数。当前页
                    size:this.$refs.pageHelper.size, //引用传入组件后,在标签中refs定义的别名
                }).then((responseData)=>{
                    console.log("分页传参:",responseData.data);
                    /*将分页参数传入module
                    当前页码:currentPage
                    每页条数:size
                    总条数(pageInfo处理的total属性为long):totalSize
                    查询记录放入list:listPageData
                    */                    this.modules=responseData.data.listPageData;
                    //分页渲染,将当前页和总条数传入==》分页组件==》后端

                    this.$refs.pageHelper.render(page,responseData.data.totalSize);
                })
            }
        }
    }
</script>

<style scoped>
    /*顶部line样式*/    .topLine {
        background-color: #2a92ee;
    }

    .lineIcon {
        font-size: 24px;
        color: #2a92ee;
        position: relative;
    }

    .lineTitle {
        position: relative;
        font-size: 22px;
        color: #2a92ee;
    }

    /*table样式*/    .previous-row {
        background: #f0f9eb;
        margin-left: 2%;
        max-width: 96%;
    }

    /*批量操作*/    .batchOPT {
        float: left;

        margin-left: 2%;
        margin-bottom: 1%;
        z-index: 1;
    }

    .batchBTN {
        background-color: #ff5202;
        color: white;
        box-shadow: 1px 2px 2px #ff6e02;
    }

    .batchBTN:hover {
        background-color: #ff3d02;
        color: white;
    }

    .batchBTN:focus {
        background-color: #ff3d02;
        color: #ffffff;
    }

    /**分页位置/
     */    .pageHelper{
        margin-left: 60px;
    }
    .flushBTN{
        position: relative;
        float: left;
        max-width: 95px;
        margin-right: 20px;
        margin-top: 5px;
    }
</style>  

11.postman测试

请求:{{source-cloudcenter}} /business/admin/module/pageList

参数:

{

“currentPage” :1,

“size” :3

}


web全栈:java微服务vue列表查询分页组件开发CMS2 postman中json传参


web全栈:java微服务vue列表查询分页组件开发CMS2 content-type


web全栈:java微服务vue列表查询分页组件开发CMS2 body传参

12.实现列表查询,分页功能效果图


web全栈:java微服务vue列表查询分页组件开发CMS2 pad端


web全栈:java微服务vue列表查询分页组件开发CMS2 pc端

13.提交gitee

Gitee地址:

12.module表(sql添加数据),gateway添加CORS跨域配置,新增pageDto分页属性,ModuleController添加分页查询功能。前端生成pageHelper分页插件,module模块引用插件实现分页完整功能


web全栈:java微服务vue列表查询分页组件开发CMS2 gitee


仓库