Spring Web MVC
Spring Web MVC需要使用IOC功能。
用于开发MVC结构的Web程序。
一.MVC思想
将程序组件分为模型,视图,控制器三部分。
二.Spring如何实现MVC
a.浏览器发出一个HTTP请求
b.请求首先进入DispatcherServlet主控制器
c.主控制器调用HandlerMapping组件根据请求找映射的Controller处理
d.执行Controller处理方法,将返回结果给ViewResolver组件
e.ViewResolver组件根据Controller返回结果定位视图JSP,将模型数据传递给JSP
f.由JSP生成响应结果,给浏览器输出
发请求到DispatcherServlet,然后到HandlerMapping到Controller1接下来返回一个ViewResolver到视图。
eg:页面上发出hello.do请求,首先经过web.xml,知道.do请求需要进入到DispatcherServlet,DispatcherServlet去applicationContext.xml里面
寻找handlerMapping组件,根据mapping名为hello.do找hello.do找helloController组件处理。根据helloController里的ModelAndView和applicationContext.xml的prefix和suffix配置去找到/WEB-INF/hello.jsp
eg1:显示登录页面
/tologin.do
—>DispatcherServlet(配置)//充当主控制器,发请求时先给他
—>hanlderMapping(配置)//定义Servlet请求和Controller对应关系,根据applicationContext.xml配置解析对应的哪一个Controller
—>toLoginController(编写+配置)//调用DAO模型组件
—>ViewerResolver(配置)//封装,转发,重定向到JSP视图
—>WEB-INF/login.jsp(编写)
3.Spring Web MVC处理流程
a.RequestMappingHandlerMapping组件
@RequestMapping(“login.do”)该标记用在Controller业务方法前
b.Controller编写和配置
取消了实现Controller接口及方法约定,可以允许程序员按需灵活定义业务方法;
public ModelAndView或String 方法名(根据request,session,response)
Controller需要扫描到Spring容器,必须使用@Controller
eg: public String execute(){
return “hello”;
}
d.Controller如何接收请求参数
1)利用HttpServletRequest
*2)利用业务方法参数(少量参数时使用)
*–参数名与请求参数key保持一致
—利用@RequestParam(“key")
*3)利用实体对象当方法参数(大量参数时使用)
使用建议:少量参数使用2);大量参数使用3);如果客户端表单数据没有格式检查,遇到非字符串类型参数建议使用1)
e.如何向响应JSP传值
*1)利用HttpServletRequest
2)利用ModelAndView做返回值
*3)利用ModelMap方法参数
4)使用@ModelAttribute(“key")
public String checkLogin(@ModuleAttribute(“user”) String username){
return “ok”;}//ok.jsp使用${user}
@ModelAttribute(“user")
public String getName(){
return “tom”;}
等价于model.put(“user”, getName());//${user}即tom
f.Controller如何使用Session
代码示例:
web.xml:
<servlet> <servlet-name>webLogin2</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext.xml</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>webLogin2</servlet-name> <url-pattern>*.do</url-pattern> </servlet-mapping>
handlermapping和controller:
@Controller public class LoginController { //登录按钮处理 @RequestMapping("/login.do") public String checkLogin3(String username, String password, ModelMap modelMap, HttpSession session){ if ("root".equals(username) && "1234".equals(password)){ modelMap.put("user", username); session.setAttribute("username", username); return "ok";//ok.jsp 使用${user} } else { modelMap.put("msg", "用户名或密码错误"); return "login";//login.jsp使用${msg} } }
spring配置:
<!--等价于handlermapping--> <mvc:annotation-driven></mvc:annotation-driven> <context:component-scan base-package="controller"> </context:component-scan> <!--配置viewerResolver--> <bean id="viewresolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <!--去prefix配置下找页面--> <property name="prefix" value="/WEB-INF/"> </property> <!--提取出.jsp结尾文件,文件名为Controller中ModelAndView返回的名字--> <property name="suffix" value=".jsp"> </property> </bean>
ok.jsp:
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> </head> <body> <form action="ok.do" method="post"> <h3>${user} login success</h3> session内容: ${sessionScope.username} </form> </body> </html>
login.jsp:
<%@ page language="java" pageEncoding="UTF-8"%> <html> <head> </head> <body> <h3>用户登录</h3> ${msg} <form action="login3.do" method="post"> 用户名:<input type="text" name="username"><br/> 密码:<input type="password" name="password"><br/> <input type="submit" value="登录"> </form> </body> </html>
访问:http://localhost:8090/webLogin2_war(此处为自己定义的war包名)/login.do
用正确的用户名密码进入显示:
root login success
session内容: root
4.Spring Web MVC
1) 解决中文接收乱码问题
<!--spring mvc解决中文乱码-->
<filter>
<filter-name>myfilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>myfilter</filter-name>
<url-pattern>*.do</url-pattern>
<!--或者写<servlet-name>webLogin2</servlet-name>-->
</filter-mapping>
2)如何处理异常
a.全局异常处理:SimpleMappingExceptionResolver
@Controller public class ExceptionController { @RequestMapping("/exception.do") public String ex(){ String s = null; s.length(); return "ok"; } }
此时访问exception.do会抛出nullpoint异常,需要进行异常处理,使用内置的全局异常处理方法
applicationContext.xml配置:
<!--异常处理器--> <!--<prop key="异常类型">视图名</prop>--> <!--抛出异常后得到error视图名传递给viewResolver--> <!--<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"> <property name="exceptionMappings"> <props> <prop key="java.lang.Exception">error</prop> </props> </property> </bean>-->
此时处理流程图:
b.局部异常处理:@ExceptionHandler
public String xxx(HttpServletRequest request, Exception e){}
@Controller public class AgeController { @RequestMapping("/toage.do") public String toage(){ //检查session里是否有username return "age";//进入age.jsp } @RequestMapping("/age.do") public String age(String birth, ModelMap modelMap) throws Exception { //接收用户输入的生日,计算年龄 Date now = new Date(); SimpleDateFormat sdf = new SimpleDateFormat("YYYY-MM-DD"); Date birth2 = sdf.parse(birth); int result = now.getYear() - birth2.getYear(); modelMap.put("msg", "年龄为: " + result); return "age";//进入age.jsp,${msg} //当出现异常时无法返回String故进入handleException方法 } /*当前Controller异常处理, * 当执行该方法后,不会再调用ExceptionResolver */ @ExceptionHandler//局部异常处理方法 public String handleException(HttpServletRequest request, Exception e) { request.setAttribute("msg", "输入信息有误导致计算失败"); return "age";//返回age.jsp } }
c.自定义ExceptionResolver(实现HandlerExceptionResolver接口)
先写自己的异常处理类:
public class MyExceptionHandler implements HandlerExceptionResolver { public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object method, Exception e) { //将异常信息写入文件 System.out.println("将异常信息写入文件: " + e); //跳转到错误页面 ModelAndView mav = new ModelAndView(); mav.setViewName("error"); return mav; } }
eorror.jsp
<%@ page language="java" pageEncoding="UTF-8" %> <html> <head> </head> <body> <h3>系统繁忙</h3> </body> </html>
注释掉applicationContext.xml中的全局异常处理,写上自己的异常处理类:
<!--使用自定义的ExceptionResolver, 访问exception.do--> <bean class="controller.MyExceptionHandler"> </bean>
此时访问exception.do当程序出错时页面将显示系统繁忙字样
3)如何实现登录权限检查
使用session进行约定值判断。
实现方法:1.采用Filter(通用解决方法);2.采用拦截器(Spring WEB MVC)
a.拦截器组件简介
拦截器组件时SpringMVC特有组件。
拦截器组件可以在Controller之前拦截;可以在Controller之后拦截;可以在JSP解析完毕给浏览器输出之前拦截。
b.拦截器使用方法
首先编写一个拦截器组件(实现HandlerInterceptor接口)
在约定方法中添加要插入的逻辑然后在applicationContext.xml中配置
拦截器类:
import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; public class LoginInterceptor implements HandlerInterceptor { @Override //controlller之前,权限检查,登录检查 public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("---preHandle实现登录检查---"); HttpSession session = request.getSession(); //获取登录成功后放置的用户信息 String name = (String) session.getAttribute("username"); if (name != null) {//登录过 return true;//继续执行mvc后续流程 } else {//登录失效(session失效)或登录失败 response.sendRedirect("/tologin.do"); return false;//终止mvc后续流程 } } @Override //controller之后,统计请求到处理开始到完毕的日志,执行的时间性能监控,检查耗时项 public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("---postHandle---"); } @Override //请求处理完毕,输出之前。统计请求到处理开始到完毕的日志,执行的时间性能监控,检查耗时项 public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("---afterHandle---"); } }
applicationContext.xml
<!--配置拦截器--> <mvc:interceptors> <mvc:interceptor> <!--拦截哪些请求--> <!--<mvc:mapping path="toage.do"/>--> <mvc:mapping path="/**/"/> <!--放过哪些请求--> <mvc:exclude-mapping path="/tologin.do"/> <mvc:exclude-mapping path="/login3.do"/> <bean class="controller.LoginInterceptor"/> </mvc:interceptor> </mvc:interceptors>
原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/198055.html