zoukankan      html  css  js  c++  java
  • Day03_CMS页面管理开发

    1 自定义条件查询

    1.1 需求分析

    在页面输入查询条件,查询符合条件的页面信息。

    查询条件如下:

    站点Id:精确匹配
    模板Id:精确匹配
    页面别名:模糊匹配
    ······
    

    1.2 服务端

    1.2.1 Dao

    使用CmsPageRepository中的findAll(Example<S> var1, Pageable var2)方法实现,无需定义。
    

    下边测试findAll方法实现自定义条件查询:

    // 自定义条件查询测试
        @Test
        public void testFindAll() {
            //条件匹配器
            ExampleMatcher exampleMatcher = ExampleMatcher.matching().withMatcher("pageAliase", ExampleMatcher.GenericPropertyMatchers.contains());
            //页面别名模糊查询,需要自定义字符串的匹配器实现模糊查询
                //ExampleMatcher.GenericPropertyMatchers.contains() 包含
                //ExampleMatcher.GenericPropertyMatchers.startsWith() //开头匹配
    
            //条件值
            CmsPage cmsPage = new CmsPage();
            //设置站点ID
            cmsPage.setSiteId("5a751fab6abb5044e0d19ea1");
            //模板ID
            cmsPage.setTemplateId("5a962c16b00ffc514038fafd");
            //创建条件实例
            Example<CmsPage> example = Example.of(cmsPage, exampleMatcher);
            Pageable pageable = PageRequest.of(1, 10);
            Page<CmsPage> all = cmsPageRepository.findAll(example, pageable);
            System.out.println(all);
        }
    

    1.2.2 Service

    在PageService的findlist方法中增加自定义条件查询代码

    /**
         * 页面列表分页查询
         * @param page  当前页码
         * @param size  页面显示个数
         * @param queryPageRequest  查询条件
         * @return  页面列表
         */
        public QueryResponseResult findList(int page, int size, QueryPageRequest queryPageRequest) {
            if (queryPageRequest == null) {
                queryPageRequest = new QueryPageRequest();
            }
            //条件匹配器
            //页面名称模糊查询,需要自定义字符串的匹配器实现模糊查询
            ExampleMatcher exampleMatcher = ExampleMatcher.matching().withMatcher("pageAliase", ExampleMatcher.GenericPropertyMatchers.contains());
            //条件值
            CmsPage cmsPage = new CmsPage();
            //站点id
            if(StringUtils.isNotEmpty(queryPageRequest.getSiteId())){
                cmsPage.setSiteId(queryPageRequest.getSiteId());
            }
            //页面别名
            if(StringUtils.isNotEmpty(queryPageRequest.getPageAliase())) {
                cmsPage.setPageAliase(queryPageRequest.getPageAliase());
            }
            //创建条件实例
            Example<CmsPage> example = Example.of(cmsPage, exampleMatcher);
            if (page <= 0) {
                page = 1;
            }
            //页码
            page = page - 1;
            if (size <= 0) {
                size = 20;
            }
            //分页对象
            Pageable pageable = PageRequest.of(page, size);
    
            //分页查询
            Page<CmsPage> all = cmsPageRepository.findAll(example,pageable);
            QueryResult<CmsPage> cmsPageQueryResult = new QueryResult<CmsPage>();
            cmsPageQueryResult.setList(all.getContent());
            cmsPageQueryResult.setTotal(all.getTotalElements());
            return new QueryResponseResult(CommonCode.SUCCESS, cmsPageQueryResult);
        }
    

    1.2.3 Controller

    无需修改

    1.2.4 测试

    使用SwaggerUI测试

    http://localhost:31001/swagger-ui.html

    1.3 前端

    1.3.1 页面

    1、增加查询表单

    <!--    查询表单-->
        <el-from :model="params">
          <el-select v-model="params.siteId" placeholder="请选择">
            <el-option
              v-for="item in siteList"
              :key="item.siteId"
              :label="item.siteName"
              :value="item.siteId">
            </el-option>
          </el-select>
          页面别名:
          <el-input v-model="params.pageAliase" style=" 100px"></el-input>
          <!--    按钮-->
          <el-button type="primary" v-on:click="query" size="small">查询</el-button>
        </el-from>
    

    :model和v-model的区别
    :model是v-bind:model的缩写,这种只是将父组件的数据传递到了子组件,并没有实现子组件和父组件数据的双向绑定。当然引用类型除外,子组件改变引用类型的数据的话,父组件也会改变的。

    2、数据模型对象

    增加siteList、pageAliase、siteId,如下:

    data() {
          return {
            siteList:[], //站点列表
            list: [],
            total: 50,
            params: {
              siteId:'',// 用于填写默认页面列表的siteId
              pageAliase:'',
              page: 1, // 页码
              size: 10 //每页显示个数
            }
          }
        }
    

    3、在钩子方法中 构建siteList站点列表

    mounted() {
          // 默认查询页面
          this.query()
          //初始化站点列表
          this.siteList = [
            {
              siteId:'5a751fab6abb5044e0d19ea1',
              siteName:'门户主站'
            },
            {
              siteId:'102',
              siteName:'测试站'
            }
          ]
        }
    

    1.3.2 Api调用

    1、向服务端传递查询条件,修改 cms.js,如下:

    //public是对axios的工具类封装,定义了http请求方法
    import http from './../../../base/api/public'
    import querystring from 'querystring'
    
    let sysConfig = require('@/../config/sysConfig')
    let apiUrl = sysConfig.xcApiUrlPre;
    
    export const page_list = (page, size, params) => {
      //将json对象转成key/values对
      let query = querystring.stringify(params)
      return http.requestQuickGet(apiUrl+'/cms/page/list/'+page+'/'+size+'/?' + query)
    }
    

    2、page_list.vue页面调用api方法

    query() {
            cmsApi.page_list(this.params.page, this.params.size, this.params).then((res) => {
              console.log(res)
              this.total = res.queryResult.total
              this.list = res.queryResult.list
            })
          }
    

    方法没变化

    测试如下:

    2 新增页面

    2.1 新增页面接口定义

    1、定义响应模型

    @Data
    public class CmsPageResult extends ResponseResult {
        CmsPage cmsPage;
        public CmsPageResult(ResultCode resultCode,CmsPage cmsPage) {
            super(resultCode);
            this.cmsPage = cmsPage;
        }
    }
    

    工程已经写好这个类

    2、定义添加Api

    在api工程中添加接口:

    @ApiOperation("添加页面")
    public CmsPageResult add(CmsPage cmsPage);
    

    2.2 新增页面服务端开发

    2.2.1 页面唯一索引

    cms_page的页面名称、站点Id、页面webpath为唯一索引。

    2.2.2 Dao

    1、添加根据页面名称、站点Id、页面webpath查询页面方法,此方法用于校验页面是否存在

    public interface CmsPageRepository extends MongoRepository<CmsPage, String> {
     		······
        //根据页面名称、站点id、页面访问路径查询
        CmsPage findByPageNameAndSiteIdAndPageWebPath(String pageName,String siteId,String pageWebPath);
    }
    

    2、使用 CmsPageRepository提供的save方法 。

    2.2.3 Service

    /**
         * 添加页面
         */
        public CmsPageResult add(CmsPage cmsPage) {
            //校验页面是否存在,根据页面名称、站点Id、页面webpath查询
            CmsPage cmsPage1 = cmsPageRepository.findByPageNameAndSiteIdAndPageWebPath(cmsPage.getPageName(), cmsPage.getSiteId(), cmsPage.getPageWebPath());
            if(cmsPage1 == null) {
                cmsPage.setPageId(null);//添加页面主键由spring data 自动生成
                cmsPageRepository.save(cmsPage);
                //返回结果
                return  new CmsPageResult(CommonCode.SUCCESS, cmsPage);
            }
            return new CmsPageResult(CommonCode.FAIL, null);
        }
    

    2.2.4 Controller

    //添加页面
        @Override
        @PostMapping("/add")
        public CmsPageResult add(@RequestBody CmsPage cmsPage) {
            return pageService.add(cmsPage);
        }
    

    2.2.5 接口测试

    使用postman测试

    post请求:http://localhost:31001/cms/page/add

    请求内容为json数据,测试数据如下:

    {
    	"dataUrl": "string", 
      "htmlFileId": "string", 
      "pageAliase": "string", 
      "pageCreateTime": "2018‐06‐11T02:01:25.667Z", 
      "pageHtml": "string", 
      "pageName": "测试页面", 
      "pageParameter": "string",
      "pagePhysicalPath": "string",
      "pageStatus": "string", 
      "pageTemplate": "string",
      "pageType": "string", 
      "siteId": "string",
      "templateId": "string"
    }
    

    成功响应结果:

    2.3 新增页面前端开发

    2.3.1 新增页面

    2.3.1.1 编写page_add.vue页面

    使用Element-UI的form组件编写添加表单内容,页面效果如下:

    1、创建page_add.vue页面

    2、配置路由

    在cms模块的路由文件中配置“添加页面”的路由:

    import page_add from '@/module/cms/page/page_add.vue';
    ······
    {path:'/cms/page/add',name:'新增页面',component: page_add,hidden:true}
    

    注意:由于“添加页面”不需要显示为一个菜单,这里hidden设置为true隐藏菜单。

    3、在页面列表添加“添加页面”的按钮

    实际情况是用户进入页面查询列表,点击“新增页面”按钮进入新增页面窗口。

    在查询按钮的旁边添加:

    <!--      新增功能按钮-->
    <router-link class="mui-tab-item" :to="{path:'/cms/page/add'}">
    	<el-button type="primary" size="small">新增页面</el-button>
    </router-link>
    

    说明:router-link是vue提供的路由功能,用于在页面生成路由链接,最终在html渲染后就是标签

    to:目标路由地址

    4、完善页面内容:

    在资料中导入page_add.vue界面即可。

    template代码如下:

    <template>
      <div>
        <el-form   :model="pageForm" label-width="80px" :rules="pageFormRules" ref="pageForm" >
          <el-form-item label="所属站点" prop="siteId">
            <el-select v-model="pageForm.siteId" placeholder="请选择站点">
              <el-option
                v-for="item in siteList"
                :key="item.siteId"
                :label="item.siteName"
                :value="item.siteId">
              </el-option>
            </el-select>
          </el-form-item>
          <el-form-item label="选择模版" prop="templateId">
            <el-select v-model="pageForm.templateId" placeholder="请选择">
              <el-option
                v-for="item in templateList"
                :key="item.templateId"
                :label="item.templateName"
                :value="item.templateId">
              </el-option>
            </el-select>
          </el-form-item>
          <el-form-item label="页面名称" prop="pageName">
            <el-input v-model="pageForm.pageName" auto-complete="off" ></el-input>
          </el-form-item>
    
          <el-form-item label="别名" prop="pageAliase">
            <el-input v-model="pageForm.pageAliase" auto-complete="off" ></el-input>
          </el-form-item>
          <el-form-item label="访问路径" prop="pageWebPath">
            <el-input v-model="pageForm.pageWebPath" auto-complete="off" ></el-input>
          </el-form-item>
    
          <el-form-item label="物理路径" prop="pagePhysicalPath">
            <el-input v-model="pageForm.pagePhysicalPath" auto-complete="off" ></el-input>
          </el-form-item>
          <el-form-item label="数据Url" prop="dataUrl">
            <el-input v-model="pageForm.dataUrl" auto-complete="off" ></el-input>
          </el-form-item>
    
          <el-form-item label="类型">
            <el-radio-group v-model="pageForm.pageType">
              <el-radio class="radio" label="0">静态</el-radio>
              <el-radio class="radio" label="1">动态</el-radio>
            </el-radio-group>
          </el-form-item>
          <el-form-item label="创建时间">
            <el-date-picker type="datetime" placeholder="创建时间" v-model="pageForm.pageCreateTime"></el-date-picker>
          </el-form-item>
    
        </el-form>
        <div slot="footer" class="dialog-footer">
          <el-button @click="go_back">返回</el-button>
          <el-button type="primary" @click.native="addSubmit" :loading="addLoading">提交</el-button>
        </div>
      </div>
    </template>
    

    此时需要再cms.js下参考page_list定义一个空的page_add,否则报错

    Form Attributes说明:

    model 表单数据对象
    rules 表单验证规则
    

    Form-Item Attributes 说明:

    prop 表单域
    model 字段,,在使用 validate、resetFields 方法的情况下,该属性是必填的
    label 标签文本
    

    详情属性及事件参考http://element.eleme.io/#/zh-CN/component/form

    5、数据对象

    <script>
      /*编写页面静态部分,即model及vm部分。*/
      import * as cmsApi from '../api/cms'
      export default {
        data() {
          return {
            //站点列表
            siteList:[],
            //末班列表
            templateList:[],
            //新增界面数据
            pageForm:{
              siteId:'',
              templateId:'',
              pageName: '',
              pageAliase: '',
              pageWebPath: '',
              pageParameter:'',
              pagePhysicalPath:'',
              pageType:'',
              pageCreateTime: new Date()
            }
          }
        },
        methods:{
          addSubmit:function(){
            alert("提交");
          }
        }
      }
    </script>
    <style>
      /*编写页面样式,不是必须*/
    </style>
    

    6、站点及模板数据(先使用静态数据)

    在created钩子方法中定义,created是在html渲染之前执行,这里推荐使用created。

    created() {
          //初始化站点列表
          this.siteList = [
            {
              siteId: '5a751fab6abb5044e0d19ea1',
              siteName: '门户主战'
            },
            {
              siteId:'102',
              siteName:'测试站'
            }
          ]
          //模板列表
          this.templateList = [
            {
              templateId:'5a962b52b00ffc514038faf7',
              templateName:'首页'
            },
            {
              templateId:'5a962bf8b00ffc514038fafa',
              templateName:'轮播图'
            }
          ]
        }
    

    7、测试预览

    新增页面按钮:

    新增页面表单:

    2.3.1.2 添加返回

    进入新增页面后只能通过菜单再次进入页面列表,可以在新增页面添加“返回”按钮,点击返回按钮返回到页面列 表。

    1. 新增页面按钮带上参数
    <router-link :to="{path:'/cms/page/add',query:{
            page:this.params.page,
            siteId:this.params.siteId
          }}">
            <el-button type="primary" size="small">新增页面</el-button>
    </router-link>
    

    说明:query表示在路由url上带上参数

    2)定义返回方法

    在page_add.vue上定义返回按钮

    <el-button type="primary" @click="go_back">返回</el-button>
    

    在page_add.vue上定义返回方法

    go_back(){
            this.$router.push({
              path: '/cms/page/page_list', query: {
                page: this.$router.query.page,
                siteId: this.$router.query.siteId
              }
            })
    }
    

    说明:this.$route.query 表示取出路由上的参数列表,有两个取路由参数的方法:

    a、通过在路由上添加key/value串使用this.$route.query来取参数,例如:/router1?id=123 ,/router1?id=456 可以通过this.$route.query.id获取参数id的值。
    
    b、通过将参数作为路由一部分进行传参数使用this.$route.params来获取,例如:定义的路由为/router1/:id ,请 求/router1/123时可以通过this.$route.params.id来获取,此种情况用this.$route.query.id是拿不到的。
    

    3)查询列表支持回显

    进入查询列表,从url中获取页码和站点id并赋值给数据模型对象,从而实现页面回显。

    url例子:http://localhost:12000/#/cms/page/list?page=2&siteId=5a751fab6abb5044e0d19ea1

     created() {
          //从路由上获取参数
          this.params.page = Number.parseInt(this.$route.query.page || 1);
          this.params.siteId = this.$route.query.siteId || '';
    			······
    }
    

    小技巧:使用 ||返回第一个有效值

    2.3.1.3 表单校验

    1、配置校验规则:

    Element-UI的Form组件提供表单校验的方法:

    在form属性上配置rules(表单验证规则)

    <el-form :model="pageForm" label-width="80px" :rules="pageFormRules" ref="pageForm">
    

    在数据模型中配置校验规则:

    pageFormRules: {
    	siteId: [{required: true, message: '请选择站点', trigger: 'blur'}],
    	templateId: [{required: true, message: '请选择模版', trigger: 'blur'}],
    	pageName: [{required: true, message: '请输入页面名称', trigger: 'blur'} ],
    	pageWebPath: [{required: true, message: '请输入访问路径', trigger: 'blur'}],
    	pagePhysicalPath: [{required: true, message: '请输入物理路径', trigger: 'blur'}]
    }
    

    更多的校验规则参考http://element.eleme.io/#/zh-CN/component/form中“表单验证”的例子。

    2、点击提交按钮触发校验

    1)在form表单上添加 ref属性(ref="pageForm")在校验时引用此表单对象

    <el‐form :model="pageForm" :rules="pageFormRules" label‐width="80px" ref="pageForm">
    

    2)在addSubmit中添加代码,执行校验

     this.$refs['pageForm'].validate((valid) => {
              if (valid) {
                alert('提交');
              } else {
                alert('校验失败')
                return false;
              }
            })
    

    2.3.2 Api调用

    1、在cms.js中定义page_add方法。

    /*页面添加*/
    export const page_add = params => {
      return http.requestPost(apiUrl+'/cms/page/add', params)
    }
    

    2、添加事件

    本功能使用到两个UI组件:

    1、使用element-ui的message-box组件弹出确认提交窗口(http://element.eleme.io/#/zhCN/component/message-box )。

    this.$confirm('确认提交吗?', '提示', {}).then(() => {})
    

    2、使用 message 组件提示操作结果 (http://element.eleme.io/#/zh-CN/component/message)

    this.$message({
    	message: '提交成功',
    	type: 'success' 
    })
    

    完整的代码如下:

    addSubmit: function () {
            this.$refs['pageForm'].validate((valid) => {
              if (valid) {
                this.$confirm('确认提交吗?', '提示', {}).then(()=>{
                  cmsApi.page_add(this.pageForm).then((res) => {
                    console.log(res);
                    if(res.success) {
                      this.$message({
                        message: '提交成功',
                        type: 'success'
                      });
                      this.$refs['pageForm'].resetField();
                    }
                  })
                })
              } else {
                this.$message.error('提交失败');
              }
            })
          }
    

    下边是测试:

    1、进入页面列表页面

    2、点击“增加页面”按钮

    3、输入页面信息点击“提交”

    3 修改页面

    修改页面用户操作流程:

    1、用户进入修改页面,在页面上显示了修改页面的信息
    2、用户修改页面的内容,点击“提交”,提示“修改成功”或“修改失败”
    

    3.1 修改页面接口定义

    @ApiOperation("通过ID查询页面")
    public CmsPage findById(String id);
    
    @ApiOperation("修改页面")
    public CmsPageResult edit(String id, CmsPage cmsPage);
    

    说明:提交数据使用post、put都可以,只是根据http方法的规范,put方法是对服务器指定资源进行修改,所以这里使用put方法对页面修改进行修改。

    3.2 修改页面服务端开发

    3.2.1 Dao

    使用 Spring Data提供的findById方法完成根据主键查询 。

    使用 Spring Data提供的save方法完成数据保存 。

    3.2.2 Service

    /**
         * 根据ID查询页面
         */
        public CmsPage getById(String id) {
            Optional<CmsPage> optional = cmsPageRepository.findById(id);
            if (optional.isPresent()) {
                return optional.get();
            }
            //返回空
            return null;
        }
    
        /**
         * 更新页面信息
         */
        public CmsPageResult update(String id, CmsPage cmsPage) {
            //根据id查询页面信息
            CmsPage one = this.getById(id);
            if (one != null) {
                //更新模板id
                one.setTemplateId(cmsPage.getTemplateId());
                //更新所属站点
                one.setSiteId(cmsPage.getSiteId());
                //更新页面别名
                one.setPageAliase(cmsPage.getPageAliase());
                //更新页面名称
                one.setPageName(cmsPage.getPageName());
                //更新访问路径
                one.setPageWebPath(cmsPage.getPageWebPath());
                //更新物理路径
                one.setPagePhysicalPath(cmsPage.getPagePhysicalPath());
                //执行更新
                CmsPage save = cmsPageRepository.save(one);
                if (save != null) {
                    // 返回成功
                    CmsPageResult cmsPageResult = new CmsPageResult(CommonCode.SUCCESS, save);
                    return cmsPageResult;
                }
            }
            // 返回失败
            return new CmsPageResult(CommonCode.FAIL, null);
        }
    

    3.2.3 Controller

    1、根据id查询页面

    @Override
    @GetMapping("/get/{id}")
    public CmsPage findById(@PathVariable String id) {
    	return pageService.getById(id);
    }
    

    2、保存页面信息

    @Override
    @PutMapping("/edit/{id}") // 这里使用put方法,http方法中put表示更新
    public CmsPageResult edit(@PathVariable String id, @RequestBody CmsPage cmsPage) {
    	return pageService.update(id, cmsPage);
    }
    

    3.3 修改页面前端开发

    3.3.1 页面处理流程

    页面的处理流程如下:

    1、进入页面,通过钩子方法请求服务端获取页面信息,并赋值给数据模型对象
    2、页面信息通过数据绑定在表单显示
    3、用户修改信息点击“提交”请求服务端修改页面信息接口
    

    3.3.3 修改页面

    3.3.3.1 编写page_edit页面

    1、编写page_edit.vue

    页面布局同添加页面,略。

    2、配置路由

    进入路由index.js页面传入pageId

    import page_edit from '@/module/cms/page/page_edit.vue';
    { path: '/cms/page/edit/:pageId', name:'修改页面',component: page_edit,hidden:true},
    

    3、在页面列表添加“编辑”链接

    参考table组件的例子,在page_list.vue上添加“操作”列

    <el-table-column label="操作" width="80">
    	<template slot-scope="page">
    		<el-button size="small" type="text" @click="edit(page.row.pageId)">编辑</el-button>
    	</template>
    </el-table-column>
    

    编写edit方法

    edit(pageId){
            this.$router.push({path: '/cms/page/edit/' + pageId, query: {
                page: this.params.page,
                siteId: this.params.siteId
              }})
    }
    

    4、测试预览

    点击“编辑”打开修改页面窗口。

    3.3.3.2 页面内容显示

    本功能实现:进入修改页面立即显示要修改的页面信息。

    1、定义api方法

    /*页面查询*/
    export const page_get= id => {
      return http.requestQuickGet(apiUrl + '/cms/page/get/' + id)
    }
    

    2、定义数据对象

    进入修改页面传入pageId参数,在数据模型中添加pageId。

    data(){
    	return { 
    		...... 
    		//页面id
    		pageId:'', 
    		......
    	}
    }
    

    3、在created钩子方法中查询页面信息

    created: function () {
          //页面参数通过路由传入,这里通过this.$route.params来获取
          this.pageId=this.$route.params.pageId;
          //根据主键查询页面信息
          cmsApi.page_get(this.pageId).then((res) => {
            console.log(res);
            if(res){
              this.pageForm = res;
            }
          });
        },
    

    4、预览页面回显效果

    3.3.4 Api调用

    1、定义api方法

    /*页面修改,采用put方法*/
    export const page_edit= (id, params) => {
      return http.requestPut(apiUrl + '/cms/page/edit/' + id, params)
    }
    

    2、提交按钮方法

    添加提交按钮事件:

    <el-button type="primary" @click.native="editSubmit" :loading="addLoading">提交</el-button>
    

    3、提交按钮事件内容:

    editSubmit(){
            this.$refs.pageForm.validate((valid) => {
              if (valid) {
                this.$confirm('确认提交吗?', '提示', {}).then(() => {
                  this.addLoading = true;
                  cmsApi.page_edit(this.pageId,this.pageForm).then((res) => {
                      console.log(res);
                    if(res.success){
                      this.addLoading = false;
                      this.$message({
                        message: '提交成功',
                        type: 'success'
                      });
                      //返回
                      this.go_back();
    
                    }else{
                      this.addLoading = false;
                      this.$message.error('提交失败');
                    }
                  });
                });
              }
            });
          }
    

    4、测试

    修改页面信息,点击提交。

    4 删除页面

    用户操作流程:

    1、用户进入用户列表,点击“删除”
    2、执行删除操作,提示“删除成功”或“删除失败”
    

    4.1 删除页面接口定义

    @ApiOperation("通过ID删除页面")
    public ResponseResult delete(String id);
    

    4.2.1Dao

    使用 Spring Data提供的deleteById方法完成删除操作 。

    4.2.2 Service

    /**
         * 删除页面
         * @param id
         * @return
         */
        public ResponseResult delete(String id) {
            CmsPage one = this.getById(id);
            if(one != null) {
                //删除页面
                cmsPageRepository.deleteById(id);
                return new ResponseResult(CommonCode.SUCCESS);
            }
            return new ResponseResult(CommonCode.FAIL);
        }
    

    4.2.3 Controller

    @Override
        @DeleteMapping("/del/{id}")
        //使用http的delete方法完成岗位操作
        public ResponseResult delete(@PathVariable String id) {
            return pageService.delete(id);
        }
    

    4.3 删除页面前端开发

    4.3.1 Api方法

    /*页面删除*/
    export const page_del = id => {
      return http.requestDelete(apiUrl + '/cms/page/del/' + id)
    }
    

    4.3.2 编写页面

    1、在page_list.vue页面添加删除按钮

    <el-table-column label="操作" width="80">
            <template slot-scope="page">
              <el-button size="small" type="text" @click="edit(page.row.pageId)">编辑</el-button>
              <el-button size="small" type="text" @click="del(page.row.pageId)">删除</el-button>
            </template>
    </el-table-column>
    

    2、删除事件

    del:function (pageId) {
            this.$confirm('您确认删除吗?', '提示', { }).then(() => {
    
              //调用服务端接口
              cmsApi.page_del(pageId).then(res=>{
    
                if(res.success){
                  this.$message.success("删除成功")
                  //刷新页面
                  this.query()
                }else{
                  this.$message.error("删除失败")
                }
              })
            })
    
          }
    

    5 异常处理

    5.1 异常处理的问题分析

    从添加页面的service方法中找问题:

    问题: 
    1、上边的代码只要操作不成功仅向用户返回“错误代码:11111,失败信息:操作失败”,无法区别具体的错误信息。 
    2、service方法在执行过程出现异常在哪捕获?在service中需要都加try/catch,如果在controller也需要添加 try/catch,代码冗余严重且不易维护。 
    解决方案: 
    1、在Service方法中的编码顺序是先校验判断,有问题则抛出具体的异常信息,最后执行具体的业务操作,返回成功信息。 2、在统一异常处理类中去捕获异常,无需controller捕获异常,向用户返回统一规范的响应信息。
    

    代码模板如下:

    /**
         * 添加页面
         */
        public CmsPageResult add(CmsPage cmsPage) {
            //校验cmsPage是否为空
            if(cmsPage == null){
                //抛出异常,非法请求
                //......
            }
            //校验页面是否存在,根据页面名称、站点Id、页面webpath查询
            CmsPage cmsPage1 = cmsPageRepository.findByPageNameAndSiteIdAndPageWebPath(cmsPage.getPageName(), cmsPage.getSiteId(), cmsPage.getPageWebPath());
            //校验页面是否存在,已存在则抛出异常
            if(cmsPage1 != null) {
                //抛出异常,非法请求
                //......
            }
            cmsPage.setPageId(null);//添加页面主键由spring data 自动生成
            cmsPageRepository.save(cmsPage);
            //返回结果
            return  new CmsPageResult(CommonCode.SUCCESS, cmsPage);
        }
    

    5.2 异常处理流程

    系统对异常的处理使用统一的异常处理流程:

    1、自定义异常类型。
    2、自定义错误代码及错误信息。
    3、对于可预知的异常由程序员在代码中主动抛出,由SpringMVC统一捕获。
    可预知异常是程序员在代码中手动抛出本系统定义的特定异常类型,由于是程序员抛出的异常,通常异常信息比较齐全,程序员在抛出时会指定错误代码及错误信息,获取异常信息也比较方便。
    4、对于不可预知的异常(运行时异常)由SpringMVC统一捕获Exception类型的异常。
    不可预知异常通常是由于系统出现bug、或一些不要抗拒的错误(比如网络中断、服务器宕机等),异常类型为 RuntimeException类型(运行时异常)。
    5、可预知的异常及不可预知的运行时异常最终会采用统一的信息格式(错误代码+错误信息)来表示,最终也会随请求响应给客户端。
    

    异常抛出及处理流程:

    1、在controller、service、dao中程序员抛出自定义异常;springMVC框架抛出框架异常类型
    2、统一由异常捕获类捕获异常,并进行处理
    3、捕获到自定义异常则直接取出错误代码及错误信息,响应给用户。
    4、捕获到非自定义异常类型首先从Map中找该异常类型是否对应具体的错误代码,如果有则取出错误代码和错误信息并响应给用户,如果从Map中找不到异常类型所对应的错误代码则统一为99999错误代码并响应给用户。
    5、将错误代码及错误信息以Json格式响应给用户。
    

    5.3 可预知异常处理

    5.3.1 自定义异常类

    在common工程定义异常类型。

    package com.xuecheng.framework.exception;
    
    import com.xuecheng.framework.model.response.ResultCode;
    
    /**
     * @author HackerStar
     * @create 2020-08-02 11:06
     */
    public class CustomException extends RuntimeException {
    
        private ResultCode resultCode;
    
        public CustomException(ResultCode resultCode) {
            //异常信息为错误代码+异常信息
            super("错误代码:"+resultCode.code()+"错误信息:"+resultCode.message());
            this.resultCode = resultCode;
        }
    
        public ResultCode getResultCode() {
            return this.resultCode;
        }
    
    }
    

    5.3.2 异常抛出类

    package com.xuecheng.framework.exception;
    
    import com.xuecheng.framework.model.response.ResultCode;
    
    /**
     * @author HackerStar
     * @create 2020-08-02 11:09
     */
    public class ExceptionCast {
        //使用此静态方法抛出自定义异常
        public static void cast(ResultCode resultCode) {
            throw new CustomException(resultCode);
        }
    }
    

    5.3.3 异常捕获类

    使用 @ControllerAdvice和@ExceptionHandler注解来捕获指定类型的异常

    package com.xuecheng.framework.exception;
    
    import com.xuecheng.framework.model.response.ResponseResult;
    import com.xuecheng.framework.model.response.ResultCode;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.web.bind.annotation.ControllerAdvice;
    import org.springframework.web.bind.annotation.ExceptionHandler;
    import org.springframework.web.bind.annotation.ResponseBody;
    
    /**
     * @author HackerStar
     * @create 2020-08-02 11:20
     */
    @ControllerAdvice
    public class ExceptionCatch {
        private static final Logger LOGGER = LoggerFactory.getLogger(ExceptionCatch.class);
    
        // 捕获CustomException异常
        @ExceptionHandler(CustomException.class)
        @ResponseBody
        public ResponseResult customException(CustomException e) {
            LOGGER.error("catch exception : {}
    exception: ",e.getMessage(), e);
            ResultCode resultCode = e.getResultCode();
            ResponseResult responseResult = new ResponseResult(resultCode);
            
            return responseResult;
        }
    }
    

    5.3.4 异常处理测试

    5.3.4.1 定义错误代码

    每个业务操作的异常使用异常代码去标识。

    package com.xuecheng.framework.domain.cms.response;
    
    import com.xuecheng.framework.model.response.ResultCode;
    import lombok.ToString;
    
    /**
     * Created by mrt on 2018/3/5.
     */
    @ToString
    public enum CmsCode implements ResultCode {
        CMS_ADDPAGE_EXISTSNAME(false,24001,"页面名称已存在!"),
        CMS_GENERATEHTML_DATAURLISNULL(false,24002,"从页面信息中找不到获取数据的url!"),
        CMS_GENERATEHTML_DATAISNULL(false,24003,"根据页面的数据url获取不到数据!"),
        CMS_GENERATEHTML_TEMPLATEISNULL(false,24004,"页面模板为空!"),
        CMS_GENERATEHTML_HTMLISNULL(false,24005,"生成的静态html为空!"),
        CMS_GENERATEHTML_SAVEHTMLERROR(false,24005,"保存静态html出错!"),
        CMS_COURSE_PERVIEWISNULL(false,24007,"预览页面为空!");
        //操作代码
        boolean success;
        //操作代码
        int code;
        //提示信息
        String message;
        private CmsCode(boolean success, int code, String message){
            this.success = success;
            this.code = code;
            this.message = message;
        }
    
        @Override
        public boolean success() {
            return success;
        }
    
        @Override
        public int code() {
            return code;
        }
    
        @Override
        public String message() {
            return message;
        }
    }
    
    5.3.4.2 异常处理测试

    1、抛出异常

    在controller、service、 dao中都可以抛出异常。

    修改PageService的add方法,添加抛出异常的代码

    //校验页面是否存在,根据页面名称、站点Id、页面webpath查询
            CmsPage cmsPage1 = cmsPageRepository.findByPageNameAndSiteIdAndPageWebPath(cmsPage.getPageName(), cmsPage.getSiteId(), cmsPage.getPageWebPath());
            //校验页面是否存在,已存在则抛出异常
            if(cmsPage1 != null) {
                //抛出异常,非法请求
                //......
                ExceptionCast.cast(CmsCode.CMS_ADDPAGE_EXISTSNAME);
            }
    

    2、启动工程,扫描到异常捕获的类ExceptionCatch

    在springBoot的启动类中添加

    @ComponentScan(basePackages = "com.xuecheng.framework")//扫描common工程下的类
    

    3、前端展示异常信息

    服务端响应信息如下:

    页面提取异常处理

    5.4 不可预知异常处理

    5.4.1 定义异常捕获方法

    5.4.1.1 异常抛出测试

    使用postman测试添加页面,不输入cmsPost信息,提交,报错信息如下:

    org.springframework.http.converter.HttpMessageNotReadableException
    此异常是springMVC在进行参数转换时报的错误。
    

    具体的响应的信息为:

    {
        "timestamp": "2020-08-02T08:14:45.355+0000",
        "status": 400,
        "error": "Bad Request",
        "message": "Required request body is missing: public com.xuecheng.framework.domain.cms.response.CmsPageResult com.xuecheng.manage_cms.web.controller.CmsPageController.add(com.xuecheng.framework.domain.cms.CmsPage)",
        "path": "/cms/page/add"
    }
    

    上边的响应信息在客户端是无法解析的。

    在异常捕获类中添加对Exception异常的捕获:

     // 捕获Exception异常
        @ExceptionHandler(Exception.class)
        @ResponseBody
        public ResponseResult exception(Exception exception) {
            LOGGER.error("catch exception : {} ", exception.getMessage());
    
            return null;
        }
    
    5.4.1.2 异常捕获方法

    针对上边的问题其解决方案是:

    1、我们在map中配置HttpMessageNotReadableException和错误代码。

    2、在异常捕获类中对Exception异常进行捕获,并从map中获取异常类型对应的错误代码,如果存在错误代码则返回此错误,否则统一返回99999错误。

    具体的开发实现如下:

    在CommonCode.java中添加代码:

    INVALID_PARAM(false,10003,"非法参数!"),
    
    1、在通用错误代码类CommCode中配置非法参数异常
    INVALID_PARAM(false,10003,"非法参数!"),
    
    2、在异常捕获类中配置 HttpMessageNotReadableException 为非法参数异常
    异常捕获类代码如下:
    
    package com.xuecheng.framework.exception;
    
    import com.google.common.collect.ImmutableMap;
    import com.xuecheng.framework.model.response.CommonCode;
    import com.xuecheng.framework.model.response.ResponseResult;
    import com.xuecheng.framework.model.response.ResultCode;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.http.converter.HttpMessageNotReadableException;
    import org.springframework.web.bind.annotation.ControllerAdvice;
    import org.springframework.web.bind.annotation.ExceptionHandler;
    import org.springframework.web.bind.annotation.ResponseBody;
    
    /**
     * @author HackerStar
     * @create 2020-08-02 11:20
     */
    @ControllerAdvice
    public class ExceptionCatch {
        private static final Logger LOGGER = LoggerFactory.getLogger(ExceptionCatch.class);
        //使用EXCEPTIONS存放异常类型和错误代码的映射,ImmutableMap的特点的一旦创建不可改变,并且线程安全
        private static ImmutableMap<Class<? extends Throwable>, ResultCode> EXCEPTIONS;
        //使用builder来构建一个异常类型和错误代码的异常
        protected static ImmutableMap.Builder<Class<? extends Throwable>, ResultCode> builder = ImmutableMap.builder();
    
        // 捕获CustomException异常
        @ExceptionHandler(CustomException.class)
        @ResponseBody
        public ResponseResult customException(CustomException e) {
            LOGGER.error("catch exception : {}
    exception: ",e.getMessage(), e);
            ResultCode resultCode = e.getResultCode();
            ResponseResult responseResult = new ResponseResult(resultCode);
    
            return responseResult;
        }
    
        // 捕获Exception异常
        @ExceptionHandler(Exception.class)
        @ResponseBody
        public ResponseResult exception(Exception e) {
            LOGGER.error("catch exception : {}
    exception: ",e.getMessage(), e);
            if(EXCEPTIONS == null)
                EXCEPTIONS = builder.build();
            final ResultCode resultCode = EXCEPTIONS.get(e.getClass());
            final ResponseResult responseResult;
            if (resultCode != null) {
                responseResult = new ResponseResult(resultCode);
            } else {
                responseResult = new ResponseResult(CommonCode.SERVER_ERROR);
            }
    
            return responseResult;
        }
    
        static {
            //在这里加入一些基础的异常类型判断
            builder.put(HttpMessageNotReadableException.class,CommonCode.INVALID_PARAM);
        }
    }
    
    

    5.4.2 异常处理测试

    仍然模拟“问题测试”中的测试步骤,异常结果为“非法参数”。

    6 实战

    此部分为自学内容,根据今天所学知识完成下边的任务。

    6.1 查询条件完善

    页面查询条件增加:页面名称、页面类型。

    页面名称对应CmsPage模型类中的pageName属性。

    页面类型对应CmsPage模型类中的pageType属性。

    查询要求:

    页面名称:模糊查询

    页面类型:精确匹配,页面类型包括:静态和动态,在数据库中静态用“0”表示,动态用“1”表示。

    6.2 页面属性增加DataUrl

    在CmsPage.java模型类型中有一个dataUrl属性,此属性在页面静态化时需要填写。

    本需求要求:

    1、在新增页面增加dataUrl输入框,并支持添加。

    2、在修改页面增加dataUrl输入框,并支持修改。

  • 相关阅读:
    scala
    数据结构(01)
    基本算法(07)
    基本算法(06)
    基本算法(05)
    git pull文件时和本地文件冲突的问题
    获取两个日期之间的日期形成一个集合
    lombok的简单介绍(2)
    springboot启动报错
    逆向工程的创建
  • 原文地址:https://www.cnblogs.com/artwalker/p/13419627.html
Copyright © 2011-2022 走看看