java微服务vue列表查询分页组件开发CMS2,java微服务vue列表查询分页组件开发CMS2
java微服务vue列表查询分页组件开发CMS2,java微服务vue列表查询分页组件开发CMS2module遍历后端传入数据解构浏览器跨域CORS解决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 explici
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_modules\fsevents):
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_modules\watchpack-chokidar2\node_modules\fsevents):
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_modules\webpack-dev-server\node_modules\fsevents):
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
axios
2.axios调用后端接口后,浏览器cors(cross origin resource sharing跨原始站点资源共享=跨域问题postman测试后端接口
请求CORS跨域
3.后端解决跨域:server-common公共跨域配置configpackage 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)
springboot版本问题,需更新originPatterns
浏览器跨域CORS解决
4.前端module遍历后端响应listmodule遍历后端传入数据解构
实现列表查询效果图
5.gateway路由跨域CORS配置SpringApplicationpackage 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 http://127.0.0.1:{}" 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跨域配置
CORS-springboot单应用注销
注解CORS
axios请求:this.$axios.get('http://localhost:8899/business/admin/module/dtoList').then((resp)=>{resp.data})
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继承
引入主pom
- server-common的moduleservice增加page分页方法
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测试
分页测试
日志输出
分页方法前端测试
- 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
分页测试
结果pageList输出:http:http://localhost:8899/business/admin/module/pageList?currentPage=1&size=3
浏览器响应结果
8.前端module --》post请求axios默认以流的方式传递给后端数据。Data{param:value}的方法,后端(接收的是表单)无法接收
axios流方式传输参数
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('http://localhost:8899/business/admin/module/dtoList')
.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('http://localhost:8899/business/admin/module/pageList' {
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
}
postman中json传参
content-type
body传参
12.实现列表查询,分页功能效果图pad端
pc端
13.提交giteeGitee地址:https://gitee.com/cevent_OS/yameng-cevent-source-cloudcenter.git
12.module表(sql添加数据),gateway添加CORS跨域配置,新增pageDto分页属性,ModuleController添加分页查询功能。前端生成pageHelper分页插件,module模块引用插件实现分页完整功能
gitee
仓库