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

【SSM_SpringMVC】学习笔记05拦截器、静态资源放行、RESTFUL风格

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

一、拦截器

SpringMVC中的拦截器:

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

2、自定义拦截器需要实现HandlerInterceptor接口;

3、自定义的拦截器实现类需要在SpringMVC配置文件中配置;

4、可以配置多个拦截器,配置的顺序会影响到拦截器的执行顺序,先配先执行

5、HandlerInterceptor共3个接口:

a) preHandler 预处理:在拦截方法前执行;

b) postHandler 后处理:在拦截方法后执行;

c) afterCompletion 渲染后处理:在页面渲染后执行;

6、拦截器也体现了AOP思想

7、应用:权限检查、日志记录、性能检测等;

拦截器的执行流程图:(图来自www.sikiedu.com)

【SSM_SpringMVC】学习笔记05拦截器、静态资源放行、RESTFUL风格

8、多拦截器执行流程

自定义多个拦截器,示例拦截器1号

/**
 * 
 * @author Dunka
 * @Time   2019年3月4日
 * @Todo   自定义拦截器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 渲染页面后处理");
	}
}

在spring容器注入所需的拦截器

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

控制台输出结果:

【SSM_SpringMVC】学习笔记05拦截器、静态资源放行、RESTFUL风格

总结:五条拦截器规则

(1)preHandler 预处理:根据拦截器定义的顺序,正向执行;

(2)postHandler 后处理:根据拦截器定义的顺序,逆向执行;

(3)afterCompletion 渲染后处理:根据拦截器定义的顺序,逆向执行;

(4)postHandler 后处理:所有拦截器都返回成功调用;

(5)afterCompletion 渲染后处理:preHandler返回true调用;

9、拦截器的应用--用户登录校验、登录异常

/**
 * 
 * @author Dunka
 * @Time   2019年3月4日
 * @Todo	自定义登陆异常
 */
public class MyLoginException extends Exception {
	private String msg;
	private Object obj;
	public MyLoginException(String msg) {
		super();
		this.msg = msg;
	}
	
	public MyLoginException(Object obj,String msg) {
		super();
		this.msg = msg;
		this.obj = obj;
	}
	
	public Object getObj() {
		return obj;
	}

	public String getMsg() {
		return msg;
	}
	
}

自定义全局异常处理类 

	//处理自定义登陆异常
	@ExceptionHandler(MyLoginException.class)
	String MyLoginException(MyLoginException e,Model model) {
			String msg = e.getMsg();
			Object obj = e.getObj();
			model.addAttribute("errorMsg", msg);
			model.addAttribute("username", obj.toString());
			//设置视图名
			return "login_page";
	}
/**
 * 
 * @author Dunka
 * @Time   2019年3月4日
 * @Todo	登陆拦截器
 */
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;
	}
	
}
/**
 * 
 * @author Dunka
 * @Time   2019年3月4日
 * @Todo	登陆
 */
@Controller
@RequestMapping("/login/")
public class LoginController {
	
	//登陆请求
	
	//登陆成功 重定向到列表页
	@RequestMapping(value="login.do",method=RequestMethod.POST)
	public String login(HttpSession session,User u) throws MyLoginException {
		
		User user = new User();
		user.setUsername("Dunka");
		user.setPassword("123");
		if(u.getUsername().equals(user.getUsername())) {
			//用户名一致
			System.out.println("用户名一致");
			if(u.getPassword().equals(user.getPassword())) {
				System.out.println("密码一致");
				session.setAttribute("user", u);
			}else {
				System.out.println("密码错误");
//				throw new MyLoginException("密码错误");
				//用户名回显
				throw new MyLoginException(u.getUsername(),"密码错误");
			}
		}else {
			System.out.println("用户名错误");
			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";
		
	}
	
}

10、静态资源放行

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

(2)在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>*.png</url-pattern>
 	<url-pattern>*.woff</url-pattern>
 	<url-pattern>*.ttf</url-pattern>
 	<url-pattern>*.js</url-pattern>
 </servlet-mapping> 

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

a) 要开启mvc:annotation-driven注解驱动;

<!-- 静态资源放行 -->
	<mvc:resources location="/css/" mapping="/css/*"/>
	<mvc:resources location="/fonts/" mapping="/fonts/**"/>
	<mvc:resources location="/js/" mapping="/js/**"/>
	<mvc:resources location="/picture/" mapping="/picture/**"/>
	<!-- 开启注解驱动 -->
	<mvc:annotation-driven/>

b) 如果配置了拦截器,需要在拦截器中进行过滤,否则会被拦截;

<!-- 登陆拦截器 -->
		<mvc:interceptor>
			<mvc:mapping path="/**"/>
			<!-- 不拦截静态资源 -->
			<mvc:exclude-mapping path="/css/**"/>
			<mvc:exclude-mapping path="/fonts/**"/>
			<mvc:exclude-mapping path="/js/**"/>
			<mvc:exclude-mapping path="/picture/**"/>
			<bean class="com.dunka.interceptor.LoginInterceptor"/>
		</mvc:interceptor>
	</mvc:interceptors>	

c)路径名不要打错;

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

在SpringMVC中使用RestFul风格开发

ItemController:

//RestFul风格开发
	@RequestMapping(value="{item_id}",method = RequestMethod.GET)
	public String selectOnRestFul(@PathVariable("item_id")String id,Model model) {
		ItemInfo item = service.selectItemInfoById(id);
		model.addAttribute("item", item);
		return "item_info";
	}

item_info:

<%@ page language="java" contentType="text/html; charset=utf-8"
    pageEncoding="utf-8"%>
<!DOCTYPE html>
<html>
<head>
<meta 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="返回"  onclick="window.location=${pageContext.request.contextPath}/item/allList.do">
</body>
</html>

item_list:

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

除了通过列表上的查询按钮可以查看信息

还可以通过http://localhost:8080/ssm_project_springmvc/item/{item_id}直接获取对应id的相关信息

配合ajax使用restFul风格开发

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


//配合ajax使用RestFul风格开发
	        function restFul(id){
	        	$.ajax({
	        		type:"get",
	        		url:"${pageContext.request.contextPath }/item/"+id,
	        		success:function(data){
	        			window.location ="${pageContext.request.contextPath }/item/"+id;
	        		}
	        	});
	        }
	//配合ajax 使用RestFul风格开发
	@RequestMapping(value="{item_id}",method = RequestMethod.GET)
//	@ResponseBody
	public String RestFul(@PathVariable("item_id")String id,Model model) {
		System.out.println("id="+id);
		ItemInfo item = service.selectItemInfoById(id);
		model.addAttribute("item", item);
		return "item_info";
	}