这是CRM项目的第二个版本。相比于上次,这次完成的内容主要有:
1.使用ajax技术实现登录验证的局部刷新技术。登录成功,则跳转到新的页面;否则,在对应的位置显示错误的原因。
2.还要实现点"登录"或者敲回车都能发送请求。
3.使登录窗口始终都处于最顶层窗口
**一个很大的问题:**在使用springMVC的拦截器来验证用户是否登录的时候,发现拦截器一点都不起作用,里面的方法根本就执行不了,找了一下午,至今没有解决!!!
1.让用户名文本框自动获得焦点
这是为了提升用户体验,让一进入到页面就能直接输入。
//页面加载完毕后,清空文本框中的内容
$("#loginAct").val("");
$("#loginAct").focus(); //使用id选择器拿到jQuery对象,然后执行focus()方法
2.按回车或者点击"登录"都可以实现登录验证
//为登录按钮绑定事件
$("#loginBtn").click(function (){
login();
})
//敲回车键也可以登录
$(window).keydown(function (event){
//event只是一个变量名,是一个引用,指向了一个事件对象,所有的键盘事件对象都有一个keyCode属性,用来获取键值。
if ("13" == event.keyCode){
login();
}
})
在login()方法里面就是使用ajax技术向后台发送请求啦~
function login(){
var loginAct = $.trim($("#loginAct").val());
var loginPwd = $.trim($("#loginPwd").val());
//用户名或密码为空的话,没必要过后台,直接前端处理就行
if (loginAct == "" || loginPwd == ""){
$("#msg").html("<font color='#FF0000'>账号或密码不能为空呀~</font>");
return false;
}
$.ajax({
url:"settings/user/login.do",
data:{"loginAct":loginAct,"loginPwd":loginPwd},
type:"POST",
dataType:"json", //预期服务器返回的数据类型
success:function (data){
//map: 1.success; 2.msg
if (data.success){
//验证成功,跳转到
window.location.href="workbench/index.jsp";
}else {
//不成功,把不成功的原因写在msg上
$("#msg").html(data.msg);
}
}
})
}
本来我是在后台做账号或密码为空的验证的,但是最后发现其实根本没有必要,如果是Null的话,直接在前端处理完就行了。
上面的settings/user/login.do
是会跑到后台的controller被处理的。一般控制器就是调用service方法,在service方法里面完成逻辑处理
@Controller //使用注解创建controller对象
public class UserController {
@Autowired //引用类型自动赋值,byType
private UserService userService;
@ResponseBody //如果返回对象,一定要加这个注解,否则没办法把值返回到正确的路径====吃了亏
@RequestMapping("/settings/user/login.do") //知道哪个方法处理哪个请求
public Map<String,Object> login(HttpServletRequest request,String loginAct, String loginPwd){ //使用逐个接收方式接收前端传来的对象
System.out.println("=======进入到用户验证控制器=========");
//接收浏览器的ip地址
String ip = request.getRemoteAddr();
Map<String,Object> map = userService.login(loginAct,loginPwd,ip);
//如果是返回真,就把user从map取出来,丢到session域中
Boolean flag = (Boolean) map.get("success");
if (flag){
User user = (User) map.get("user");
request.getSession().setAttribute("user",user);
map.remove("user");
}
return map; //这里的map也是有user对象的,但是不需要,上面给删除了
}
}
Service实现类,这里我没有使用异常类的方式进行处理,直接一个一个进行验证了。Service是调用dao完成查询工作的,如果能查得到,就把user对象扔回前端。
@Service
public class UserServiceImpl implements UserService {
@Autowired //引用类型的自动注入,默认是byType,只能有一个这样的类型的
private UserDao userDao; //org.apache.ibatis.binding.MapperProxy@3cd3cb8a是代理对象
@Override
public Map<String, Object> login(String loginAct, String loginPwd, String ip) {
Map<String,Object> map = new HashMap<>();
//将密码变成密文形式
loginPwd = MD5Util.getMD5(loginPwd);
User user = userDao.login(loginAct,loginPwd);
//验证账号密码是否正确
if (user == null){
map.put("success",false);
map.put("msg","<font color='#FF0000'>账号或密码不正确~</font>");
return map;
}
//有记录--验证允许访问ip
if (!user.getAllowIps().contains(ip)){
map.put("success",false);
map.put("msg","<font color='#FF0000'>你没有权限访问该网址!</font>");
return map;
}
boolean flag = false;
SimpleDateFormat sdf =new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//创建日期转换对象:年月日 时分秒
Date today = new Date();
Date dateD = null; //转换为 date 类型 Debug:Sun Nov 11 11:11:11 CST 2018
try {
dateD = sdf.parse(user.getExpireTime()); //数据库时间
flag = dateD.getTime() >= today.getTime(); //前面>=后面,true。数据库时间更大,返回真
} catch (ParseException e) {
e.printStackTrace();
}
//验证失效时间
if (!flag){
map.put("success",false);
map.put("msg","<font color='#FF0000'>你的使用时间已到期!!!</font>");
return map;
}
//验证锁定状态
if ("0".equals(user.getLockState())){
map.put("success",false);
map.put("msg","<font color='#FF0000'>你的账号已被锁定,你干了什么啊~</font>");
return map;
}
//能到这里说明全部正确
map.put("success",true);
map.put("user",user); //把查出来的记录丢回Controller,前端要用到一些信息
return map;
}
}
UserDao内容:这里传多个值的时候,必须使用@Param(“xxx”)注解,否则会报错,mapper文件里面找不到这两个值。====我吃了亏
public interface UserDao {
User login(@Param("loginAct") String loginAct, @Param("loginPwd") String loginPwd);
}
3.使登录窗口始终处于最顶层
//使login.jsp始终在顶层窗口中打开
if(window.top!=window){
window.top.location=window.location;
}
!!!未解决的问题
使用springmvc的拦截器的时候出现了问题,无论怎么配置,拦截器都不起作用。
拦截器:用来拦截请求,对请求做预先的判断处理工作。拦截器常用在:用户登录处理,权限检查,记录日志。
使用步骤:1.定义类实现HandlerInterceptor接口,重写相应的方法 2.在springmvc配置文件中,声明拦截器, 让框架知道拦截器的存在。
public class LoginInterceptor implements HandlerInterceptor {
//在方法前先执行这个方法
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("==========进入用户访问权限拦截器===========");
//获取访问的路径
String path = request.getServletPath();
if ("/login.jsp".equals(path) || "/settings/user/login.do".equals(path)){
//登录请求应该放行
return true;
}else {
//验证有没有登录过,从session域里面拿到user对象
HttpSession session = request.getSession();
User user = (User) session.getAttribute("user");
if (user != null){ //说明已经登录了
return true;
}else {
//重定向到登录页面
response.sendRedirect(request.getContextPath()+"/login.jsp");
return false;
}
}
}
}
在配置文件里面:
<!--声明拦截器-->
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="com.bjpowernode.crm.web.interceptor.LoginInterceptor" />
</mvc:interceptor>
</mvc:interceptors>
所有步骤都做完了,但拦截器就是始终都不起作用,好邪门,不知道怎么回事。网上有的是因为在springmvc的配置文件里面配置了注解驱动<mvc:annotation-driven />
导致冲突,但是我把这个注释了,还是不起作用。另外,这个注解驱动是要加的,否则,你的页面就会全部变成404了,显然这不是解决办法。
还有一些说在第一行的下面先声明拦截器类的位置,即加多一行:<bean class="com.bjpowernode.crm.web.interceptor.LoginInterceptor" />
我试了,显然也是没用的。
还有一些答案说什么:springmvc有一个默认的拦截器,自己写的会和他的冲突,而且优先级没有那么高,所以你的执行不到,也没找到解决方法。。。。。。
这个问题就暂且放一放吧!等我下次找到答案的时候,我会回来更新的。另外,如果有大神知道怎么解决的话,告诉告诉呗!!!
分割线================
下面的内容是我后面更新的,关于springmvc的拦截器不起作用的原因,我找到答案了。知道原因的那一刻,就好像是多年心中的结被解开了。
具体原因是因为,在web.xml文件注册监听器的时候,我的<url-pattern>
里面是这样子写的
<url-pattern>*.do</url-pattern>
这里的*.do表示,所有以do结尾的请求都有这个DispatcherServlet来处理。这就说明,静态资源是不会给这个DispatcherServlet来管理的,而是使用系统默认的DefaultServlet来处理,难怪我说怎么一直不起作用呢!!!哭死了。为什么会发现是这里的错误呢?这是因为我在发起xxx.do请求的时候,控制器方法在控制台上输出了,最后给我找到了这个原因。经过这次几天的恶心我的过程,以后我感觉对这个是有非常深的印象了。
总结一下:如果以后拦截器不起作用的话,从哪里开始找问题吧。
(1)去web.xml配置文件里面看你是怎么注册中央调度器的,是不是把你要拦截的资源给他管理了,静态资源啊、动态资源啊。
(2)去springmvc的配置文件里面查看你的拦截器的声明,也是看哪些内容需要被拦截!!!
最后,虽然发现了这个问题,但是配了这个拦截器之后,反而出现了更多问题。第一个就是拦截的路径实在一言难尽,有时候明明将其交给拦截器拦截,但又没有。有些设置了不需要他拦截,他又一直拦截,最后导致我登录都没有办法登录。还有就是路径问题,使用拦截器之后,绝对路径不知道变成什么了。
所以,最后,我直接取消了拦截器,哈哈哈哈。
还是非常开始能找到这个原因的。头秃的一天。
这一版就更新到这了。下一次应该是做市场活动相关的模块了~