欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

SSM第三季-SpringMVC-拦截器&静态资源放行&RestFul风格开发

程序员文章站 2022-07-10 18:03:39
...

SpringMVC

拦截器

配置拦截器

单一拦截器执行流程图

SSM第三季-SpringMVC-拦截器&静态资源放行&RestFul风格开发

SpringMvc中的拦截器:

a) SpringMvc拦截器帮我们按照一定规则拦截请求,后根据开发人员自定义的拦截逻辑进行处理;

b) 自定义拦截器需要实现HandlerInterceptor接口;

c) 自定义的拦截器实现类需要在SpringMvc配置文件中配置;

d) 可以配置多个拦截器,配置的顺序会影响到拦截器的执行顺序,配置在前的先执行;

e) HandlerInterceptor有3个接口:

​ i. preHandle 预处理:在拦截方法前执行;

​ ii. postHandle 后处理:在拦截方法后执行;

​ iii. afterCompletion 渲染后处理:在页面渲染后执行;

f) 拦截器也体现了AOP思想;

g) 拦截器的应用:权限检查,日志记录,性能检测等;

在applicationContext.xml中配置拦截器

		<mvc:interceptors>
			<!-- 拦截器1 -->
		 	<mvc:interceptor>
				<mvc:mapping path="/**"/>
				<bean class="com.sikiedu.interceptor.MyInterceptor1"/>
			</mvc:interceptor> 
			
			<!-- 拦截器2 -->
			<mvc:interceptor>
				<mvc:mapping path="/**"/>
				<bean class="com.sikiedu.interceptor.MyInterceptor2"/>
			</mvc:interceptor> 
			
		</mvc:interceptors>

interceptor包

MyInterceptor1.java

package com.sikiedu.interceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

/**
 * 自定义拦截器1
 */
public class MyInterceptor1 implements HandlerInterceptor {

	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		
		System.out.println(" 1 preHandle 预处理 ");
		
		return true;
	}
	
	@Override
	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
			ModelAndView modelAndView) throws Exception {
		System.out.println(" 1 postHandle 后处理 ");
	}

	@Override
	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
			throws Exception {
		System.out.println(" 1 afterCompletion 页面渲染后处理 ");
	}
	
}

MyInterceptor2.java

package com.sikiedu.interceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

/**
 * 自定义拦截器2
 */
public class MyInterceptor2 implements HandlerInterceptor {

	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		
		System.out.println(" 2 preHandle 预处理 ");
		
		return false;//false就中断后续执行了
	}
	
	@Override
	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
			ModelAndView modelAndView) throws Exception {
		System.out.println(" 2 postHandle 后处理 ");
	}

	@Override
	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
			throws Exception {
		System.out.println(" 2 afterCompletion 页面渲染后处理 ");
	}
	
}

控制台打印

1 preHandle 预处理
2 preHandle 预处理
1 afterCompletion 页面渲染后处理

因为MyInterceptor2.java中的preHandle返回值是false,所以拦截器1预处理跑到拦截器2预处理这里时拦截器2就断开了,然后继续执行拦截器1的页面渲染后处理

使用拦截器完成用户登陆效验&登陆异常处理

在bean包下创建user类

package com.sikiedu.bean;

public class User {
	
	private String username;
	private String password;
	/*get和set方法*/
}

新建自定义异常类

MyLoginException.java

package com.sikiedu.exception;

/**
 * 登录异常处理
 */
public class MyLoginException extends Exception {
	
	private String msg;
	
	private Object obj;
	
	public Object getObj() {
		return obj;
	}

	public String getMsg() {
		return msg;
	}

	public MyLoginException(String msg) {
		super();
		this.msg = msg;
	}
	
	public MyLoginException(Object obj, String msg) {
		super();
		this.msg = msg;
		this.obj = obj;
	}	

}

MyGlobalExceptionHandler.java

package com.sikiedu.exception;

import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

/**
 * 自定义全局异常处理类
 * 
 */
@ControllerAdvice
public class MyGlobalExceptionHandler {
	//处理自定义异常
	@ExceptionHandler(MyLoginException.class)
	String loginException(MyLoginException e, Model model) {
		
		Object obj = e.getObj();
		if(obj != null)
		{
			model.addAttribute("username", obj.toString());
		}
		
		model.addAttribute("errorMsg", e.getMsg());
		
		//视图名
		return "login_page";	
	}
}

在controller包下新建LoginController类

LoginController.java

package com.sikiedu.controller;

import javax.servlet.http.HttpSession;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import com.sikiedu.bean.User;
import com.sikiedu.exception.MyLoginException;

/**
 * 登录
 */
@Controller
@RequestMapping("/login/")
public class LoginController {

	//登录请求 
	
	//登录成功 重定向到列表页
	@RequestMapping(value = "login.do", method= RequestMethod.POST)
	public String login(User u, HttpSession session) throws MyLoginException{
		
		User user = new User();
		user.setUsername("xueleng");
		user.setPassword("123");
		
		if(u.getUsername().equals(user.getUsername())) {
			//用户名正确
			if(u.getPassword().equals(user.getPassword())) {
				session.setAttribute("user", u);
			}
			else {
				//throw new MyLoginException("密码错误");
				throw new  MyLoginException(u.getUsername(), "密码错误");
			}
		}
		else {
			throw new MyLoginException("用户名错误");
		}
		
		//判断用户
		/*if(u != null) {
			session.setAttribute("user", u);
		}*/
		
		//重定向到列表页
		return "redirect:/item/allList.do";
	}
	
	
	//登录失败 前往登录页面
	@RequestMapping(value = "login.do", method= RequestMethod.GET)
	public String login() {
		//前往登录页面
		return "login_page";
	}
	
}

新建一个拦截器

LoginInterceptor.java

package com.sikiedu.interceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.HandlerInterceptor;

/**
 * 登录拦截器
 */
public class LoginInterceptor implements HandlerInterceptor {

	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		
		//获取请求
		String URI = request.getRequestURI();
		
		if(!URI.contains("login")) {
			//不是登录请求 拦截
			Object user = request.getSession().getAttribute("user");
			
			if(user == null) {
				//没有登录 重定向到登录页面 / 请求
				response.sendRedirect(request.getContextPath()+"/login/login.do");
				return false;
			}
		}
		
		return true;
	}

}

配置拦截器

<mvc:interceptors>
			<!-- 登录验证拦截器 -->
			<mvc:interceptor>
				<mvc:mapping path="/**"/>
				<bean class="com.sikiedu.interceptor.LoginInterceptor"/>
			</mvc:interceptor>
		</mvc:interceptors>

登陆页面

<%@ 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 charset="UTF-8">
        <title>登录/注册</title>
        <meta name="viewport" content="initial-scale=1.0,maximum-scale=1.0,user-scalable=no">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">

        <!-- bootstrap framework -->
        <link href="${pageContext.request.contextPath }/css/bootstrap.min.css" rel="stylesheet" media="screen">
        <!-- elegant icons -->
        <link href="${pageContext.request.contextPath }/css/style.css" rel="stylesheet" media="screen">
        <!-- main stylesheet -->
		<link href="${pageContext.request.contextPath }/css/main.min.css" rel="stylesheet" media="screen">

        <!-- jQuery -->
        <script src="${pageContext.request.contextPath }/js/jquery.min.js"></script>

    </head>
    <body class="login_page">
        <div class="login_header">
        </div>
        <div class="login_register_form">
            <div class="form_wrapper animated-short" id="login_form">
                <h3 class="sepH_c"><span>Login</span> \ <a href="javascript:void(0)" class="form-switch" data-switch-form="register_form">Register</a></h3>
                <form id="loginFrom" action="${pageContext.request.contextPath }/login/login.do" method="post">
                    <div class="input-group input-group-lg sepH_a">
                        <span class="input-group-addon"><span class="icon_profile"></span></span>
                        <input type="text" class="form-control" placeholder="Username" name="username" value="${username }">
                    </div>
                    <div class="input-group input-group-lg">
                        <span class="input-group-addon"><span class="icon_key_alt"></span></span>
                        <input type="password" class="form-control" placeholder="Password" name="password">
                    </div>
                    
                    <div>
                        <a id="errorMsg" href="javascript:void(0)" style="color: red">${errorMsg}</a>
                    </div>
                    
                    <div class="sepH_c text-right">
                        <a href="javascript:void(0)" class="small">Forgot password?</a>
                    </div>
                    <div class="form-group sepH_c">
                        <a href="javascript:doucment:loginFrom.submit()" class="btn btn-lg btn-primary btn-block">Log in</a>
                    </div>
                </form>
            </div>
            <div class="form_wrapper animated-short" id="register_form" style="display:none">
                <h3 class="sepH_c"><span>Register</span> \ <a href="javascript:void(0)" class="form-switch" data-switch-form="login_form">Login</a></h3>
                <form name = "registerForm" action="${pageContext.request.contextPath}/userRegister" method="post">
                    <div class="input-group input-group-lg sepH_a">
                        <span class="input-group-addon"><span class="icon_profile"></span></span>
                        <input type="text" class="form-control" placeholder="Username" name="username">
                    </div>
                    <div class="input-group input-group-lg sepH_a">
                        <span class="input-group-addon"><span class="icon_key_alt"></span></span>
                        <input type="password" class="form-control" placeholder="Password" name="password">
                    </div>
                    <div class="input-group input-group-lg sepH_c">
                        <span class="input-group-addon"><span class="icon_mail_alt"></span></span>
                        <input type="email" class="form-control" placeholder="Email" name="email">
                    </div>
                    <div class="form-group sepH_c">
                        <a href="javascript:doucment:registerForm.submit()" class="btn btn-lg btn-success btn-block">Register</a>
                    </div>
                </form>
            </div>
        </div>

        <script>
            $(function () {
                $('.form-switch').on('click', function (e) {
                    e.preventDefault();

                    var $switchTo = $(this).data('switchForm'),
                        $thisForm = $(this).closest('.form_wrapper');

                    $('.form_wrapper').removeClass('fadeInUpBig');
                    $thisForm.addClass('fadeOutDownBig');

                    setTimeout(function () {
                        $thisForm.removeClass('fadeOutDownBig').hide();
                        $('#' + $switchTo).show().addClass('fadeInUpBig');
                    }, 300);

                });
            });
        </script>
    </body>
</html>

静态资源放行

a) 在web.xml配置DispatcherServlet的url-pattern以扩展名结尾,例如*.do*.html 等;

b) 在web.xml配置default servlet-mapping的url-pattern,以目录形式和扩展名形式;

  <!-- 静态资源放行 -->
<!--   <servlet-mapping>
  	<servlet-name>default</servlet-name>
  	<url-pattern>/css/*</url-pattern>
  	<url-pattern>*.css</url-pattern>
  	<url-pattern>*.ttf</url-pattern>
  	<url-pattern>*.woff</url-pattern>
  	<url-pattern>*.js</url-pattern>
  	<url-pattern>*.png</url-pattern>
  </servlet-mapping> -->

c) 在springmvc.xml中配置<mvc:resources/>,该方法需要注意以下几点:

		<!-- 静态资源放行 -->
		<mvc:resources location="/css/" mapping="/css/**"/>
		<mvc:resources location="/fonts/" mapping="/fonts/**"/>
		<mvc:resources location="/js/" mapping="/js/**"/>
		<mvc:resources location="/picture/" mapping="/picture/**"/>

​ i. 需要开启mvc:annotation-driven注解驱动;

		<!-- 开启注解驱动 -->
	<mvc:annotation-driven/>

​ ii. 如果配置了拦截器,需要在拦截器中进行过滤,否则会被拦截

			<!-- 登录验证拦截器 -->
			<mvc:interceptor>
				<mvc:mapping path="/**"/>
				<!-- 排除一些文件|不拦截一些文件 -->
				<mvc:exclude-mapping path="/**/*.css"/>
				<mvc:exclude-mapping path="/**/*.js"/>
				<mvc:exclude-mapping path="/**/*.png"/>
				<mvc:exclude-mapping path="/**/*.tff"/>
				<mvc:exclude-mapping path="/**/*.woff"/>
				<bean class="com.sikiedu.interceptor.LoginInterceptor"/>
			</mvc:interceptor>

​ iii. 路径名不要打错 ;

RestFul风格开发

RESTful风格开发:一种以URL定位资源的开发风格。使用RESTful开发URL会变得一目了然,更有层次,它不是标准或者协议;

使用RESTful前:

http://127.0.0.1/item/save POST 新增物品
http://127.0.0.1/item/delete GET/POST 删除物品
http://127.0.0.1/item/update POST 修改物品

http://127.0.0.1/item/query.do?id=1 GET 根据id查询物品

使用RESTful后:

http://127.0.0.1/item POST 新增物品
http://127.0.0.1/item/1 DELETE 根据id删除物品
http://127.0.0.1/item PUT 修改物品
http://127.0.0.1/item/1 GET 根据id查询物品

RESTful风格开发对Http协议中的基本方法的使用

POST INSERT 增 邮寄一个新的

DELETE DELETE 删 仍了,不要了

GET SELECT 查 获取一个

PUT UPDATE 改 往这个里边放点东西

使用Springmvc实现RESTful风格开发;

使用物品id当作请求路径,点击按钮,跳转到具体的页面;

在ItemController.java中添加一个方法
//使用restFul开发
	//查询一个游戏信息,并且显示在内容页
	 
新建一个item_info.jsp用于跳转页面测试
<%@ 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>
	<h3>我是内容页</h3>
	<input type="text" value="${item.item_id }">
	<input type="text" value="${item.item_name }">
	<input type="button" value="返回" οnclick="window.location='${pageContext.request.contextPath}/item/allList.do'">
</body>
</html>
修改主页面部分代码,添加一个input查询按钮用于跳转页面测试

<a herf="#" id="del_btn" class="btn btn-xs btn-danger" onclick="window.location='${pageContext.request.contextPath }/item/${item.item_id}'">查询</a>

页面效果

SSM第三季-SpringMVC-拦截器&静态资源放行&RestFul风格开发

当点击查询按钮时,页面url跳转到<http://localhost:8080/ssm_project_springmvc/item/游戏的id>

当使用ajax时,页面不会跳转,需要到ajax回调中处理

修改主页面部分代码,添加一个input查询按钮和函数用于跳转页面测试

<a herf="#" id="del_btn" class="btn btn-xs btn-warning" onclick="restFul('${item.item_id}')">查询</a>

//restFul
		function restFul(id) {
			$.ajax({
				type : "get",
				url : "${pageContext.request.contextPath }/item/" + id,
				success : function(data) {
					//window.location="${pageContext.request.contextPath }/item/"+id;
					alert(data.item_name);
				}
			});
		}
修改controller中的方法
//使用restFul开发
	//查询一个游戏信息,并且显示在内容页
	@RequestMapping(value = "{item_id}", method=RequestMethod.GET)
	@ResponseBody
	public ItemInfo restFul(@PathVariable("item_id") String id, Model model) {
		System.out.println("ajax " + id);
		//查询
		ItemInfo item = itemService.selectItemInfoById(id);
		
		model.addAttribute("item", item);
		
		//返回页面
		//return "item_info";
		return item;
	}