精华内容
下载资源
问答
  • 点击上方“蓝字”关注我们无论你是正在学习vue 还是在学习node, 你一定碰到前端路由和后端路由这两个概念, 因为路由是实现页面之间的切换的一个重要途径。相信我,这篇文章一定能让你入门路由的概念。路由的概念...
    4337d98f682e5965bc0ab83f0b9db5a5.png

    点击上方“蓝字”关注我们

    无论你是正在学习vue 还是在学习node, 你一定会碰到前端路由和后端路由这两个概念, 因为路由是实现页面之间的切换的一个重要途径。相信我,这篇文章一定能让你入门路由的概念。

    270048cd1f080daba24fa115d8508595.png路由的概念270048cd1f080daba24fa115d8508595.png

    首先,什么是路由?那你想到的一定是我们生活中使用的路由器。没错, 我们所说到的路由,原理就跟路由器相似。

    其实, 路由就是绝对数据包从来源到目的地的路径,将输入端的数据转移到合适的输出端。说的通俗一点就是, 路由有一个非常重要的概念叫做路由表,本质上是一个映射表,决定了数据的指向。

    270048cd1f080daba24fa115d8508595.png后端路由270048cd1f080daba24fa115d8508595.png

    我为什么要先讲后端路由呢, 因为后端路由的概念出现在前端发展的最早期, 那个时候前后端未分离, 用户在浏览器请求不同的 url地址时,客户端会向服务器请求数据, 而服务器接收到这个url地址时,会根据url地址, 在服务端通过html+css以及一些后端语言将需要的数据直接渲染到网页上, 然后再发送给客户端,最终呈现在浏览器上。那么在后端, 路由映射表中就是不同的url地址与不同的html + css + 后端语言 + 数据库中的数据 之间的映射。

    下面来看一张图,更形象地了解一下后端路由:

    c5b46755058ce0c13cf5eb5ed8ee542f.png

    再换种方式说,就是后端路由就是有很多套页面代码, 它们各自对应着一个url地址, 当你请求一个url地址时,就去找到对应的那套页面代码,进行渲染解析。

    270048cd1f080daba24fa115d8508595.png前端路由270048cd1f080daba24fa115d8508595.png

    最后再讲前端路由,是因为前端路由是后来发展到SPA(单页面富应用)时才出现的概念。整个页面就只有一整套的css + js, 这一套html + css + js中包含了很多个网页的代码, 当我们请求不同的url地址时, 客户端会从这一整套的css + js 代码中 找到对应的部分 css + js代码,将他们解析执行,渲染在页面上。

    同样的来看一张图,形象地了解一下前端路由:

    2abd73df3221049119f4a31b93ebe8a8.png

    270048cd1f080daba24fa115d8508595.png其它知识270048cd1f080daba24fa115d8508595.png

    其实在前后端路由的这两个概念里,有涉及到其他的两个概念,那就是前端渲染和后端渲染, 如果想了解更多的话,可以去我的另一篇文章看一下——超详细图文解释——客户端渲染和服务器渲染的区别

    因为这些概念都很有可能会在面试中被问到,所以我觉得还是都了解账户哦一下比较好。

    好了, 前后端路由的知识点就给大家讲到这,希望能对大家在学习vue-router 或 node 时, 有一个辅助性的帮助, 如果有什么地方讲的不对或者说是什么地方不懂,欢迎私信我, 我也会即使回复大家的,谢谢。d0297c3ecbd78a9bca3bc786c0e133ff.gif

    文章都看完了e23460378bcfede3a150d81498414cc8.gif不点个 419ef202a313a114c996406284df6a66.png  吗

    展开全文
  • 前端路由和后端路由的概念讲解引言 引言 无论你是正在学习vue 还是在学习node, 你一定碰到前端路由和后端路由这两个概念, 因为路由是实现页面之间的切换的一个重要途径,

    引言

    无论你是正在学习vue 还是在学习node, 你一定会碰到前端路由和后端路由这两个概念, 因为路由是实现页面之间的切换的一个重要途径。相信我,这篇文章一定能让你入门路由的概念。

    • 公众号:前端印象
    • 不定时有送书活动,记得关注~
    • 关注后回复对应文字领取:【面试题】、【前端必看电子书】、【数据结构与算法完整代码】、【前端技术交流群】

    正文

    一、路由的概念

    首先,什么是路由? 那你想到的一定是我们生活中使用的路由器。 没错, 我们所说到的路由,原理就跟路由器相似。

    其实, 路由就是绝对数据包从来源到目的地的路径,将输入端的数据转移到合适的输出端。说的通俗一点就是, 路由有一个非常重要的概念叫做路由表,本质上是一个映射表,决定了数据的指向。

    二、后端路由

    我为什么要先讲后端路由呢, 因为后端路由的概念出现在前端发展的最早期, 那个时候前后端未分离, 用户在浏览器请求不同的 url地址时,客户端会向服务器请求数据, 而服务器接收到这个url地址时,会根据url地址, 在服务端通过html+css以及一些后端语言将需要的数据直接渲染到网页上, 然后再发送给客户端,最终呈现在浏览器上。那么在后端, 路由映射表中就是不同的url地址与不同的html + css + 后端语言 + 数据库中的数据 之间的映射。

    下面来看一张图,更形象地了解一下后端路由:
    在这里插入图片描述
    再换种方式说,就是后端路由就是有很多套页面代码, 它们各自对应着一个url地址, 当你请求一个url地址时,就去找到对应的那套页面代码,进行渲染解析。

    三、前端路由

    最后再讲前端路由,是因为前端路由是后来发展到SPA(单页面富应用)时才出现的概念。 整个页面就只有一整套的css + js, 这一套html + css + js中包含了很多个网页的代码, 当我们请求不同的url地址时, 客户端会从这一整套的css + js 代码中 找到对应的部分 css + js代码,将他们解析执行,渲染在页面上。

    同样的来看一张图,形象地了解一下前端路由:
    在这里插入图片描述

    四、其他知识

    其实在前后端路由的这两个概念里,有涉及到其他的两个概念,那就是前端渲染和后端渲染, 如果想了解更多的话,可以去我的另一篇文章看一下,客户端渲染和服务器渲染的区别
    因为这些概念都很有可能会在面试中被问到,所以我觉得还是都了解账户哦一下比较好。

    结束语

    好了, 前后端路由的知识点就给大家讲到这,希望能对大家在学习vue-router 或 node 时, 有一个辅助性的帮助, 如果有什么地方讲的不对或者说是什么地方不懂,欢迎评论告知, 我也会即使回复大家的,谢谢。

    展开全文
  • .vue文件的结构如下: <template> <!‐‐编写页面静态部分,即view部分‐‐> 测试页面显示... .../*编写页面样式,不是必须*/ ...注意:template内容必须有一个根元素,否则vue会报错,这里..


    .vue文件的结构如下:

    <template>
    <!‐‐编写页面静态部分,即view部分‐‐>
    测试页面显示...
    </template>
    <script>
    /*编写页面静态部分,即model及vm部分。*/
    </script>
    <style>
    /*编写页面样式,不是必须*/
    </style>

    在页面的template中填写 “测试页面显示...”。
    注意:template内容必须有一个根元素,否则vue会报错,这里我们在template标签内定义一个div。


    3.1.1.2 页面路由

    在cms目录下创建page_list.vue页面。
    现在先配置路由,实现url访问到页面再进行内容完善与调试。

    1、在cms的router下配置路由

    import Home from '@/module/home/page/home.vue';
    import page_list from '@/module/cms/page/page_list.vue';
    export default [{
    path: '/cms',
    component: Home,
    name: 'CMS内容管理',
    hidden: false,
    children:[
    {path:'/cms/page/list',name:'页面列表',component: page_list,hidden:false}
    ]
    }
    ]

    2、在base目录下的router导入cms模块的路由
    3、测试
    启动工程,刷新页面,页面可以外正常浏览,并且看到“测试页面显示...”字样
    3.1.2 Table组件测试
    3.1.2.1 Element-UI介绍
    使用Element-UI来构建界面,Element是一套为开发者、设计师和产品经理准备的基于 Vue 2.0 的桌面端组
    件库。
    Element-UI官方站点:http://element.eleme.io/#/zh-CN/component/installation
    3.1.2.2 Table组件测试
    本功能实现的页面列表,用户可以进行分页查询、输入查询条件查询,通过查看Element-UI库,我们需要Table 表
    格、Form表单 及Pagination 分页组件。
    进入Element-UI官方,找到Table组件,拷贝源代码到vue页面中,如下:
    // // 导入路由规则
    import HomeRouter from '@/module/home/router'
    import CmsRouter from '@/module/cms/router'
    // 合并路由规则
    concat(HomeRouter)
    concat(CmsRouter)
    <template>
    <div>
    <!‐‐相当于编写html的内容‐‐>
    <el‐table
    :data="tableData"
    stripe
    style="width: 100%">
    <el‐table‐column
    prop="date"
    label="日期"
    width="180">
    </el‐table‐column>
    <el‐table‐column
    prop="name"
    label="姓名"
    width="180">
    </el‐table‐column>
    <el‐table‐column
    prop="address"
    label="地址">
    </el‐table‐column>
    </el‐table>
    </div>
    </template>
    <script>
    //填写js代码,实现VM的功能,创建vue实例
    export default {
    data() {
    return {
    tableData: [{
    date: '2016‐05‐02',
    name: '王小虎',
    address: '上海市普陀区金沙江路 1518 弄'
    }, {
    date: '2016‐05‐04',
    name: '王小虎',
    address: '上海市普陀区金沙江路 1517 弄'
    }, {
    date: '2016‐05‐01',
    name: '王小虎',
    address: '上海市普陀区金沙江路 1519 弄'
    }, {
    date: '2016‐05‐03',
    name: '王小虎',
    address: '上海市普陀区金沙江路 1516 弄'
    }]
    }
    }
    }
    </script>
    <style>
    /*css样式*/
    </style>
    测试:
    通过查看代码发现:
    el-table组件绑定了tableData模型数据。
    tableData模型数据在script标签中定义。
    3.1.3页面内容完善
    根据需求完善页面内容,完善列表字段,添加分页组件。
    <template>
    <div>
    <el‐button type="primary" v‐on:click="query" size="small">查询</el‐button>
    <el‐table
    :data="list"
    stripe
    style="width: 100%">
    <el‐table‐column type="index" width="60">
    </el‐table‐column>
    <el‐table‐column prop="pageName" label="页面名称" width="120">
    </el‐table‐column>
    <el‐table‐column prop="pageAliase" label="别名" width="120">
    </el‐table‐column>
    <el‐table‐column prop="pageType" label="页面类型" width="150">
    </el‐table‐column>
    <el‐table‐column prop="pageWebPath" label="访问路径" width="250">
    </el‐table‐column>
    <el‐table‐column prop="pagePhysicalPath" label="物理路径" width="250">
    </el‐table‐column>
    <el‐table‐column prop="pageCreateTime" label="创建时间" width="180" >
    </el‐table‐column>
    </el‐table>
    <el‐pagination
    layout="prev, pager, next"
    :page‐size="this.params.size"
    v‐on:current‐change="changePage"
    :total="total" :current‐page="this.params.page" style="float:right;">
    </el‐pagination>
    </div>
    </template>
    <script>
    export default {
    data() {
    return {
    list:[],
    total:50,
    params:{
    page:1,//页码
    size:2//每页显示个数
    }
    }
    },
    methods:{
    //分页查询
    2、测试
    3.2 Api调用
    3.2.1 Api方法定义
    在cms模块的api目录定义cms.js,
    在cms.js中定义如下js方法,此方法实现http请求服务端页面查询接口。
    axios实现了http方法的封装,vue.js官方不再继续维护vue-resource,推荐使用 axios。
    3.2.2 Api调用
    前端页面导入cms.js,调用js方法请求服务端页面查询接口。
    1)导入cms.js
    changePage:function () {
    this.query()
    },
    //查询
    query:function () {
    alert("查询")
    }
    }
    }
    </script>
    //public是对axios的工具类封装,定义了http请求方法
    import http from './../../../base/api/public'
    export const page_list = (page,size,params) => {
    return http.requestQuickGet('http://localhost:31001/cms/page/list/'+page+'/'+size)
    }query方法中调用 page_list方法
    3.3 跨域问题解决
    测试 上边的代理 ,结果 报错如下 :
    No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin
    'http://localhost:11000' is therefore not allowed access.
    原因:浏览器的同源策略不允许跨域访问,所谓同源策略是指协议、域名、端口相同。
    解决:采用proxyTable解决。
    proxyTable是什么?
    vue-cli提供的解决vue开发环境下跨域问题的方法,proxyTable的底层使用了http-proxy-
    middleware(https://github.com/chimurai/http-proxy-middleware),它是http代理中间件,它依赖node.js,
    基本原理是用服务端代理解决浏览器跨域:
    cms跨域解决原理:
    1、访问页面http://localhost:11000/
    2、页面请求http://localhost:11000/cms
    import * as cmsApi from '../api/cms'
    //查询
    query:function () {
    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
    })
    }
    由于url由http://localhost:31001/cms...改为“http://localhost:11000/cms.",所以不存在跨域
    3、通过proxyTable由node服务器代理请求 http://localhost:31001/cms.
    服务端不存在跨域问题
    具体的配置如下:
    1)修改api方法中url的定义
    请求前加/api前缀
    2)在confifig/index.js下配置proxyTable。
    以/api/cms开头的请求,代理请求http://localhost:31001
    3.4 分页查询测试
    1、定义分页视图
    使用v-on监听更改分页事件
    2、定义数据模型对象
    //public是对axios的工具类封装,定义了http请求方法
    import http from './../../../base/api/public'
    let sysConfig = require('@/../config/sysConfig')
    let apiUrl = sysConfig.xcApiUrlPre;
    export const page_list = (page,size,params) => {
    return http.requestQuickGet(apiUrl+'/cms/page/list/'+page+'/'+size)
    }
    '/api/cms': {
    target: 'http://localhost:31001',
    pathRewrite: {
    '^/api': ''//实际请求去掉/api
    }
    <el‐pagination
    layout="prev, pager, next"
    :page‐size="this.params.size"
    v‐on:current‐change="changePage"
    :total="total" :current‐page="this.params.page" style="float:right;">
    </el‐pagination>
    3、定义分页方法,接收页码参数
    修改完毕,测试分页效果。
    3.5 进入页面立即查询
    目前实现的功能是进入页面点击查询按钮向服务端表求查询,实际的需求是进入页面立即查询。
    如何实现?
    这要用到vue的钩子函数,每个 Vue 实例在被创建时都要经过一系列的初始化过程——例如,需要设置数据监听、
    编译模板、将实例挂载到 DOM 并在数据变化时更新 DOM 等。同时在这个过程中也会运行一些叫做生命周期钩子
    的函数,这给了用户在不同阶段添加自己的代码的机会。
    data() {
    return {
    list:[],
    total:50,
    params:{
    page:1,//页码
    size:2//每页显示个数
    }
    }
    //分页查询,接收page页码
    changePage(page){
    this.params.page = page;
    this.query()
    }
    通常使用最多的是created和mounted两个钩子:
    created:vue实例已创建但是DOM元素还没有渲染生成。
    mounted:DOM元素渲染生成完成后调用。
    本例子在两个方法的任意一个都满足需求:
    添加如下代码:
    mounted() {
    //默认查询页面
    this.query()
    }
    重新刷新页面。
    4 前后端请求响应流程小结
    参考 “讲义-->前后端请求响应流程.png”,如下:
    1、在浏览器输入前端url
    2、前端框架vue.js根据url解析路由,根据路由找到page_list.vue页面
    3、首先执行page_list.vue中的钩子方法
    4、在钩子方法中调用query方法。
    5、在query方法中调用cms.js中的page_list方法
    6、cms.js中的page_list方法通过axios请求服务端接口
    7、采用proxyTable解决跨域问题,node.js将请求转发到服务端(http://localhost:31001/cms/page/list)
    8、服务端处理,将查询结果响应给前端
    9、成功响应调用then方法,在then方法中处理响应结果,将查询结果赋值给数据模型中的total和list变量。
    10、vue.js通过双向数据绑定将list数据渲染输出


    1 自定义条件查询
    1.1 需求分析
    在页面输入查询条件,查询符合条件的页面信息。
    查询条件如下:
    站点Id:精确匹配
    模板Id:精确匹配
    页面别名:模糊匹配
    ...
    1.2 服务端
    1.2.1 Dao
    下边测试fifindAll方法实现自定义条件查询:
    使用 CmsPageRepository中的findAll(Example<S> var1, Pageable var2)方法实现,无需定义。
    //自定义条件查询测试
    @Test
    public void testFindAll() {
    //条件匹配器
    ExampleMatcher exampleMatcher = ExampleMatcher.matching();
    exampleMatcher = exampleMatcher.withMatcher("pageAliase",
    ExampleMatcher.GenericPropertyMatchers.contains());
    //页面别名模糊查询,需要自定义字符串的匹配器实现模糊查询
    //ExampleMatcher.GenericPropertyMatchers.contains() 包含
    //ExampleMatcher.GenericPropertyMatchers.startsWith()//开头匹配
    //条件值
    CmsPage cmsPage = new CmsPage();
    //站点ID
    cmsPage.setSiteId("5a751fab6abb5044e0d19ea1");
    //模板ID
    cmsPage.setTemplateId("5a962c16b00ffc514038fafd");
    // cmsPage.setPageAliase("分类导航");
    //创建条件实例
    Example<CmsPage> example = Example.of(cmsPage, exampleMatcher);
    1.2.2 Service
    在PageService的fifindlist方法中增加自定义条件查询代码
    1.2.3 Controller
    Pageable pageable = new PageRequest(0, 10);
    Page<CmsPage> all = cmsPageRepository.findAll(example, pageable);
    System.out.println(all);
    }
    /**
    * 页面列表分页查询
    * @param page 当前页码
    * @param size 页面显示个数
    * @param queryPageRequest 查询条件
    * @return 页面列表
    */
    public QueryResponseResult findList(int page,int size,QueryPageRequest 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);
    //页码
    page = page‐1;
    //分页对象
    Pageable pageable = new PageRequest(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.4 测试
    使用SwaggerUI测试
    1.3 前端
    1.3.1 页面
    1、增加查询表单
    2、数据模型对象
    增加siteList、pageAliase、siteId,如下:
    <!‐‐查询表单‐‐>
    <el‐form :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="width: 100px"></el‐input>
    <el‐button type="primary" v‐on:click="query" size="small">查询</el‐button>
    </el‐form>
    data() {
    3、在钩子方法中 构建siteList站点列表
    1.3.2 Api调用
    1、向服务端传递查询条件,修改 cms.js,如下:
    2、页面调用api方法
    return {
    siteList:[],//站点列表
    list:[],
    total:50,
    params:{
    siteId:'',
    pageAliase:'',
    page:1,//页码
    size:2//每页显示个数
    }
    }
    }
    mounted() {
    //默认查询页面
    this.query()
    //初始化站点列表
    this.siteList = [
    {
    siteId:'5a751fab6abb5044e0d19ea1',
    siteName:'门户主站'
    },
    {
    siteId:'102',
    siteName:'测试站'
    }
    ]
    }
    //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/value对
    let query = querystring.stringify(params)
    return http.requestQuickGet(apiUrl+'/cms/page/list/'+page+'/'+size+'/?'+query)
    }
    测试如下:
    2 新增页面
    2.1 新增页面接口定义
    1、定义响应模型
    2、定义添加Api
    在api工程中添加接口:
    2.2 新增页面服务端开发
    //查询
    query:function () {
    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
    })
    }
    @Data
    public class CmsPageResult extends ResponseResult {
    CmsPage cmsPage;
    public CmsPageResult(ResultCode resultCode,CmsPage cmsPage) {
    super(resultCode);
    this.cmsPage = cmsPage;
    }
    }
    @ApiOperation("添加页面")
    public CmsPageResult add(CmsPage cmsPage);
    2.2 新增页面服务端开发
    2.2.1 页面唯一索引
    在cms_page集中上创建页面名称、站点Id、页面webpath为唯一索引
    2.2.2 Dao
    1、添加根据页面名称、站点Id、页面webpath查询页面方法,此方法用于校验页面是否存在
    2、使用 CmsPageRepository提供的save方法 。
    2.2.3 Service
    2.2.4 Controller
    2.2.5 接口测试
    使用postman测试
    public interface CmsPageRepository extends MongoRepository<CmsPage,String> {
    //根据页面名称、站点id、页面访问路径查询
    CmsPage findByPageNameAndSiteIdAndPageWebPath(String pageName,String siteId,String
    pageWebPath);
    。。。
    //添加页面
    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);
    //返回结果
    CmsPageResult cmsPageResult = new CmsPageResult(CommonCode.SUCCESS,cmsPage);
    return cmsPageResult;
    }
    return new CmsPageResult(CommonCode.FAIL,null);
    }
    //添加页面
    @Override
    @PostMapping("/add")
    public CmsPageResult add(@RequestBody CmsPage cmsPage) {
    return pageService.add(cmsPage);
    }
    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",
    "pageWebPath": "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模块的路由文件中配置“添加页面”的路由:
    注意:由于“添加页面”不需要显示为一个菜单,这里hidden设置为true隐藏菜单。
    测试,在浏览器地址栏输入http://localhost:11000/#/cms/page/add
    3、在页面列表添加“添加页面”的按钮
    实际情况是用户进入页面查询列表,点击“新增页面”按钮进入新增页面窗口。
    在查询按钮的旁边添加:
    说明:router-link是vue提供的路由功能,用于在页面生成路由链接,最终在html渲染后就是<a标签。
    to:目标路由地址
    4、完善页面内容:
    代码如下:
    {path:'/cms/page/add',name:'新增页面',component: page_add,hidden:true}
    <router‐link class="mui‐tab‐item" :to="{path:'/cms/page/add/'}">
    <el‐button type="primary" size="small">新增页面</el‐button>
    </router‐link>
    <el‐form :model="pageForm" label‐width="80px" >
    <el‐form‐item label="所属站点" prop="siteId">
    <el‐select v‐model="pageForm.siteId" placeholder="请选择站点">
    <el‐option
    Form Attributes说明:
    model 表单数据对象
    rules 表单验证规则
    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="类型">
    <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 type="primary" @click="addSubmit" >提交</el‐button>
    </div>
    Form-Item Attributes说明:
    prop 表单域 model 字段,在使用 validate、resetFields 方法的情况下,该属性是必填的
    label 标签文本
    详情属性及事件参考http://element.eleme.io/#/zh-CN/component/form
    5、数据对象
    6、站点及模板数据(先使用静态数据)
    在created钩子方法中定义,created是在html渲染之前执行,这里推荐使用created。
    data(){
    return {
    //站点列表
    siteList:[],
    //模版列表
    templateList:[],
    //新增界面数据
    pageForm: {
    siteId:'',
    templateId:'',
    pageName: '',
    pageAliase: '',
    pageWebPath: '',
    pageParameter:'',
    pagePhysicalPath:'',
    pageType:'',
    pageCreateTime: new Date()
    }
    }
    },
    methods:{
    addSubmit(){
    alert("提交")
    }
    }
    created:function(){
    //初始化站点列表
    this.siteList = [
    {
    siteId:'5a751fab6abb5044e0d19ea1',
    siteName:'门户主站'
    },
    {
    siteId:'102',
    7、测试预览
    新增页面按钮:
    新增页面表单:
    2.3.1.2 添加返回
    进入新增页面后只能通过菜单再次进入页面列表,可以在新增页面添加“返回”按钮,点击返回按钮返回到页面列
    表。
    1) 新增页面按钮带上参数
    siteName:'测试站'
    }
    ]
    //模板列表
    this.templateList = [
    {
    templateId:'5a962b52b00ffc514038faf7',
    templateName:'首页'
    },
    {
    templateId:'5a962bf8b00ffc514038fafa',
    templateName:'轮播图'
    }
    ]
    }
    <router‐link class="mui‐tab‐item" :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/list', query: {
    page: this.$route.query.page,
    siteId:this.$route.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(表单验证规则)
    在数据模型中配置校验规则:
    更多的校验规则参考http://element.eleme.io/#/zh-CN/component/form中“表单验证”的例子。
    2、点击提交按钮触发校验
    1)在form表单上添加 ref属性(ref="pageForm")在校验时引用此表单对象
    2)执行校验
    <el‐form :model="pageForm" :rules="pageFormRules" label‐width="80px" >
    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'}
    ]
    }
    <el‐form :model="pageForm" :rules="pageFormRules" label‐width="80px" ref="pageForm">
    2.3.2 Api调用
    1、在cms.js中定义page_add方法。
    2、添加事件
    本功能使用到两个UI组件:
    1、使用element-ui的message-box组件弹出确认提交窗口(http://element.eleme.io/#/zh-
    CN/component/message-box)。
    2、使用 message组件提示操作结果 (http://element.eleme.io/#/zh-CN/component/message)
    完整的代码如下:
    this.$refs.pageForm.validate((valid) => {
    if (valid) {
    alert('提交');
    } else {
    alert('校验失败');
    return false;
    }
    })
    /*页面添加*/
    export const page_add = params => {
    return http.requestPost(apiUrl+'/cms/page/add',params)
    }
    this.$confirm('确认提交吗?', '提示', {}).then(() => {})
    this.$message({
    message: '提交成功',
    type: 'success'
    })
    addSubmit(){
    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: '提交成功',
    下边是测试:
    1、进入页面列表页面
    2、点击“增加页面”按钮
    3、输入页面信息点击“提交”
    3 修改页面
    type: 'success'
    });
    this.$refs['pageForm'].resetFields();
    }else{
    this.$message.error('提交失败');
    }
    });
    });
    }
    });
    }
    3 修改页面
    修改页面用户操作流程:
    1、用户进入修改页面,在页面上显示了修改页面的信息
    2、用户修改页面的内容,点击“提交”,提示“修改成功”或“修改失败”
    3.1 修改页面接口定义
    修改页面需要定义的API如下:
    说明:提交数据使用post、put都可以,只是根据http方法的规范,put方法是对服务器指定资源进行修改,所以这
    里使用put方法对页面修改进行修改。
    3.2 修改页面服务端开发
    3.2.1Dao
    使用 Spring Data提供的fifindById方法完成根据主键查询 。
    使用 Spring Data提供的save方法完成数据保存 。
    3.2.2Service
    @ApiOperation("通过ID查询页面")
    public CmsPage findById(String id);
    @ApiOperation("修改页面")
    public CmsPageResult edit(String id,CmsPage cmsPage);
    //根据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
    3.2.3Controller
    1、根据id查询页面
    2、保存页面信息
    3.3 修改页面前端开发
    3.3.1 页面处理流程
    页面的处理流程如下:
    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);
    }
    @Override
    @GetMapping("/get/{id}")
    public CmsPage findById(@PathVariable("id") String id) {
    return pageService.getById(id);
    }
    @Override
    @PutMapping("/edit/{id}")//这里使用put方法,http 方法中put表示更新
    public CmsPageResult edit(@PathVariable("id") String id, @RequestBody CmsPage cmsPage) {
    return pageService.update(id,cmsPage);
    }
    1、进入页面,通过钩子方法请求服务端获取页面信息,并赋值给数据模型对象
    2、页面信息通过数据绑定在表单显示
    3、用户修改信息点击“提交”请求服务端修改页面信息接口
    3.3.3 修改页面
    3.3.3.1 编写page_edit页面
    修改页面的布局同添加页面,可以直接复制添加页面,在添加页面基础上修改。
    下边编写页面内容:
    1、编写page_edit.vue
    页面布局同添加页面,略。
    2、配置路由
    进入修改页面传入pageId
    3、在页面列表添加“编辑”链接
    参考table组件的例子,在page_list.vue上添加“操作”列
    编写edit方法
    import page_edit from '@/module/cms/page/page_edit.vue';
    { path: '/cms/page/edit/:pageId', name:'修改页面',component: page_edit,hidden:true},
    <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:function (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方法
    2、定义数据对象
    进入修改页面传入pageId参数,在数据模型中添加pageId。
    data(){
    return {
    ......
    //页面id
    pageId:'',
    ......
    }
    }
    3、在created钩子方法 中查询页面信息
    /*页面查询*/
    export const page_get = id => {
    return http.requestQuickGet(apiUrl+'/cms/page/get/'+id)
    }
    7、预览页面回显效果
    3.3.4 Api调用
    1、定义api方法
    2、提交按钮方法
    添加提交按钮事件:
    created: function () {
    //页面参数通过路由传入,这里通过this.$route.params来获取
    this.pageId=this.$route.params.pageId;
    //根据主键查询页面信息
    cmsApi.page_get(this.pageId).then((res) => {
    console.log(res);
    if(res.success){
    this.pageForm = res.cmsPage;
    }
    });
    }
    /*页面修改,采用put方法*/
    export const page_edit = (id,params) => {
    return http.requestPut(apiUrl+'/cms/page/edit/'+id,params)
    }
    <el‐button type="primary" @click="editSubmit" >提交</el‐button>
    3、提交按钮事件内容:
    4、测试
    修改页面信息,点击提交。
    4 删除页面
    用户操作流程:
    1、用户进入用户列表,点击“删除”
    2、执行删除操作,提示“删除成功”或“删除失败”
    4.1 删除页面接口定义
    4.2 删除页面服务端开发
    editSubmit(){
    this.$refs.pageForm.validate((valid) => {
    if (valid) {
    this.$confirm('确认提交吗?', '提示', {}).then(() => {
    cmsApi.page_edit(this.pageId,this.pageForm).then((res) => {
    console.log(res);
    if(res.success){
    this.$message({
    message: '修改成功',
    type: 'success'
    });
    //自动返回
    this.go_back();
    }else{
    this.$message.error('修改失败');
    }
    });
    });
    }
    });
    }
    @ApiOperation("通过ID删除页面")
    public ResponseResult delete(String id);
    4.2 删除页面服务端开发
    4.2.1Dao
    使用 Spring Data提供的deleteById方法完成删除操作 。
    4.2.2 Service
    4.2.3Controller
    4.3 删除页面前端开发
    4.3.1 Api方法
    4.3.2编写页面
    1、在page_list.vue页面添加删除按钮
    //删除页面
    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);
    }
    @DeleteMapping("/del/{id}") //使用http的delete方法完成岗位操作
    public ResponseResult delete(@PathVariable("id") String id) {
    return pageService.delete(id);
    }
    /*页面删除*/
    export const page_del = id => {
    return http.requestDelete(apiUrl+'/cms/page/del/'+id)
    }
    <el‐table‐column label="操作" width="120">
    <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({
    type: 'success',
    message: '删除成功!'
    });
    //查询页面
    this.query()
    }else{
    this.$message({
    type: 'error',
    message: '删除失败!'
    });
    }
    })
    })
    }
    5 异常处理
    5.1 异常处理的问题分析
    从添加页面的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);
    //返回结果
    CmsPageResult cmsPageResult = new CmsPageResult(CommonCode.SUCCESS,cmsPage);
    return cmsPageResult;
    }
    return new CmsPageResult(CommonCode.FAIL,null);
    }
    问题:
    1、上边的代码只要操作不成功仅向用户返回“错误代码:11111,失败信息:操作失败”,无法区别具体的错误信
    息。
    2、service方法在执行过程出现异常在哪捕获?在service中需要都加try/catch,如果在controller也需要添加
    try/catch,代码冗余严重且不易维护。
    解决方案:
    1、在Service方法中的编码顺序是先校验判断,有问题则抛出具体的异常信息,最后执行具体的业务操作,返回成
    功信息。
    2、在统一异常处理类中去捕获异常,无需controller捕获异常,向用户返回统一规范的响应信息。
    代码模板如下:
    //添加页面
    public CmsPageResult add(CmsPage cmsPage){
    //校验cmsPage是否为空
    if(cmsPage == null){
    //抛出异常,非法请求
    //...
    }
    //根据页面名称查询(页面名称已在mongodb创建了唯一索引)
    CmsPage cmsPage1 =
    cmsPageRepository.findByPageNameAndSiteIdAndPageWebPath(cmsPage.getPageName(),
    cmsPage.getSiteId(), cmsPage.getPageWebPath());
    //校验页面是否存在,已存在则抛出异常
    if(cmsPage1 !=null){
    //抛出异常,已存在相同的页面名称
    //...
    }
    cmsPage.setPageId(null);//添加页面主键由spring data 自动生成
    CmsPage save = cmsPageRepository.save(cmsPage);
    //返回结果
    CmsPageResult cmsPageResult = new CmsPageResult(CommonCode.SUCCESS,save);
    return cmsPageResult;
    }
    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工程定义异常类型。
    5.3.2 异常抛出类
    package com.xuecheng.framework.exception;
    import com.xuecheng.framework.model.response.ResultCode;
    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;
    }
    }
    package com.xuecheng.framework.exception;
    import com.xuecheng.framework.model.response.ResultCode;
    public class ExceptionCast {
    //使用此静态方法抛出自定义异常
    public static void cast(ResultCode resultCode){
    throw new CustomException(resultCode);
    }
    }
    5.3.3 异常捕获类
    使用 @ControllerAdvice和@ExceptionHandler注解来捕获指定类型的异常
    5.3.4异常处理测试
    5.3.4.1定义错误代码
    每个业务操作的异常使用异常代码去标识。
    package com.xuecheng.framework.domain.cms.response;
    import com.xuecheng.framework.model.response.ResultCode;
    import lombok.ToString;
    @ToString
    public enum CmsCode implements ResultCode {
    CMS_ADDPAGE_EXISTS(false,24001,"页面已存在!");
    //操作结果
    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;
    @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 : {}\r\nexception: ",e.getMessage(), e);
    ResultCode resultCode = e.getResultCode();
    ResponseResult responseResult = new ResponseResult(resultCode);
    return responseResult;
    }
    }
    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_EXISTS);
    }
    2、启动工程,扫描到异常捕获的类ExceptionCatch
    在springBoot的启动类中添加
    @ComponentScan(basePackages="com.xuecheng.framework")//扫描common工程下的类
    3、前端展示异常信息
    服务端响应信息如下:
    页面提取异常处理
    5.4 不可预知异常处理
    5.4.1 定义异常捕获方法
    5.4.1.1 异常抛出测试
    使用postman测试添加页面,不输入cmsPost信息,提交,报错信息如下:
    addSubmit(){
    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'].resetFields();
    }else if(res.message){
    this.$message.error(res.message);
    }else{
    this.$message.error('提交失败');
    }
    });
    });
    }
    });
    }
    org.springframework.http.converter.HttpMessageNotReadableException
    此异常是springMVC在进行参数转换时报的错误。
    具体的响应的信息为:
    上边的响应信息在客户端是无法解析的。
    在异常捕获类中添加对Exception异常的捕获:
    5.4.1.2 异常捕获方法
    针对上边的问题其解决方案是:
    1、我们在map中配置HttpMessageNotReadableException和错误代码。
    2、在异常捕获类中对Exception异常进行捕获,并从map中获取异常类型对应的错误代码,如果存在错误代码则返
    回此错误,否则统一返回99999错误。
    具体的开发实现如下:
    1、在通用错误代码类CommCode中配置非法参数异常
    2、在异常捕获类中配置 HttpMessageNotReadableException 为非法参数异常。
    异常捕获类代码如下:
    {
    "timestamp": 1528712906727,
    "status": 400,
    "error": "Bad Request",
    "exception": "org.springframework.http.converter.HttpMessageNotReadableException",
    "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.C
    msPage)",
    "path": "/cms/page/add"
    }
    @ExceptionHandler(Exception.class)
    @ResponseBody
    public ResponseResult exception(Exception exception){
    //记录日志
    LOGGER.error("catch exception:{}",exception.getMessage());
    return null;
    }
    INVALID_PARAM(false,10003,"非法参数!"),
    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 Administrator
    * @version 1.0
    * @create 2018‐06‐11 17:16
    **/
    @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();
    //捕获Exception异常
    @ResponseBody
    @ExceptionHandler(Exception.class)
    public ResponseResult exception(Exception e) {
    LOGGER.error("catch exception : {}\r\nexception: ",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;
    }
    //捕获 CustomException异常
    @ExceptionHandler(CustomException.class)
    @ResponseBody
    public ResponseResult customException(CustomException e) {
    LOGGER.error("catch exception : {}\r\nexception: ",e.getMessage(), e);
    ResultCode resultCode = e.getResultCode();
    ResponseResult responseResult = new ResponseResult(resultCode);
    return responseResult;
    }
    5.4.3 异常处理测试
    仍然模拟“问题测试”中的测试步骤,异常结果为“非法参数”。
    6 实战
    此部分为自学内容,根据今天所学知识完成下边的任务。
    6.1 查询条件完善
    页面查询条件增加:页面名称、页面类型。
    页面名称对应CmsPage模型类中的pageName属性。
    页面类型对应CmsPage模型类中的pageType属性。
    查询要求:
    页面名称:模糊查询
    页面类型:精确匹配,页面类型包括:静态和动态,在数据库中静态用“0”表示,动态用“1”表示。
    6.2 页面属性增加DataUrl
    在CmsPage.java模型类型中有一个dataUrl属性,此属性在页面静态化时需要填写。
    本需求要求:
    1、在新增页面增加dataUrl输入框,并支持添加。
    2、在修改页面增加dataUrl输入框,并支持修改。
    static{
    //在这里加入一些基础的异常类型判断
    builder.put(HttpMessageNotReadableException.class,CommonCode.INVALIDPARAM);
    }
    }

    展开全文
  • 命令完成后生成 将这两个目录丢给后端就完事了。 不过有要求 必须要放在根目录下 也就是说 XXX:80/ 这个根目录 如果不想这样想单独建一个目录然后给访问那就需要去修改下 build: { // Template for ...

    执行

    npm run build

    命令完成后会生成

    将这两个目录丢给后端就完事了。 不过有要求  必须要放在根目录下 也就是说 XXX:80/ 这个根目录

    如果不想这样想单独建一个目录然后给访问那就需要去修改下

     

    
      build: {
        // Template for index.html
        index: path.resolve(__dirname, '../dist/index.html'),
    
        // Paths
        assetsRoot: path.resolve(__dirname, '../dist'),
        assetsSubDirectory: 'static',
    // 目录名
        assetsPublicPath: '/XXX',
        // assetsPublicPath: '/',
    
        /**
         * Source Maps

    然后重新打包 然后丢给后台  然后访问就是XXX/XXX了

     

    展开全文
  • 正开发过程中 前后端分离或者不分离 ,接口多半是之后与...首先必须有node环境(都用到json-server一定有node环境吧)然后全局安装json-server npm install json-server -g 安装完成后检查是否全局安装成功 G:\demo
  • 作为一名后端程序员,我们通常专注于后端代码开发,当然也涉及到一些常用前端脚本语言框架,像jquery(逐步被淘汰),偶尔也写一些css样式。可以说除了UI之外,我们什么都做。但是这些放在今天是远远不够的,...
  • windows的IIS上发布部署项目(vue前端+python后端项目)项目需求项目实现效果展示 项目需求 项目中使用python作为后端并且习惯使用IIS,所以顺理成章的需要将项目发布到IIS上。查看网上的许多部署指南,还是有一些...
  • 问题1前端访问不到后端页面配置问题 response.addHeader(“x-frame-options”, “...必须了解每一个配置的意思,不能乱粘网上的代码,这个需要花时间去整理,稍后我在别的博客详细整理 问题2自定义的文件,访问不...
  • 但是,如果你必须经常在框架之间切换,在深入探讨另一个框架之后,你可能轻易忘记另一个框架中的语法。在本文中,我总结了这些框架的基本语法和方案,然后并排列出。我希望这可以帮助我们尽快掌握语法,不过限于...
  • 前端开发入门很简单,HTML,CSS和JS是前端学习的三个基础,如果要进步,还必须学习H5,C3,Node,Ajax,Vue.js等, 后端技术,学习的广度和深度都不小。首先,您需要精通一种编程语言,例如Java是一个不错的选择,...
  • VUE+js项目改为VUE+TypeScript 吐槽:不仅要学VUE,还要用TypeScript,对于一个后端,听都没听过好吗;项目都前后端分离了,连个前端工程师都懒得招...// ts-loader typescript 必须安装,其他的相信你以后也装上的 np
  • : { // 设置提示信息国际化, 此处需要注意地址, 否则导致地址栏重新请求 "sUrl": "/theme/js/jquery.pager.cn.txt" }, /<em> 分页请求start==== </em>/ "bServerSide"...
  • vue-cli小记录

    2020-03-30 16:32:29
    vue-cli小记录方便操作打包时选择环境设置代理(vue运行代理,和nginx代理,解决跨域)vue-cli开启压缩,后端也开启压缩 方便操作打包时选择环境 1.可以为特定的环境准备不同的文件.必须以**.env **开头的文件.这样才能被...
  • 首先把后端的服务搭好,方便以后前端调用,使用npm安装express,mongoose等必须的依赖即可,暂时不考虑验证等东西. npm install express body-parser mongoose --save 然后在项目根目录添加一个app.js,编写好启动express...
  • 我想,像我一样刚接触VUE后端小白一定很疑惑:我是想用vue的前端框架,为啥一百度都是安装node.js还有什么npm 其实你不妨可以理解成要运行java代码必须安装jdk一样,那么node.js就是vue的JavaScript的运行环境,...
  • 上面的模块不可以使用import来导入,必须使用require,同时需要通过npm安装babel-core、babel-preset-es2015、babel-preset-stage-0、babel-polyfill等依赖。这样就可以愉快地使用import/export了。 服务端代码片段...
  • Vue 进阶之技术实战

    2020-08-03 02:50:20
    Vue 可谓是开启了后端程序员的新时代,简单易学的语法知识、前后端分离的开发模式以及各种各样的组件、插件使其成为了实现快速、高效开发的有效手段之一。 而如何更加简单、简便的使用 Vue,减少重复代码、提高代码...
  • vue基础总结

    2021-03-18 18:13:01
    mvc:后端概念,model和view和controller; mvvm:前端的概念,model(data部分)和vm(双向数据绑定控制)和view(html代码部分) 插值表达式 v-if的值为false的时候,在html树结构中消失 v-show的值为false的时候,...
  • 自己做vue项目时出现的问题:登陆完成后,服务器保存了session信息,consule.log输出req.session也有登陆信息,但是登陆完切从登陆页面切换主页面时,显示我未登陆(后端是我自己写的,加了个登陆验证) ...
  • Vue 微信h5支付

    2020-03-14 17:46:18
    是因为权限的问题,商户平台申请h5支付时填写产品域名,请求后端支付接口时必须与产品域名一样,这样跳转后是在产品域名下请求mwebUrl, 如果不是在这个指定的产品域名下还是出现“商家参数格式有误,请联系商家...
  • 在设计好这些步骤之后,在进行UI的设计,在对比UI图的时候,每个图上的每个功能必须与产品所提的需求一致 例如,此时我们需要完成一个[弹窗]组件 点击详情的时候,显示弹窗, 得到需求后,我们要确认,[弹窗]的样式...
  • vue跨域访问spring rest服务

    千次阅读 2017-07-18 15:10:57
    vue跨域访问spring rest服务使用前后端分离的方式去做,就遇到跨域访问的问题。默认情况下,js访问都必须是同域访问,这是为了安全考虑。那么跨域要怎么解决呢? 后端服务我们这里使用spring来提供后端服务。然后...
  • 前端vue通过axios调用java接口,用的是springboot+jwt,用post请求的时候,headers里带了个token,请求的时候变成options,然后报401。网上找了一下说这是...回答跨域请求先发option请求所以后端必须能够处理...
  • 项目开始都是默认的json格式传输 后端加了权限认证(security)之后过滤器只能接收表单数据 做不到像控制器一般灵活,所以在前端vue的使用中必须能够切换为表单传输 但是我将头headers换位了表单格式 后端却还是接收不...
  • 请求的url地址,必须与浏览器上的url地址处于同域上,也就是域名,端口,协议相同。否则就抛出跨域错误哦~ 在传统的JQuery项目里面,后端给一个callback函数,然后前端用jsonp来处理。 或者后端将header设置为 * 来...
  • 首先Vue作为国内主流的前后端分离框架,不管是作为前端后端开发,还是准备转型成为测试开发的技术人员都是必须掌握的,平时忙于工作和陪对象没错我有对象不是new的,记录下学习的过程,防止忘记~ 1.安装教程 vue的...
  • 1 hash 模式下,仅 hash 符号之前的内容被包含在请求中,如 http://www.abc.com,因此对于后端来说,即使没有做到对路由的全覆盖,也不会返回 404 错误。 2 history 模式下,前端的 URL 必须和实际向后端发起请求...
  • 代码中, 我们发现一个问题, 在 handler.php 中 异常信息是返回的, 官方文档中有介绍, **使用异常处理接管的函数必须返回一个 response 响应, 所以可以看到 在 BaseException 中 设置了 is_anomaly_andling_take...
  • Vue动态绑定属性和动态获取属性值

    千次阅读 2020-07-09 21:18:16
    基本不用写前端了,虽然Vue不太,Jquery还是点的,Jquery可以动态绑定设定值,作为Vue这么牛逼优秀的框架,不支持动态绑定?我今天快被合作的前端小哥给气到了,不行必须得写出来,太气人了,做后端的帮你搞定...

空空如也

空空如也

1 2 3 4 5
收藏数 98
精华内容 39
关键字:

后端必须会vue

vue 订阅