https://www.cnblogs.com/lovejune/p/java_login_1.html

上一章内容搭建起了登录应用场景的环境,模拟实现了登录操作,页面与后端数据的交互过程,使用的是异步的ajax请求实现。

在LoginController中,我们实现了对数据的简单校验,但事实上,在实际开发中,我们不可能使用这么繁琐的校验代码。校验过程,交给javax.validation.Valid类来实现。

下面将研究javax.validation.Valid的原理和使用方法。

  • @Valid注解

  用于校验的注解,所属包为javax.validation.Valid,

在LoginController类中修改如下代码

@RequestMapping("/do_login")
@ResponseBody
public Result<Boolean> dologin(HttpServletResponse response, @Valid Person person, BindingResult bindingResult){ System.out.println(person);
if(bindingResult.hasErrors()){
System.out.println(bindingResult.getFieldError().getDefaultMessage());
return null;
} Result<Boolean> result = userService.login(person); return result;
}

BindingResult类是跟在@Valid后面的结果类,若校验出错,该对象会返回出错信息。但这样的代码仍然比较繁琐,且无法与我们自定义的结果类相关联。

在参数中去掉BindingResult bindingResult,运行程序,发现执行ajax的error里面的代码,所以请求出错了,推测这是因为@Valid验证不通过会在内部报错,如果没有BindingResult ,将报错,此刻,需要引入spring中的异常管理。

接下来,使用@ControllerAdvice注解来统一处理异常,该注解是@Controller注解的增强,当将异常抛到controller时,可以对异常进行统一处理,规定返回的json格式或是跳转到一个错误页面。

  • 自定义异常类

定义一个全局异常类,将所有的异常都交给controller来处理

public class GobalException extends RuntimeException {

    private Integer code;
private String Msg; @Override
public String toString() {
return "GobalException{" +
"code=" + code +
", Msg='" + Msg + '\'' +
'}';
} public Integer getCode() {
return code;
} public void setCode(Integer code) {
this.code = code;
} public String getMsg() {
return Msg;
} public void setMsg(String msg) {
Msg = msg;
}
}
  • 修改自定义的结果类

package com.liuxinghang.result;

public class Result {

    private Integer code;
private String Msg; //定义构造方法 public Result(Integer code,String Msg){
this.code=code;
this.Msg=Msg;
} public Result(){ } //定义静态属性拿值
public static Result NOPERSON=new Result(0,"查无此人"); public static Result ERRORPASS=new Result(01,"密码错误"); public static Result SUCCESS=new Result(1,"登录成功"); public static Result SEVERERROR=new Result(000,"服务器异常"); public static Result error(Integer code,String Msg){
return new Result(code,Msg);
} @Override
public String toString() {
return "Result{" +
"code=" + code +
", Msg='" + Msg + '\'' +
'}';
} public Integer getCode() {
return code;
} public void setCode(Integer code) {
this.code = code;
} public String getMsg() {
return Msg;
} public void setMsg(String msg) {
Msg = msg;
} }

该结果类虽然修改了,但仍然有很多瑕疵,可以进一步抽象。

  • 异常处理类

@ControllerAdvice
@ResponseBody //出现异常,将异常信息通过response返回
public class GlobalExceptionHandler { @ExceptionHandler(value = Exception.class)
public Result exceptionHandle(HttpServletResponse response,Exception e){
e.printStackTrace(); //判断异常类型
if(e instanceof GobalException){
System.out.println("GobalException异常");
return new Result(((GobalException) e).getCode(),((GobalException) e).getMsg());
}else if(e instanceof BindException){
System.out.println("BindException异常");
BindException ex = (BindException)e;
List<ObjectError> errors = ex.getAllErrors();
ObjectError error = errors.get(0);
String msg = error.getDefaultMessage();
return new Result(123,msg);
}else {
return Result.SEVERERROR;
}
}
}

总结来说,异常处理类,通过注解@ControllerAdvice和@ResponseBody 以及@ExceptionHandler(value = Exception.class)使得所有的异常统一进行处理,并通过response来返回异常消息,也可以通过渲染页面,返回到错误的页面中。

到此,我们已经了解了登录时对消息验证的交互逻辑,接下来,探索如何自定义验证规则,来完成我们自己数据的验证,用户通过手机号来进行登录,可以验证手机号码是否符合规则,比如,手机号为11位,而且第一个数字一定为1。

  • ValidatorUtil类,定义isMobile方法

 此类通过一个pattern类对传来的数据进行正则约束,返回一个布尔类型

public class ValidatorUtil {

    private static Pattern MOBILE_PATTERN = Pattern.compile("1\\d{10}");

    public static boolean isMobile(String mobile){
if(StringUtils.isEmpty(mobile)){
return false;
}
Matcher matcher=MOBILE_PATTERN.matcher(mobile);
return matcher.matches();
}
}

该类通过对手机号码的格式提出一定要求,符合返回true,不符合返回false

  • IsMobile注解的自定义

自定义注解只需创建一个接口,在interface前加个@,java有四个元注解,来规定注解的使用范围,文档等。

@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER })
@Retention(RUNTIME)
@Documented
@Constraint(validatedBy = {IsMobileValidator.class }) //处理自定义规则的逻辑 public @interface IsMobile { boolean required() default true;
String message() default "手机号码格式错误";
//分组
Class<?> [] groups() default {};
//负载
Class<? extends Payload> [] payload() default {};
}

@Constraint(validatedBy = {IsMobileValidator.class }) //处理自定义规则的逻辑,

IsMobileValidator来自定义的处理格式的逻辑代码,该类必须继承ConstraintValidator接口,来实现方法。该接口有两个参数,一个是校验逻辑的类,一个是待校验的属性的参数。

public class IsMobileValidator implements ConstraintValidator<IsMobile,String> {

    private boolean required=false;

    @Override
public void initialize(IsMobile isMobile) {
required=isMobile.required();
} @Override
public boolean isValid(String s, ConstraintValidatorContext constraintValidatorContext) {
if(required){
return ValidatorUtil.isMobile(s);
}else if(StringUtils.isEmpty(s)){
return true;
}else {
return ValidatorUtil.isMobile(s);
}
}
}

到现在为止,我们自己定义了一个校验的规则IsMobile,判断手机号是不是1开头的十一位数字。

  • 测试

可以得到BindException传回的消息与定义的消息一致。


接下来,针对网络中密码传播不安全的需求,对密码进行加密。

密码加密对于登录场景有着重要的意义,原则是,明文密码不能在网络上传播,因此,需要在客户端就对密码进行加密,使用md5算法进行加密。该算法的加密过程是固定的,需要加入随机盐来增加不确定性。

  • 修改login.html页面

 function login(){
var inputPass=$("#password").val();
var salt = "1a2b3c4d";
var str = ""+salt.charAt(0)+salt.charAt(2) + inputPass +salt.charAt(5) + salt.charAt(4);
var password = md5(str); $.ajax({
url: "/login/do_login",
type: "POST",
data:{
mobile:$("#mobile").val(),
password: password
},
success:function(data){
alert(data.code+"+"+data.msg+"+"+data.date);
},
error:function(){
alert("错误")
}
});
}

对客户端输入的密码进行加密。

在服务端拿到密码后,再进行加密,二次加密后的密码存到数据库中,以防止进行密码反查而得到确定的密码。

  • Md5Util类

public class Md5Util {
private static String SALT="1a2b3c4d"; //md5加密
private static String md5(String pass){
return DigestUtils.md5Hex(pass);
} //加密
public static String dbPass2FormPass(String dbPass){
String src=""+SALT.charAt(0)+SALT.charAt(2)+dbPass+SALT.charAt(5)+SALT.charAt(4);
return md5(src);
} }

到这里,前端和服务器的交互已经大致完成,剩下的是一些耦合性太高的代码需要重新设计。

下面将开始探究服务器和数据库的交互,包括Mysql数据库和Redis数据库。

 
 

java初探(1)之登录再探的更多相关文章

  1. 再探java基础——break和continue的用法

    再探java基础——break和continue的用法 break break可用于循环和switch...case...语句中. 用于switch...case中: 执行完满足case条件的内容内后 ...

  2. ViewPager+Fragment再探:和TAB滑动条一起三者结合

    Fragment前篇: <Android Fragment初探:静态Fragment组成Activity> ViewPager前篇: <Android ViewPager初探:让页面 ...

  3. 【再探backbone 02】集合-Collection

    前言 昨天我们一起学习了backbone的model,我个人对backbone的熟悉程度提高了,但是也发现一个严重的问题!!! 我平时压根没有用到model这块的东西,事实上我只用到了view,所以昨 ...

  4. [老老实实学WCF] 第五篇 再探通信--ClientBase

    老老实实学WCF 第五篇 再探通信--ClientBase 在上一篇中,我们抛开了服务引用和元数据交换,在客户端中手动添加了元数据代码,并利用通道工厂ChannelFactory<>类创 ...

  5. 再探ASP.NET 5(转载)

    就在最近一段时间,微软又有大动作了,在IDE方面除了给我们发布了Viausl Studio 2013 社区版还发布了全新的Visual Studio 2015 Preview. Visual Stud ...

  6. 第四节:SignalR灵魂所在Hub模型及再探聊天室样例

    一. 整体介绍 本节:开始介绍SignalR另外一种通讯模型Hub(中心模型,或者叫集线器模型),它是一种RPC模式,允许客户端和服务器端各自自定义方法并且相互调用,对开发者来说相当友好. 该节包括的 ...

  7. 深入出不来nodejs源码-内置模块引入再探

    我发现每次细看源码都能发现我之前写的一些东西是错误的,去改掉吧,又很不协调,不改吧,看着又脑阔疼…… 所以,这一节再探,是对之前一些说法的纠正,另外再缝缝补补一些新的内容. 错误在哪呢?在之前的初探中 ...

  8. 强连通分量再探 By cellur925

    我真的好喜欢图论啊. (虽然可能理解的并不深hhh) 上一次(暑假)我们初探了强联通分量,这一次我们再探.(特别感谢pku-lyc老师的课件.有很多引用) 上次我们忘记讨论复杂度了.tarjan老爷爷 ...

  9. 再探快速傅里叶变换(FFT)学习笔记(其三)(循环卷积的Bluestein算法+分治FFT+FFT的优化+任意模数NTT)

    再探快速傅里叶变换(FFT)学习笔记(其三)(循环卷积的Bluestein算法+分治FFT+FFT的优化+任意模数NTT) 目录 再探快速傅里叶变换(FFT)学习笔记(其三)(循环卷积的Blueste ...

随机推荐

  1. c++日志工具spdLog

    c++日志工具spdLog简单使用示例代码 spdlog直接引用头文件就可以使用,这一点还是比较方便的,也是刚入门使用,下面是在源码的示例代码基础上修改测试的代码: #include <cstd ...

  2. 畅购商城(八):微服务网关和JWT令牌

    好好学习,天天向上 本文已收录至我的Github仓库DayDayUP:github.com/RobodLee/DayDayUP,欢迎Star,更多文章请前往:目录导航 畅购商城(一):环境搭建 畅购商 ...

  3. 六种酷炫Python运行进度条

    本文介绍了目前6种比较常用的进度条,让大家都能直观地看到脚本运行最新的进展情况 很多人学习python,不知道从何学起.很多人学习python,掌握了基本语法过后,不知道在哪里寻找案例上手.很多已经做 ...

  4. 比原Bapp红包应用

    喜迎国庆期间,比原链在自己的移动端钱包Bycoin(下载地址)和google插件钱byone中推出了红包应用,在国庆期间深受大家好评. 那我们今天就来大概介绍一下比原红包,以及基于比原链开发dapp应 ...

  5. 树莓派4B的CPU系统里查到为BCM2835而非BCM2711

    树莓派4B采用四核64位的ARM Cortex-A72架构CPU,型号为博通BCM2711 SoC.2711是个64位的四核,而2835是多年前的32位单核CPU. 查看当前芯片版本,显示为4核心,但 ...

  6. Java编译解释之cmd

    一.编译 1. javac 类名.java (在类当前目录下) 2. javac 类的全路径 二.解释 1. java 类名(在类当前目录下) 2. java -cp 类的当前目录路径 类名

  7. CSS概述(二)

    目录 CSS背景属性 设置背景颜色 background-color 设置背景图像 background-image 设置背景重复 background-repeat 设置背景定位 backgroun ...

  8. 详解POW工作量证明原理

    原文地址  来自 微信公众号 区块链大师 POW工作量证明(英文全称为Proof of Work)早在比特币出现之前就已经有人探索,常见的是利用HASH运算的复杂度进行CPU运算实现工作量确定,当然你 ...

  9. Go 编译器内部知识:向 Go 添加新语句-第 2 部分

    这是探讨 Go 编译器两篇文章的最后一篇.在第 1 部分中,我们通过构建自定义的编译器,向 Go 语言添加了一条新语句.为此,我们按照此图介绍了编译器的前五个阶段: 在"rewrite AS ...

  10. 修改linux 动态ip为静态ip

    vi /etc/sysconfig/network-scripts/ifcfg-ens33 BOOTPROTO=static 设置网卡引导协议为 静态 ONBOOT=yes 网卡开机自启动 配置[IP ...