java+验证码,已有验证码工具类,不知道java basecontrollerr怎么写,前端页面怎么获取src位置。

JavaWeb登录页面生成数字或字母图片验证码 - CSDN博客
JavaWeb登录页面生成数字或字母图片验证码
现在大部分的登录或验证系统都拥有了字母或数字图片的验证码,自己也一时兴起,根据网上的demo自己也尝试了一下,很有意思!
下面则是这次实验的效果图:
1.登陆页jsp:
&& &&base href=&/&&
&&& &meta charset=&UTF-8&&
&&& &title&登陆页面&/title&
&&& &meta name=&viewport&
&&&&&&&&& content=&width=device-width,initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no&/&
&&& &meta http-equiv=&Content-Type& content=&text/ charset=utf-8&&
&&& &link rel=&stylesheet& href=&css/login.css&&
&&& &script language=&javascript& src=&js/jquery-1.9.0.min.js&&&/script&
&&& &script language=&javascript& src=&js/login/login.js&&&/script&
&div class=&login_form&&
&&&&&&&&&&&&&& &&& &&form name='myForm' action='' method='post' &
&& &&&&&&&&&&&&&&&&&&&&&&&& &input type=&text& name=&userName& id=&userName& placeholder=&请输入用户名&&
&& &&&&&&&&&&&&&&&&&&&&&&&& &input type=&password& name=&password& id=&password& placeholder=&请输入密码&&
&&&&&&&&&&&&&&&&&&& &/form&
&&&&&&&&&&&&&&&&&&& &input class=&check_input& type=&text&& placeholder=&请输入验证码&&
&&&&&&&&&&&&&&&&&&& &img id=&imgVerify& src=&& alt=&点击更换验证码& width=&112& height=&36& onclick=&getVerify(this);&&//首次获取验证码图片,也可在此将src设为访问路径/getVerify
&&&&&&&&&&&&&&&&&&& &div class=&login_form_warn_lable&&&/div&
&&&&&&&&&&&&&&&&&&& &div class=&login_form_warn&&
&&&&&&&&&&&&&&&&&&&&&&&&&&& &span class=&warn_text&&用户名或密码错误&/span&
&&&&&&&&&&&&&&&&&&& &/div&
&&&&&&&&&&&&&&&&&&& &div class=&login_form_submit&&
&&&&&&&&&&&&&&&&&&&&&&&&&&& &button class=&btn_submit& onclick=&login();&&登&&&录&/button&
&&&&&&&&&&&&&&&&&&& &/div&
&&&&&&&&&&&&&&& &/div&
2.登陆页面js:
$(document.body).ready(function () {
&& &//首次获取验证码
&& &$(&#imgVerify&).attr(&src&,&/getVerify?&+Math.random());
//点击登录按钮
function login(){
&&& &//校验验证码
&& &checkSum();
//提交表单
function submitForm(){
&& &document.myForm.action = &/login&;
&& &document.myForm.submit();
//获取验证码
function getVerify(obj){
&& &obj.src = &/getVerify?&+Math.random();
//校验验证码
function checkSum(){
&& &var inputStr = $(&.check_input&).val();
&& &if(inputStr!=null && inputStr!=&&){
&& &&& &inputStr = inputStr.toUpperCase();//将输入的字母全部转换成大写
&& &&& &$.ajax({
&& &&& &&& &url : &checkVerify&,
&& &&& &&& &data: {inputStr:inputStr},
&& &&& &&& &success : function(datas) {
&& &&& &&& &&& &if(datas == &T&){
&& &&& &&& &&& &&& &submitForm();//提交表单
&& &&& &&& &&& &}else{
&& &&& &&& &&& &&& &$(&.check_input&).val(&&);
&& &&& &&& &&& &&& &$(&.warn_text&).text(&验证码输入错误!&);
&& &&& &&& &&& &&& &$(&.login_form_warn&).css(&display&,&block&);
&& &&& &&& &&& &}
&& &&& &&& &}
&& &&& &});
&& &}else{
&& &&& &$(&.warn_text&).text(&请输入验证码&);
&& &&& &$(&.login_form_warn&).css(&display&,&block&);
3.(springMVC框架)java后台controller获取和校验验证码:
&&&& * 登录页面生成验证码
&&& @RequestMapping(value = &getVerify&)
&&& public void getVerify(HttpServletRequest request, HttpServletResponse response){
&& &&& &response.setContentType(&image/jpeg&);//设置相应类型,告诉浏览器输出的内容为图片 &
&&&&&&& response.setHeader(&Pragma&, &No-cache&);//设置响应头信息,告诉浏览器不要缓存此内容 &
&&&&&&& response.setHeader(&Cache-Control&, &no-cache&);
&&&&&&& response.setDateHeader(&Expire&, 0);
&&&&&&& RandomValidateCode randomValidateCode = new RandomValidateCode();
&&&&&&& try {
&&&&&&&&&&& randomValidateCode.getRandcode(request, response);//输出验证码图片方法 &
&&&&&&& } catch (Exception e) {
&&&&&&&&&&& e.printStackTrace();
&&&& * 登录页面校验验证码
&&& @RequestMapping(value = &checkVerify&)
&&& @ResponseBody
&&& public String checkVerify(String inputStr, HttpSession session){
&& &&& &//从session中获取随机数
&& &&& &String random = (String) session.getAttribute(&RANDOMVALIDATECODEKEY&);
&& &&& &if(random.equals(inputStr)){
&& &&& &&& &return &TURE&;//验证码正确
&& &&& &}else{
&& &&& &&& &return &FALSE&;//验证码错误
4.验证码图片生成工具类:
&* 验证码生成类
&* @author admin
public class RandomValidateCode {
&& &public static final String RANDOMCODEKEY= &RANDOMVALIDATECODEKEY&;//放到session中的key && &
&& &//private String randString = &&;//随机产生只有数字的字符串 private String
&& &private String randString = &ABCDEFGHIJKLMNOPQRSTUVWXYZ&;//随机产生只有字母的字符串
&& &//private String randString = &ABCDEFGHIJKLMNOPQRSTUVWXYZ&;//随机产生数字与字母组合的字符串 &
&&& private int width = 95;// 图片宽 &
&&& private int height = 25;// 图片高 &
&&& private int lineSize = 40;// 干扰线数量 &
&&& private int stringNum = 4;// 随机产生字符数量 &
&&& private Random random = new Random();
&&&& * 获得字体
&&& private Font getFont() {
&&&&&&& return new Font(&Fixedsys&, Font.CENTER_BASELINE, 18);
&&&& * 获得颜色
&&& private Color getRandColor(int fc, int bc) {
&&&&&&& if (fc & 255)
&&&&&&&&&&& fc = 255;
&&&&&&& if (bc & 255)
&&&&&&&&&&& bc = 255;
&&&&&&& int r = fc + random.nextInt(bc - fc - 16);
&&&&&&& int g = fc + random.nextInt(bc - fc - 14);
&&&&&&& int b = fc + random.nextInt(bc - fc - 18);
&&&&&&& return new Color(r, g, b);
&&&& * 生成随机图片
&&& public void getRandcode(HttpServletRequest request,
&&&&&&&&&&& HttpServletResponse response) {
&&&&&&& HttpSession session = request.getSession();
&&&&&&& // BufferedImage类是具有缓冲区的Image类,Image类是用于描述图像信息的类 &
&&&&&&& BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_BGR);
&&&&&&& Graphics g = image.getGraphics();// 产生Image对象的Graphics对象,改对象可以在图像上进行各种绘制操作 &
&&&&&&& g.fillRect(0, 0, width, height);
&&&&&&& g.setFont(new Font(&Times New Roman&, Font.ROMAN_BASELINE, 18));
&&&&&&& g.setColor(getRandColor(110, 133));
&&&&&&& // 绘制干扰线 &
&&&&&&& for (int i = 0; i &= lineS i++) {
&&&&&&&&&&& drowLine(g);
&&&&&&& // 绘制随机字符 &
&&&&&&& String randomString = &&;
&&&&&&& for (int i = 1; i &= stringN i++) {
&&&&&&&&&&& randomString = drowString(g, randomString, i);
&&&&&&& //将生成的随机字符串保存到session中,而jsp界面通过session.getAttribute(&RANDOMCODEKEY&), &
&&&&&&& //获得生成的验证码,然后跟用户输入的进行比较 &
&&&&&&& session.removeAttribute(RANDOMCODEKEY);
&&&&&&& session.setAttribute(RANDOMCODEKEY, randomString);
&&&&&&& g.dispose();
&&&&&&& try {
&&&&&&&&&&& // 将内存中的图片通过流动形式输出到客户端 &
&&&&&&&&&&& ImageIO.write(image, &JPEG&, response.getOutputStream());
&&&&&&& } catch (Exception e) {
&&&&&&&&&&& e.printStackTrace();
&&&& * 绘制字符串
&&& private String drowString(Graphics g, String randomString, int i) {
&&&&&&& g.setFont(getFont());
&&&&&&& g.setColor(new Color(random.nextInt(101), random.nextInt(111), random
&&&&&&&&&&&&&&& .nextInt(121)));
&&&&&&& String rand = String.valueOf(getRandomString(random.nextInt(randString
&&&&&&&&&&&&&&& .length())));
&&&&&&& randomString +=
&&&&&&& g.translate(random.nextInt(3), random.nextInt(3));
&&&&&&& g.drawString(rand, 13 * i, 16);
&&&&&&& return randomS
&&&& * 绘制干扰线
&&& private void drowLine(Graphics g) {
&&&&&&& int x = random.nextInt(width);
&&&&&&& int y = random.nextInt(height);
&&&&&&& int xl = random.nextInt(13);
&&&&&&& int yl = random.nextInt(15);
&&&&&&& g.drawLine(x, y, x + xl, y + yl);
&&&& * 获取随机的字符
&&& public String getRandomString(int num) {
&&&&&&& return String.valueOf(randString.charAt(num));
本文已收录于以下专栏:
相关文章推荐
短信验证码一般两种发送方式,用于用户注册、身份确认、重要资料修改及相关通知的场景,特别是存在于电商平台,无论是APP还是网站注册的时候都会使用短信验证码,因为验证了手机,商家就有获得两项好处,一是绑定...
●登录名和密码是同时验证的,并不是先验证登录名Java登录页面实时验证用户名密码和动态验证码是否存在然后再验证密码是否正确,是同时进行验证,若登录名和密码当中一个条件不符合,则提示用户登录名或者密码错...
需要相关的jar包
function changeImg() {
var imgSrc = $(&#imgObj&)...
java实现验证码的步骤:
1.创建验证码的实体类,代码如下:
import java.awt.BasicS
import java.awt.C
import java.aw...
login.jsp,代码如下:
[plain] view
plain copy
 print?
  
String path = request.g...
这个是根据代码 
package hpu.edu.lzl.S
import java.awt.C
import java.awt.F
import ja...
纯手工编写,希望对大家能有所帮助
首先编写注册和登录的基本页面,分别命名为regist.jsp,login.jsp,另外再创一个用于证明用户已经登录的页面提示,命名为main.jsp
login.jsp,代码如下:
My JSP '
本文转自/topic/370847
1,生成动态验证码的Servlet。
Java代码  
package com.xcu.web...
他的最新文章
讲师:宋宝华
讲师:何宇健
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)javaweb登录验证码的实现 - CSDN博客
javaweb登录验证码的实现
Controller:生成验证码
@RequestMapping(&/user/check.jpg&)
public void createCode(HttpServletRequest request, HttpServletResponse response) throws IOException {
// 通知浏览器不要缓存
response.setHeader(&Expires&, &-1&);
response.setHeader(&Cache-Control&, &no-cache&);
response.setHeader(&Pragma&, &-1&);
CaptchaUtil util = CaptchaUtil.Instance();
// 将验证码输入到session中,用来验证
String code = util.getString();
request.getSession().setAttribute(“code”, code);
// 输出打web页面
ImageIO.write(util.getImage(), &jpg&, response.getOutputStream());
jsp:显示验证码
&img id=&img& src=&&%=basePath%&user/check.jpg& onclick=&refresh()&&
function refresh() {
var url = $(&#basePath&).val() + &user/check.jpg?number=&+Math.random();
$(&#img&).attr(&src&,url);
获取session中的code与前台传回的code是否一致
* 验证码验证
* @param session
* @param code
private void checkCode(HttpSession session, String code) {
String codeSession = (String) session.getAttribute(“code”);
if (StringUtils.isEmpty(codeSession)) {
log.error(&没有生成验证码信息&);
throw new IllegalStateException(&ERR-01000&);
if (StringUtils.isEmpty(code)) {
log.error(&未填写验证码信息&);
throw new BussinessException(&ERR-06018&);
if (codeSession.equalsIgnoreCase(code)) {
// 验证码通过
log.error(&验证码错误&);
throw new BussinessException(&ERR-06019&);
import java.awt.C
import java.awt.F
import java.awt.G
import java.awt.image.BufferedI
import java.util.R
* 验证码生成工具
* @author HXL
public class CaptchaUtil {
private BufferedI// 图像
private S// 验证码
private static char code[] = &abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ&.toCharArray();
public static final String SESSION_CODE_NAME=&code&;
private CaptchaUtil() {
init();// 初始化属性
* 取得RandomNumUtil实例
public static CaptchaUtil Instance() {
return new CaptchaUtil();
* 取得验证码图片
public BufferedImage getImage() {
return this.
* 取得图片的验证码
public String getString() {
return this.
private void init() {
// 在内存中创建图象
int width = 85, height = 20;
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
// 获取图形上下文
Graphics g = image.getGraphics();
// 生成随机类
Random random = new Random();
// 设定背景色
g.setColor(getRandColor(200, 250));
g.fillRect(0, 0, width, height);
// 设定字体
g.setFont(new Font(&Times New Roman&, Font.PLAIN, 18));
// 随机产生155条干扰线,使图象中的认证码不易被其它程序探测到
g.setColor(getRandColor(160, 200));
for (int i = 0; i & 155; i++) {
int x = random.nextInt(width);
int y = random.nextInt(height);
int xl = random.nextInt(12);
int yl = random.nextInt(12);
g.drawLine(x, y, x + xl, y + yl);
// 取随机产生的认证码(4位数字)
String sRand = &&;
for (int i = 0; i & 4; i++) {
String rand = String.valueOf(code[random.nextInt(code.length)]);
// 将认证码显示到图象中
g.setColor(new Color(20 + random.nextInt(110), 20 + random.nextInt(110), 20 + random.nextInt(110)));
// 调用函数出来的颜色相同,可能是因为种子太接近,所以只能直接生成
g.drawString(rand, 13 * i + 6, 16);
// 赋值验证码
this.str = sR
// 图象生效
g.dispose();
// ByteArrayInputStream input =
// ByteArrayOutputStream output = new ByteArrayOutputStream();
// ImageOutputStream imageOut = ImageIO.createImageOutputStream(output);
// ImageIO.write(image, &JPEG&, imageOut);
// imageOut.close();
// input = new ByteArrayInputStream(output.toByteArray());
// } catch (Exception e) {
// System.out.println(&验证码图片产生出现错误:& + e.toString());
// this.image = input
this.image =/* 赋值图像 */
* 给定范围获得随机颜色
private Color getRandColor(int fc, int bc) {
Random random = new Random();
if (fc & 255)
if (bc & 255)
int r = fc + random.nextInt(bc - fc);
int g = fc + random.nextInt(bc - fc);
int b = fc + random.nextInt(bc - fc);
return new Color(r, g, b);
最后说明一点: 登录拦截器必须要放行生成验证码路径!&登录拦截器必须要放行生成验证码路径!!&登录拦截器必须要放行生成验证码路径!!!重要的事情说三遍~~
最后展示:
不算很丑~~~
本文已收录于以下专栏:
相关文章推荐
工作中过程中,同事给的一个后台开发分页工具类,小收藏一下~~
在jsp中,前一页和后一页分别使用previouspage和nextpage,中间的分页数值1,2,3...等,只要forea...
现在的登录界面大多数都带有:验证码的功能+验证码局部刷新+ajax登录。用ajax登录的好处最明显就是速度快,URL地址没有变化。所有现在登录功能很少再用form表单post提交了,大多数都已经采用了...
验证码基础
一.什么是验证码及它的作用
  
:验证码为全自动区分计算机和人类的图灵测试的缩写,是一种区分用户是计算机的公共全自动程序,这个问题可以由计算机生成并评判,但是必须只有人类才能解答....
java实现验证码的步骤:
1.创建验证码的实体类,代码如下:
import java.awt.BasicS
import java.awt.C
import java.aw...
验证码实现
网上大都是通过servlet实现的验证码,入下图逻辑:
1、请求登录页面时随机生成验证码字符串;
2、将生成对验证码字符串存到session中;
3、根据验证码字符串生成验证码...
什么是HTTP协议?以前看完了百度百科一大篇幅下来,似懂非懂,过了两天,根本忘记了它到底是个什么神秘的存在。
    我:小A,你知道HTTP协议是什么东西吗,给我科普一下?
    小A:知道啊...
一.什么是验证码及验证码的作用
验证码为全自动区分计算机和人类的图灵测试的缩写。是一种区分用户还是计算机的全自动程序,这个问题可以由计算机生成并进行判断,但是只有人类才可以解答。...
他的最新文章
讲师:宋宝华
讲师:何宇健
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)当前位置: &>&&>& >
[手把手教程][JavaWeb]优雅的SpringMvc+Mybatis应用(四)
的SpringMvc+Mybatis应用(四)
转眼间文章已经到了第四期了。坚持做一件事,确实是很难的。特别是要不断的转换思维,一个习惯前端开发的人,做什么还是前端的考虑的多一点,后端的架构设计之类的,现在还谈不上,一切稳稳的前进就行了。
关于上一期,本来是投了首页的,后来不知道什么原因没上,检查了一下,也就是推荐了下自己的博客和github,有点惆怅。
IDE为idea15
JDK环境为1.8
maven版本为maven3
Mysql版本为5.5.27
Tomcat版本为7.0.52
流程图绘制(xmind)
登录注册的简单体验优化
完整的后台主页
前端使用json数据
列表数据分页注册登录的简单体验优化
上一期我们注册登录都成功了,但是后台主页显示很丑陋,所以这里我换了个主页,但是前面没有注意到的细节又看到了。如下图:
ssm应用四-注册成功-地址栏错误
在上面的图中,地址栏显示的地址是前面注册接口的地址,并不是我们常规看到的xxx/home这种主页地址。所以我们需要进行优化处理。
同时,我们可以看到我们的Form表单提交的提示信息是在新产生的ModelAndView界面里面addObject("字段名",数据),这样我们的数据都显示到新的界面去了。也就是说前面的设计不合符现在主流的开发思路,用户体验也相对糟糕。我们需要做到在登录界面前端效验数据,同时登录注册的提示信息也是在对应的界面完成的。如下:
ssm应用四-前端form错误-提示示例
值得注意的是:为了程序执行效率、数据完整性和程序健壮性,我们的前端必须做对应的基础数据效验,后端的控制器必须做所有需要的数据的效验。
前端数据效验我们使用js完成
前端界面样式是由CSS完成
网络请求采用异步请求,具体的实现是使用的ajax完成
js获取web页面数据统一使用标签的ID,格式为:$("#标签ID")
web页面标签最好一个标签一行,这样代码看起来更加舒服
我们先重构登录页面:首先,我不擅长写web页面,我能做的也就是少量的修改,CSS和js本身不是我的强项,需要大量的时间来磨合。
所以,我选择了在网上找web界面,然后自己做少量的修改,同时一些简单的小控件我也从网络获取资源来解决需要,合理的查找资源是最快的学习方法。
登录页面重构目标:
web前端完成基本的数据效验
数据效验完成后,有基本的对应提示。如上面登录界面的小标签。
后端接口返回数据为json
前端页面解析json控制程序流转
首先,按照上面的提示,我们可以知道的是前端页面上面的基本数据效验是要使用js完成的,同时js中获取web页面标签的数据是需要使用标签的ID完成,简单的示例如下:
&script type="text/javascript"&
function webLogin() {
//定义一个名为webLogin的js函数(在java中我们称呼函数为方法)
var loginname = $("#u").val();
//var是申明一个变量的关键字,loginname为变量名,
//$("#u")是找到一个标签ID为"u"的标签,.val() 是获取对应ID标签的值
if ("" == loginname) {
//u标签的值为空
//只有通过 $("#u") 的形式才能获取一个标签。
$("#u").tips({
// .tips 是js提示标签的调用方法,具体的轮廓如上面的登陆页面的提示标签
msg: '用户名不得为空',
//提示的信息
bg: '#AE81FF',
time: 3 //呈现的时间
$("#u").focus();
//让u标签获取输入焦点
//返回false,打断js的执行
var loginpwd = $("#p").val();
if (loginpwd == "") {
$("#p").tips({
msg: '密码不得为空',
bg: '#AE81FF',
$("#p").focus();
//使用jquery下面的ajax开启网络请求
type: "POST",
//http请求方式为POST
url: '&%=request.getContextPath()%&/userAction/login',
//请求接口的地址
data: {loginId: loginname, pwd: loginpwd},
//存放的数据,服务器接口字段为loginId和pwd,分别对应用户登录名和密码
dataType: 'json',
//当这里指定为json的时候,获取到了数据后会自动解析的,只需要 返回值.字段名称 就能使用了
cache: false,
//不用缓存
success: function (data) {
//请求成功,http状态码为200。返回的数据已经打包在data中了。
if (data.code == 1) {
//获判断json数据中的code是否为1,登录的用户名和密码匹配,通过效验,登陆成功
window.location.href = "&%=request.getContextPath()%&/mvc/home";
//跳转到主页
//登录不成功
alert(data.msg);
//弹出对话框,提示返回的错误信息
$("#u").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 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 style="padding-left:50margin-top:20"&
&input type="button"
id="btn_login"
value="登 录"
oncli="webLogin();"
//此处调用我们上面写的js的登录方法
style="width:150"
class="button_blue"/&
上面就是web中调用js的简单实现,注意的是,FORM表单必须删除action的值,在点击后需要触发对应事件的地方调用js。
当然,我们的前端页面完成后,我们必须在后端接口处,做出对应的修改,让他符合我们前端的调用规则。后端修改如下:
* 用户请求相关控制器
* &br/&Created by acheng on .
@Controller //标明本类是控制器
@RequestMapping("/userAction")
//外层地址
public class UserController {
@Autowired
private UserServiceImpl userS
//自动载入Service对象
private ResponseObj responseO
//返回json数据的实体
* 登录接口,因为json数据外层一般都是Object类型,所以返回值必须是Object&br/&
这里的地址是: 域名/userAction/login
* @param req
* @param user
@RequestMapping(value = "/login"
//内层地址
, method = RequestMethod.POST
//限定请求方式
, produces = "application/ charset=utf-8") //设置返回值是json数据类型
@ResponseBody
public Object login(HttpServletRequest req, User user) {
if (null == user) {
responseObj = new ResponseObj&User&();
responseObj.setCode(ResponseObj.EMPUTY);
responseObj.setMsg("登录信息不能为空");
result = new GsonUtils().toJson(responseObj);
//通过gson把java bean转换为json
//返回json
if (StringUtils.isEmpty(user.getLoginId()) || StringUtils.isEmpty(user.getPwd())) {
responseObj = new ResponseObj&User&();
responseObj.setCode(ResponseObj.FAILED);
responseObj.setMsg("用户名或密码不能为空");
result = new GsonUtils().toJson(responseObj);
//查找用户
User user1 = userService.findUser(user);
if (null == user1) {
responseObj = new ResponseObj&User&();
responseObj.setCode(ResponseObj.EMPUTY);
responseObj.setMsg("未找到该用户");
result = new GsonUtils().toJson(responseObj);
if (user.getPwd().equals(user1.getPwd())) {
responseObj = new ResponseObj&User&();
responseObj.setCode(ResponseObj.OK);
//登录成功,状态为1
responseObj.setMsg(ResponseObj.OK_STR);
responseObj.setData(user1); //登陆成功后返回用户信息
result = new GsonUtils().toJson(responseObj);
responseObj = new ResponseObj&User&();
responseObj.setCode(ResponseObj.FAILED);
responseObj.setMsg("用户密码错误");
result = new GsonUtils().toJson(responseObj);
注意:如果为了返回数据为json,那么我们需要设定某个方法对应的注解为:@ResponseBody 。 否则会产生404错误!
我们通过上面的重构可以明白以下几点:
js实现基本的数据效验
js发起网络请求
ajax发起网络请求,返回类型设置json能自动解析
js获取页面控件
页面控件调用js
js获取解析后的json数据的值,进行程序流转控制
后端控制器必须申明
后端的地址必须配置
每个地址返回的数据类型要匹配
返回json数据,方法上面必须配置:@ResponseBody
可以使用工具类来方便开发
后台主页→个人信息修改
上期我们可以看到,我们的登录和注册都是已经OK了。现在我们登录和注册成功后,我们都让他跳转到主页去。同时完善登录和注册的错误提示页面。
一般来说,大家更喜欢看到登录成功后的主页界面,毕竟大多数人都是有喜新厌旧之嫌。我也是一样的。哈哈。
为了程序的执行逻辑,考虑后端需求都不是那么单一,我们先做一些公共的建设。比如说用户信息修改现实之类的。如下图:
ssm应用四-后台主页-修改个人信息
如上图所示,我们需要一个可以弹出的对话框,我去百度了一下,那个“妹子UI”还是很受人欢迎,所以就集成进来了。
我们选取一个比较喜欢的后端主页,然后把对应的资源放入到对应的文件目录(js、css、images等),需要新加入的资源如果在以前的目录中没有的话,那么我们需要在里面进行配置。比如说这里我加入了字体文件,那么我现在需要先把字体文件指定目录为:
static/font/
目录指定后我需要在Spring的配置文件,spring-web.xml中配置静态资源的目录如下:
&mvc:resources mapping="/fonts/**" location="/static/fonts/"/&
剩下的就是写好jsp页面(Copy+Pause+修改资源文件路径)。然后我们在Controller中配置好路径
* 后台主页
@RequestMapping(value = "/home", method = RequestMethod.GET)
public String home() {
return "home";
这样子配置好了后,我们就可以直接用“域名/mvc/home”来访问我们的主页了。同时按照上面的设置,我们登录成功后,直接解析json确认用户登录成功,然后前端使用js来进行页面跳转,如:
window.location.href = "&%=request.getContextPath()%&/mvc/home";
//跳转到主页
这样,我们就能修复上面说道的页面和地址显示不匹配的问题。
同时,通过上面的可以看出,我们在jsp页面中,纯粹没加入任何jsva代码,全是使用的前端+接口实现的功能。我们这样做,以后维护和重构中也能降低一部分压力。
言归正传,我们这里主要是想做一个个人信息修改的功能。首先我们进行功能和业务流程分析。
功能和业务流程分析:
1.web点击头像显示修改信息对话框。
2.根据后端定义的用户信息表,得出用户信息修改需要填写的资料。
3.用户上传个人资料,上传之前前端必须先进行基础信息验证。
4.用户个人信息验证通过后,上传到服务器。(重点)
5.服务器接收上传的信息,进行存储,并返回修改结果。(重点)
从上面我们可以看到我画出两个重点,而且这两个重点都是java web避免不了事情。为什么这样说呢?
1.任何一个动态的web服务器都免不了数据资料的更新,数据资料更新一般分为两种。
有文件的信息上传
无文件的信息上传
2.可能其他童鞋看到http请求的方法有很多种,但是一般来说get和post我们能做出任何的操作。
3.在大量数据的服务器中,考虑到很多因素(历史记录查询、数据库增量等),一般不会进行真正的物理数据删除,一般都是通过控制输出来实现的。(实战经验,血泪教训,切记)
现在我们开始实现对话框:
打开“妹子UI”的js插件页面,我们找到模态窗口相关的文档,在“模拟 Prompt”这里,我们可以看到具体的对话框的实现和调用如下:
&!--这是html代码--&
type="button"
class="am-btn am-btn-success"
id="doc-prompt-toggle"&
&div class="am-modal am-modal-prompt" tabindex="-1" id="my-prompt"&
&div class="am-modal-dialog"&
&div class="am-modal-hd"&Amaze UI&/div&
&div class="am-modal-bd"&
来来来,吐槽点啥吧
&input type="text" class="am-modal-prompt-input"&
&div class="am-modal-footer"&
&n class="am-modal-btn" data-am-modal-cancel&取消&/n&
&span class="am-modal-btn" data-am-modal-confirm&提交&/span&
&!--这是js调用--&
$(function() {
$('#doc-prompt-toggle').on('cli', function() {
//在这里设定上面的按钮的点击函数
$('#my-prompt').modal({ //显示ID为my-prompt的窗口
relatedTarget: this,
onConfirm: function(e) {
//窗口的确定按钮的响应事件
alert('你输入的是:' + e.data || '')
onCancel: function(e) {
//取消按钮的响应事件
alert('不想说!');
关于上面的相关代码,我们需要引入妹子UI后才能使用!!!接下来我们需要改造成符合我们实际需求的界面,如下:
&!--这里是html代码--&
&div class="am-modal am-modal-prompt" tabindex="-1" id="my-prompt"&
&div class="am-modal-dialog"&
&div class="am-modal-hd"&用户信息修改&/div&
&div class="am-modal-bd"&
&form enctype="multipart/form-data" accept-charset="UTF-8"&
&input type="text" class="am-modal-prompt-input" id="changeName"&
&input type="text" class="am-modal-prompt-input" id="changeSex"&
&input type="text" class="am-modal-prompt-input" id="changeCell"&
&input type="text" class="am-modal-prompt-input" id="changeAge"&
&div class="am-modal-prompt-input"&
&input type="file" name="file"
id="changeHeadPic" size="28"/&
&div class="am-modal-footer"&
&span class="am-modal-btn" data-am-modal-cancel&取消&/span&
&span class="am-modal-btn" data-am-modal-confirm&上传&/span&
&!--下面是js代码--&
&!--文件上传这里加入了js插件:jquery.ajaxfileupload.js--&
function uploadFile() {
//这里应该加入Loading 窗口开启
fileName = document.getElementById('changeHeadPic').
$.ajaxFileUpload({
url: "&%=request.getContextPath()%&/userAction/uploadHeadPic",
secureuri: false, //是否需要安全协议,一般设置为false
fileElementId: 'changeHeadPic', //文件上传域的ID
dataType: 'json', //返回值类型 一般设置为json
contentType: "application/x-www-form- charset=utf-8",
success: function (data) {
alert(data.msg);
//先根据返回的code确定文件是否上传成功
//文件上传失败,直接弹出错误提示,根据错误进行相应的事物处理(关闭Loading窗口,弹出提示对话框)
//文件上传成功后,继续现实loading窗口,接着执行上传表单信息等事物
function changeUserInfo() { //显示个人信息修改窗口
$('#my-prompt').modal({
relatedTarget: this,
onConfirm: function () {
uploadFile();
//调用上面的文件上传函数
onCancel: function (e) {
上面的代码,我们完成了控制窗口显示的函数,完成了修改个人信息界面的构建。现在我们需要的是找到执行程序入口。按照我的习惯,肯定是找到头像控件,然后设置点击事件为上面的changeUserInfo()。实现如下:
&!--下面是头像的html代码,在头像控件后面的点击事件上面添加上函数就行了。--&
&div class="user-img"&
&img src="/static/images/avatar-1.jpg" alt="user-img" title="Mat Helme"
class="img-circle img-thumbnail img-responsive" onclick="changeUserInfo()"&
&!--在这里添加onclick方法的值为:changeUserInfo()--&
&div class="user-status offline"&
&i class="am-icon-dot-circle-o" aria-hidden="true"&&/i&
好的,上面我们可以看到我的前端界面代码基本上完成了。接下来,我们需要在我们后端上面写上对应的程序接口,实现功能即可。
本来计划文件上传单独使用commons-fileupload和commons-io完成的,毕竟这是在Servelt上面的老套路,但是我发现Spring里面已经考虑到这一点,有新的东西来完成,所以就使用了Spring的实现方式。具体代码如下:
//我们在UserController这个控制器里添加这个方法
@RequestMapping(value = "/uploadHeadPic"
, method = RequestMethod.POST
, produces = "application/ charset=utf-8")
@ResponseBody
public Object uploadHeadPic(@RequestParam(required = false) MultipartFile file, HttpServletRequest request) {
//在这里面文件存储的方案一般是:收到文件→获取文件名→在本地存储目录建立防重名文件→写入文件→返回成功信息
//如果上面的步骤中在结束前任意一步失败,那就直接失败了。
if (null == file || file.isEmpty()) {
responseObj = new ResponseObj();
responseObj.setCode(ResponseObj.FAILED);
responseObj.setMsg("文件不能为空");
return new GsonUtils().toJson(responseObj);
responseObj = new ResponseObj();
responseObj.setCode(ResponseObj.OK);
responseObj.setMsg("文件长度为:" + file.getSize());
return new GsonUtils().toJson(responseObj);
完成了上面的方法后,我们觉得应该是没问题了,毕竟这样一个接口来接受请求是没问题的嘛,是的,我也是这么认为的。
但是现实的打脸是很严重的,因为按照这么写后,我无论如何都收不到文件(文件一直为null),Why?我的思路是正确的啊。经过我的仔细查找,发现我的Spring的配置文件中,没有添加文件的支持设置,所以我们又得补充配置文件,spring-web.xml新增配置如下:
&bean id="multipartResolver" class="org.springframework.monsMultipartResolver"&
&!--下面设置的是上传文件的最大大小--&
&property name="maxUploadSize" value=""/&
经过上面的一番折腾,我们发现框架这个东西,也不是一劳永逸的,毕竟很多东西需要不断的增加。
任何东西都需要根据需求不断的变化,可增可减,张弛有度。
Spring接收文件上传时,Controller的具体方法的参数前面插入注解,同时数据类型是MultipartFile。
引入第三方资源的时候,必须查看文档,根据说明文档好办事。
js进行前端流程控制,后端接口隔离,前后端解耦。
前两天刮台风,停电导致数据丢失,是个很尴尬的事情,拖慢了进度。同时,朋友遇到点问题,我在开导他。文章写到现在也是凌晨4点过了,本期计划的列表分页也没做,很对不起大家对我的期待。真诚的说一声:对不起。对不起你们的期待。
给朋友开导的时候,我也总结了下做人做事:随心、追梦、勇敢、独行。希望有心做事的,都用这几句话勉励自己吧。
前行的路上不只是孤独,还有满山的鲜花,更有远方和诗。
下期预告:
简易用户角色控制
拦截器的使用
延伸阅读:
(责任编辑:美朵)
每日重点推荐
夏医生是自己多年老同事的儿子,国外学成归来做事业,老同事担心儿子诊所刚开,门厅罗雀伤了自尊,便偷偷塞钱给李梅,求她装病去“捧场”。
一周热点文章
在线阅读专题

我要回帖

更多关于 java验证码工具类 的文章

 

随机推荐