【SSM_SpringMVC】学习笔记05拦截器、静态资源放行、RESTFUL风格
一、拦截器
SpringMVC中的拦截器:
1、SpringMVC拦截器帮我们按照一定规则拦截请求,后根据开发人员自定义的拦截逻辑进行处理;
2、自定义拦截器需要实现HandlerInterceptor接口;
3、自定义的拦截器实现类需要在SpringMVC配置文件中配置;
4、可以配置多个拦截器,配置的顺序会影响到拦截器的执行顺序,先配先执行
5、HandlerInterceptor共3个接口:
a) preHandler 预处理:在拦截方法前执行;
b) postHandler 后处理:在拦截方法后执行;
c) afterCompletion 渲染后处理:在页面渲染后执行;
6、拦截器也体现了AOP思想
7、应用:权限检查、日志记录、性能检测等;
拦截器的执行流程图:(图来自www.sikiedu.com)
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>
控制台输出结果:
总结:五条拦截器规则
(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";
}