spring+springMVC+mybatis的整合 part7

为了程序执行效率、数据完整性和程序健壮性,我们的前端必须做对应的基础数据效验,后端的控制器必须做所有需要的数据的效验。

前端数据效验我们使用js完成,界面样式是由CSS完成,网络请求采用异步请求,具体的实现是使用的ajax完成。
js获取web页面数据统一使用标签的ID,格式为:$("#标签ID")
web页面标签最好一个标签一行,这样代码看起来更加舒服
后端接口返回数据为json,前端页面解析json控制程序流转

很多时候我们要先引入相关的辅助JS
数据检验JS代码

function checkLoginInfo() {
        if ("" == $("#u").val()) {
            $("#u").tips({
                side: 2,
                msg: '用户名不得为空',
                bg: '#AE81FF',
                time: 3
            });
            $("#u").focus();
            return false;
        }
        if ($("#p").val() == "") {

            $("#p").tips({
                side: 2,
                msg: '密码不得为空',
                bg: '#AE81FF',
                time: 3
            });
            $("#p").focus();
            return false;
        }
        return true;
    }

登录的js代码

function webLogin() {
        if (checkLoginInfo()) {
            var loginname = $("#u").val();
            var password = $("#p").val();
            $.ajax({
                type: "POST",
                url: '<%=request.getContextPath()%>/userAction/login',
                data: {loginId: loginname, pwd: password},
                dataType: 'json',   //当这里指定为json的时候,获取到了数据后会自动解析的,只需要返回值.字段名称 就可以了
                cache: false,
                success: function (data) {
                    if (data.code == 1) {
                        window.location.href = data.data.nextUrl;   //拿到服务器返回的地址,然后进行跳转操作
                        //window.location.href = '<%=request.getContextPath()%>/mvc/home';    //跳转到主页*/
                    } else {
                        alert(data.msg);
                        $("#u").focus();
                    }
                }
            });
        }
    }

注册的JS代码

function webReg() {

        if ($('#user').val() == "") {
            $('#user').focus();
            $("#user").tips({
                side: 2,
                msg: '用户名不能为空',
                bg: '#AE81FF',
                time: 3
            });
            return false;
        }

        if ($('#user').val().length < 4 || $('#user').val().length > 16) {
            $('#user').focus();
            $("#user").tips({
                side: 2,
                msg: '用户名位6-16字符',
                bg: '#AE81FF',
                time: 3
            });
            return false;
        }

        if ($('#name').val().length < 2
            || $('#name').val().length > 16
            || $('#name').val() == "") {

            $('#name').focus();

            $("#name").tips({
                side: 2,
                msg: '用户姓名必须为4-16位字符',
                bg: '#AE81FF',
                time: 3
            });
            return false;
        }

        if ($('#passwd').val().length < 6) {
            $('#passwd').focus();
            $("#passwd").tips({
                side: 2,
                msg: '密码不能小于6位',
                bg: '#AE81FF',
                time: 3
            });
            return false;
        }
        if ($('#passwd2').val() != $('#passwd').val()) {
            $('#passwd2').focus();
            $("#passwd2").tips({
                side: 2,
                msg: '两次密码不一致',
                bg: '#AE81FF',
                time: 3
            });
            return false;
        }

        var sqq = /^1[34578]\d{9}$/;
        if (!sqq.test($('#phoneNumber').val())
            || $('#phoneNumber').val().length < 11
            || $('#phoneNumber').val().length > 14
            || $('#phoneNumber').val() == "") {

            $('#phoneNumber').focus();
            $("#phoneNumber").tips({
                side: 2,
                msg: '手机号不正确',
                bg: '#AE81FF',
                time: 3
            });
            return false;
        }

        if ($('#sex').val() == "") {
            $('#sex').focus();
            $("#sex").tips({
                side: 2,
                msg: '性别不能为空',
                bg: '#AE81FF',
                time: 3
            });
            return false;
        }

        if ($('#age').val() == "") {
            $('#age').focus();
            $("#age").tips({
                side: 2,
                msg: '年龄不能为空',
                bg: '#AE81FF',
                time: 3
            });
            return false;
        }

        var loginname = $("#user").val();
        var password = $("#passwd").val();
        var username = $("#name").val();
        var cellNumber = $("#phoneNumber").val();
        var sex = $("#sex").val();
        var age = $("#age").val();

        $.ajax({
            type: "POST",
            url: '<%=request.getContextPath()%>/userAction/reg',
            data: {loginId: loginname, pwd: password, name: username, sex: sex, age: age, cellNumber: cellNumber},
            dataType: 'json',   
            cache: false,
            success: function (data) {
                if (data.code == 1) {
                    window.location.href = data.data.nextUrl;
                } else {
                    alert(data.msg);
                    $("#user").focus();
                }
            }
        });
    }

上面的注释已经能很明显的看出我们的 前端效验、网络请求和js解析json,下面我们在前端页面中调用这个js,如下:

<form action=""     //此处必须删掉form表单的地址
    name="loginform"
    accept-charset="utf-8" 
    id="login_form" 
    class="loginForm"
    method="post">
        <input type="hidden" name="did" value="0"/>
        <input type="hidden" name="to" value="log"/>

        <div class="uinArea" id="uinArea">
            <label class="input-tips" for="u">帐号:</label>
            <div class="inputOuter" id="uArea">
                <input type="text" id="u" name="loginId" class="inputstyle"/>
            </div>
        </div>

        <div class="pwdArea" id="pwdArea">
            <label class="input-tips" for="p">密码:</label>
            <div class="inputOuter" id="pArea">
                <input type="password" id="p" name="pwd" class="inputstyle"/>
            </div>
        </div>

        <div style="padding-left:50px;margin-top:20px;">
            <input type="button"
               id="btn_login"
               value="登 录"
               onclick="webLogin();"    //此处调用我们上面写的js的登录方法
               style="width:150px;"
               class="button_blue"/>
        </div>
</form>

主要就是在onclick中添加js函数

前端页面:
FORM表单必须删除action的值
input type="submit"要改为input type="button"

前端页面完成后,我们必须在后端接口处,做出对应的修改,让他符合我们前端的调用规则。
后端修改如下:
登录接口,因为json数据外层一般都是Object类型,所以返回值必须是Object
如果之前返回的是ModelAndView,现在要改为Object

错误405

也许有人问,如果我不改会怎样

Paste_Image.png

这个错误的意思是
Request method 'POST' not supportedPOST方法不被允许
The method received in the request-line is known by the origin server but not supported by the target resource.不支持接收这种类型的数据
对于请求所标识的资源,不允许使用请求行中所指定的方法

如果把POST请求换成GET请求可以吗
答案是不可以的,因为登录你需要传数据到后台,所以你要用POST把数据传给后台

在网上还有人说是路径问题
不过使用绝对路径是没错的
<%=request.getContextPath()%>是为了解决相对路径的问题,可返回站点的根路径。

<%=request.getContextPath()%>/userAction/login

解决方法:
把返回的数据ModelAndView,现在要改为Object

ModelAndView就是一个map集合
一旦Controller处理完客户请求,则返回ModelAndView对象给DispatcherServlet前端控制器。ModelAndView中包含了模型(Model)和视图(View)
从宏观角度考虑,DispatcherServlet是整个Web应用的控制器;
从微观角度考虑,Controller是单个Http请求处理过程中的控制器,
ModelAndViewHttp请求过程中返回的模型和视图。前端控制器返回的视图可以是视图的逻辑名,或者实现了View接口的对象。View对象能够渲染客户响应结果。其中,ModelAndView中的模型能够供渲染View时使用。借助于Map对象能够存储模型。

通过上面的重构可以明白以下几点:
前端
js实现基本的数据效验,发起网络请求(具体实现用ajax),返回类型设置json能自动解析,获取页面控件,页面控件调用js
js获取解析后的json数据的值,进行程序流转控制
后端:
后端控制器必须申明,后端的地址必须配置,每个地址返回的数据类型要匹配,返回json数据,方法上面必须配置:@ResponseBody
可以使用工具类来方便开发

关于在HTML里引入图片,css等资源

一般采用相对路径
获取某个资源的相对路径可以这么做

Paste_Image.png

对资源点击右键→Copy Relative Path 获取相对路径

选取一个比较喜欢的后端主页,然后把对应的资源放入到对应的文件目录(js、css、images等),需要新加入的资源如果在以前的目录中没有的话,那么需要在里面进行配置。比如说这里加入了字体文件,那么现在需要先把字体文件指定目录为:

static/font/

目录指定后需要在Spring的配置文件,spring-web.xml中配置静态资源的目录如下:

<mvc:resources mapping="/fonts/**" location="/static/fonts/"/>

有文件的信息上传

关于文件上传
前端写完数据发送,后端写完controller后
还要在Spring的配置文件中添加文件的支持设置,不然无论如何都收不到文件(文件一直为null)
补充配置文件,spring-web.xml新增配置如下:

<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <!--下面设置的是上传文件的最大大小-->
        <property name="maxUploadSize" value="10000000"/>   
    </bean>

Spring接收文件上传时,Controller的具体方法的参数前面插入注解,同时数据类型是MultipartFile
js进行前端流程控制,后端接口隔离,前后端解耦。

主要参考于大牛Clone丶记忆的SSM集成之路

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,919评论 6 502
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,567评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,316评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,294评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,318评论 6 390
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,245评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,120评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,964评论 0 275
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,376评论 1 313
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,592评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,764评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,460评论 5 344
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,070评论 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,697评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,846评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,819评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,665评论 2 354

推荐阅读更多精彩内容