SSM+Ajax+maven+拦截器实现登录功能
SSM+maven+拦截器实现登录功能
写这篇文章的时候一直不知道怎么写,怎么说呢,因为我这篇博客的内容是在上一篇博客所用代码里改的,为了偷懒,也就不好意思让各位去看一下上一篇博客内容是怎么配置的啦。我把主要添加了的内容加到这里面来,然后代码也上传到CSDN中。内容主要包含了以下几点
- maven配置文件和web.xml文件内容不变
- 登录的操作所用请求不变
- *编写拦截器
- spring-mvc.xml文件中的配置
拦截器配置
springMVC拦截器的实现一般有两种方式
第一种方式是要定义的Interceptor类要实现了Spring的HandlerInterceptor 接口
第二种方式是继承实现了HandlerInterceptor接口的类,比如Spring已经提供的实现了HandlerInterceptor接口的抽象类HandlerInterceptorAdapter,我的这里采用了第一种方式
HandlerInterceptor 接口中定义了三个方法,我们就是通过这三个方法来对用户的请求进行拦截处理的。
afterCompletion:该方法主要是用来处理请求之后的收尾工作,也就是在DispatcherServlet 渲染了对应的视图之后执行。表述不清,望见谅
postHandle:这个方法在业务处理器处理请求之前被调用,在调用过程中最先被执行。
preHandle:请求执行前需要进行校验的操作在该方法体内。
下面是我的LoginInterceptor类的操作,里面的注释也很多,相信都没问题
package com.blog.interceptor;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
public class LoginInterceptor implements HandlerInterceptor {
private static final Logger log = Logger.getLogger(LoginInterceptor.class);
/**
* 不拦截的后缀
*/
private List<String> excludeMappingUrl;//不拦截的后缀通过Spring-mvc.xml配置文件中配置
/*
* (non-Javadoc)
* Handler执行完之后的操作
*/
@Override
public void afterCompletion(HttpServletRequest resquest, HttpServletResponse response, Object object, Exception exception)
throws Exception {
System.out.println("afterCompletion:请求之后被执行");
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object object, ModelAndView mv)
throws Exception {
System.out.println("postHandle:请求之前被执行。");
}
/*
* Handler执行前执行的方法,请求前进行执行校验
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object object) throws Exception {
log.info("enter method preHandle");
String url = request.getRequestURI();//获取请求的URL
// System.out.println(url);
String postFix = null; //前缀
// 查看是否是静态文件,如果是静态文件,放行
if(StringUtils.isNotEmpty(url)){
int index = url.lastIndexOf(".");//获取.操作最后出现的位置的下标
if(index > -1){//说明索引的位置可以以“.”开头
postFix = url.substring(index);//拿到该URL的后缀
if(StringUtils.isNotEmpty(postFix)&&excludeMappingUrl.contains(postFix)){
//静态文件,默认处理
return true;
}
}else if(!url.contains("/vaild")&&!url.contains("/toLogin")){
//判断session是否存在
HttpSession session = request.getSession();
if(session.getAttribute("USER_INFO")==null){
//说明session中不存在用户的登录信息
//可在这里写关于转发的操作.不存在的情况就转发到登录页面中去
// String basePath = request.getContextPath();//解决相对路径问题,相当于站点的根路径,
// PrintWriter out = response.getWriter();//通过PrintWrite,以流方式输出html,返回给客户端,反馈在页面上
// out.println("<html>");
// out.println("<script>");
// out.println("window.open('"+basePath+"/toLogin')");
// out.println("</script>");
// out.println("</html>");
// out.flush();
log.info("Interceptor:跳转到login页面!");
request.getRequestDispatcher("/WEB-INF/view/login.jsp").forward(request, response);
return false;
}
return true;//包含以上两个URL是开始就进入的页面操作
}
}
return true;
//不是登录请求,不是静态文件,判断session是否存在
//符合条件的准许登录,否则跳转到登录界面
}
public List<String> getExcludeMappingUrl() {
return excludeMappingUrl;
}
public void setExcludeMappingUrl(List<String> excludeMappingUrl) {
this.excludeMappingUrl = excludeMappingUrl;
}
}
接下来是在spring-mvc.xml文件中的配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation=" http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<!-- 自动扫描该包,使Springmvc认为包下使用了@Controller注解的类是控制器 -->
<context:component-scan base-package="com.blog.controller" />
<!-- 定义文件跳转的前后缀,完成请求和POJO的映射 -->
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass"
value="org.springframework.web.servlet.view.JstlView" />
<property name="prefix" value="/WEB-INF/view/" />
<property name="suffix" value=".jsp" />
</bean>
<!-- 静态资源映射 -->
<mvc:resources mapping="/resource/js/**" location="/resources/js/" />
<mvc:resources mapping="/resource/css/**" location="/resources/css/" />
<mvc:resources mapping="/resource/images/**" location="/resources/images/" />
<mvc:resources mapping="/resource/fonts/**" location="/resources/fonts/" />
<mvc:resources mapping="/resource/plugins/**" location="/resources/plugins/" />
<bean id="jsonConverter"
class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"></bean>
<bean
class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="messageConverters">
<list>
<ref bean="jsonConverter" />
</list>
</property>
</bean>
<!-- 配置拦截器 多个拦截器顺序执行-->
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="com.blog.interceptor.LoginInterceptor">
<!-- 配置属性列表 -->
<property name="excludeMappingUrl"><!-- 列表中包含的文件后缀 -->
<list>
<value>/toLogin</value>
<value>/vaild</value>
<value>/out</value>
<value>.js</value>
<value>.css</value>
<value>.gif</value>
<value>.png</value>
<value>.map</value>
<value>.jpg</value>
<value>.woff3</value>
<value>.woff2</value>
<value>.woff</value>
<value>.ttf</value>
</list>
</property>
</bean>
</mvc:interceptor>
</mvc:interceptors>
<!-- 自动注册DefaultAnnotationHandlerMapping与AnnotationMethodHandlerAdapter
两个bean,是spring MVC为@Controllers分发请求所必须的 -->
<mvc:annotation-driven />
</beans>
哎,我这个是什么心态呀,总是担心小伙伴看不懂忍不住想把所有的内容写上。算了,太晚了,我还是忍忍。
接下来是login.jsp文件和index.jsp文件,还有controller这个类中的文件,那就先controller吧
package com.blog.controller;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpSession;
import org.apache.commons.collections.map.HashedMap;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;
import com.blog.service.UserService;
import com.blog.util.MD5Util;
import com.blog.vo.Page;
import com.blog.vo.ResultInfoVO;
import com.blog.vo.User;
@SuppressWarnings("unchecked")
@Controller
//@RequestMapping(value="user")
public class UserController {
private final String USER_INFO="USER_INFO";//用来保存
private static final Logger log = Logger.getLogger(UserController.class);
@Autowired
private UserService userService;
// @RequestMapping(value="/list",method=RequestMethod.GET)
// @ResponseBody
// public ResultInfoVO getAllList(){
// log.info("Enter method getAllList ");
// int result = 1;
// String message = "";
// ResultInfoVO vo = new ResultInfoVO();
// List<User> users = userService.getAllUsers();
// if(users!=null){
// vo.setObject(users);
// message = "成功!";
// result = 0;
// }
// vo.setResult(result);
// vo.setRtnMessage(message);
// return vo;
// }
//
@RequestMapping(value="toLogin")
public String toLogin(){
return "login";
}
@RequestMapping(value="/out")
public String out(){
return "redirect:toLogin";
}
/*
* @ModelAttribute,使用该注解能将请求传过来的值封装到对应的user对象的参数名称中去
*/
@RequestMapping(value="/vaild",method=RequestMethod.POST)
@ResponseBody
public ResultInfoVO vail(HttpSession session,String userName,String password){
log.info("vail");
ResultInfoVO mv = new ResultInfoVO();
User checkUser = new User();
checkUser.setUserName(userName);
checkUser.setPassword(MD5Util.getMd5(password));
String rtnMessage="";
int result = -1;
if(StringUtils.isNotEmpty(userName)&&StringUtils.isNotEmpty(MD5Util.getMd5(password))){
//判断传输过来的值是否为空,不为空才进行查询
User user = userService.getLoginUser(checkUser);
if(null == user){
//没有登录成功
rtnMessage = "用户名或密码错误";
}else{
//将checkUser的值塞到session中
result=0;
session.setAttribute("USER_INFO", user);
}
}
//如果验证通过,转发到主页去
mv.setResult(result);
mv.setRtnMessage(rtnMessage);
return mv;
}
@RequestMapping(value="/index")
public String mainIndex(){
return "index";
}
/* @RequestMapping(value="/user/initIsZero",method=RequestMethod.POST)
@ResponseBody
public ResultInfoVO initIsZero(Integer indexPage,Integer pageSize){
log.info("Enter method initIsZero ");
ResultInfoVO vo = new ResultInfoVO();
int count = userService.getUserCount();
Page page = new Page();
int result = -1;
String rtnMessage = "";
page.setSkip(indexPage*pageSize); //设置跳过的条数
page.setPageSize(pageSize); //设置要显示多少条数据,可在前端页面中更改
List<User> users = userService.getPageZero(page);
Map<String,Object> map = new HashedMap();
if(users!=null){
map.put("users", users);
map.put("count",count);
result=0;
rtnMessage = "OK";
}
vo.setObject(map);
vo.setRtnMessage(rtnMessage);
vo.setResult(result);
return vo;
}
@RequestMapping(value="/user/indexPageNotZero",method=RequestMethod.POST)
@ResponseBody
public ResultInfoVO indexPageNotZero(Integer indexPage,Integer pageSize){
log.info("Enter method initIsZero ");
ResultInfoVO vo = new ResultInfoVO();
Page page = new Page();
int result = -1;
String rtnMessage = "";
page.setSkip(indexPage*pageSize); //设置跳过的条数
page.setPageSize(pageSize); //设置要显示多少条数据,可在前端页面中更改
List<User> users = userService.getPageZero(page);
Map<String,Object> map = new HashedMap();
if(users!=null){
result = 0;
rtnMessage = "OK";
map.put("users", users);
}
vo.setObject(map);
System.out.println(map.get("users").toString());
vo.setResult(result);
vo.setRtnMessage(rtnMessage);
return vo;
}*/
}
login.jsp页面
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions"%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jstl/fmt_rt"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme() + "://"
+ request.getServerName() + ":" + request.getServerPort()
+ path + "/";
%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
<script type="text/javascript" src="<%=basePath%>resource/js/jquery-2.1.4.min.js"></script>
<style type="text/css">
body{
widht:100%;
height: 100%;
}
#main{
margin-left:40%;
margin-top:20%;
padding:20px;
}
</style>
</head>
<body>
<div id="main">
<div>
<form method="post" id="user_info">
用户名:<input type="text" name="userName" id="userName"/></br>
密 码:<input name="password" id="password" type="password" /></br>
<input type="button" onclick="login()" value="登录"> <input type="button" value="注册"/></br>
<label id="messageView"></label>
</form>
</div>
</div>
</body>
<script type="text/javascript">
function login(){
var userName = $("input[name='userName']").val();
var password = $("input[name='password']").val();
$.ajax({
url:'<%=basePath%>vaild',
type:'POST',
dataType:'json',
data:"userName="+userName+"&password="+password,
success:function(data){
//如果成功,转发到其他页面,否则提示内容
alert(data);
if(data.result==0){
window.location="<%=basePath%>index";
}else{
alert(data.rtnMessage);
}
},
error:function(data){
alert("error");
}
});
}
</script>
</html>
登录成功后的主页
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
这里是登录成功后的首页位置
</body>
</html>
也不想搞事情,就随意的写了一个页面
如果没有数据库的,可以先进入自己的数据库,执行操作:
create database blog;
create table user(id int(10) primary key auto_increment,username varchar(20),password varchar(40));随意插入几条数据 insert into user(username,password) values(“用户名”,”密码”);
在这里的密码我使用了MD5加密的方式,插入数据的时候还可以在测试类中使用里面的测试方法插入数据,测试类内容如下:
package com.blog.test;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.blog.service.UserService;
import com.blog.util.MD5Util;
import com.blog.vo.User;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"classpath:spring.xml"})
public class TestUserAllMethod {
// String[] config = new String[]{"spring.xml","spring-mvc.xml"};
// ApplicationContext context = new ClassPathXmlApplicationContext(config);
// String config = "spring.xml";
// ApplicationContext context = new ClassPathXmlApplicationContext(config);
@Autowired
private UserService userService;
@Test
public void loginTest(){
// userService = (UserService) context.getBean("userService");
User user = new User();
user.setUserName("lg1");
user.setPassword("1234");
User user1 = userService.getLoginUser(user);
System.out.println(user1.getUserName()+user1.getPassword());
System.out.println(userService);
}
@Test
public void testInsert(){
User user = new User();
user.setPassword(MD5Util.getMd5("1234"));
user.setUserName("llbb");
int rtnValue = userService.insertUser(user);
System.out.println(rtnValue);
}
public static void main(String[] args){
String s = ".sd";
int index = s.lastIndexOf('.');
System.out.println(index);
System.out.println(s.substring(index));
}
}
注释的那部分是获取对象的另外一种写法。可以自行百度。
MD5加密代码部分:
package com.blog.util;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class MD5Util {
//静态方法,便于作为工具类
public static String getMd5(String plainText) {
try {
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(plainText.getBytes());
byte b[] = md.digest();
int i;
StringBuffer buf = new StringBuffer("");
for (int offset = 0; offset < b.length; offset++) {
i = b[offset];
if (i < 0)
i += 256;
if (i < 16)
buf.append("0");
buf.append(Integer.toHexString(i));
}
//32位加密
return buf.toString();
// 16位的加密
//return buf.toString().substring(8, 24);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
return null;
}
}
}
加密的这个地方也忘记了作者是谁了,不知道哪里抄来的,万一原作者看到,请见谅,我抄了你的代码。最后查看运行效果:
输入地址
http://localhost:8080/blog/
用户名:llbb。密码:1234
成功后的页面:
控制台打印内容
看到一个请求方法的执行顺序了吗?请注意。
下面我说说我在写的过程中遇到的问题,之前我以为,我只要项目名称出现,然后随意输入一个地址,系统都会给我转发到登录页面,其实才知道这个拦截器拦截的只是存在的URL,不存在的URL使用的话只会报404错误。下面附上代码地址:http://download.csdn.net/detail/qq_25050981/9921742
接下来我会编写关于权限控制,webSocket聊天,然后我将深入理解java编程思想,把遇到的问题更新下去。技术无止尽,不放弃。