SpringMVC
1. SpringMVC
1) MVC模型
M-Model模型
模型(Model)的职责是负责业务逻辑,包含两层:业务数据和业务处理逻辑,比如实体类,DAO,Service都属于模型层
V-View视图
视图(View)的职责是负责显示界面和用户交互(收集用户信息),属于视图层的组件是不包含业务逻辑和控制逻辑的JSP
C-Controller控制器
控制器是模型层与视图层之间的桥梁,用于控制流程,比如在Servlet项目中单一控制器ActionServlet
(线程不安全,比如一个人负责多个请求,如果操作共同的数据的话会产生相应的影响)
2) 什么是SpringMVC
SpringMVC是Spring框架中一个功能模块,实现了MVC结构,便于简单,快速开发的MVC结构的WEB程序,SpringMVC提供的API封装了WEB开发中常用的功能,简化了WEB过程
3) Spring MVC的核心组件
Spring MVC提供了M,V和C相关的主要实现组件,具体如下:
DispatcherServlet(控制器,请求入口)
HandlerMapping(控制器,请求派发)
Controller(控制器,请求处理流程)
ModelAndView(模型,封装)
ViewResolver(视图、视图显示处理器)
4) Spring处理流程
浏览器向服务器发送请求,请求交给前端控制器DispatcherServlet处理,前端控制通过HandlerMapping找到相对应的Controller,执行Controller组件的约定方法处理请求,在约定方法中调用模型层组件完成业务处理,约定方法返回一个ModelAndView对象,此对象封装了处理结果数据和视图名称信息,前端控制器接收到ModelAndView之后调用ViewResolver来定位View(JSP),传递数据信息,生成响应页面
2. 基于XML配置的MVC应用
搭建Spring MVC环境
1) 创建WEB工程,导入SpringMVC相关开发包:Spring IOC,web,webMVC等开发包
2) 在src下添加Spring XML配置文件,名称可以自定义,例如spring-mvc.xml
<!-- 声明Controller --> <bean id="helloController" class="com.xms.controller.HelloController"></bean>
<!-- 定义请求处理映射HandlerMapping --> <bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"> <!-- 指定请求和Controller对应关系 --> <property name="mappings"> <props> <prop key="/hello/hello.do">helloController</prop> </props> </property> </bean>
<!-- 定义视图解析器 ViewResolver--> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/jsp/"></property> <property name="suffix" value=".jsp"></property> </bean> |
3) 在web.xml中配置DispatcherServlet前端控制器组件,DispatcherServlet组件在Spring MVC中已提供,只需要配置即可,配置DispatcherServlet时,同时指定XML配置文件
<servlet> <servlet-name>springMVC</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet>
<servlet-mapping> <servlet-name>springMVC</servlet-name> <url-pattern>*.do</url-pattern> </servlet-mapping> |
Controller组件负责执行具体的业务处理,编写时需要实现Controller接口及约定方法HandleRequest
Controller接口及约定方法handleRequest
public class HelloController implements Controller {
public ModelAndView handleRequest(HttpServletRequest arg0, HttpServletResponse arg1) throws Exception {
System.out.println("Hello.Spring MVC");
return new ModelAndView("hello"); } } |
Controller组件中约定的handleRequest方法执行后会返回一个ModelAndView对象,此对象封装模型数据和视图名称
ModelAndView(String viewName)
ModelAndView(String viewName,Model model)
viewName是视图名称,model是业务处理的数据
通过HandlerMapping组件,DispatcherServlet控制器可以将客户端的Http请求映射到对应的Controller组件上
SimpleUrlHandlerMapping维护一个Http请求和Controller映射关系表(Map),根据列表对应关系调用Controller
ViewResolver组件,Controller组件返回一个ModelAndView对象,Spring中的视图以名字为标识,视图解析器ViewResolver通过名字来解析视图
InternalResourceViewResolver:UrlBasedViewResolver的子类,它支持InternalResourceView(对Servlet和JSP的包装),以及子类 JstlView和TitlesView响应类型
3. 基于注解配置的MVC应用
推荐使用@Controller声明Controller组件,可以使Controller控制器更加灵活,可以不用实现Controller接口,请求处理方法也可以灵活的定义。
为了使@Controller注解生效,需要在Spring的XML配置文件中开启组件扫描定义。
<context:componnent-scanbase-package=""/>
RequestMapping
@RequestMapping注解可以使用类定义和方法定义上,表明此组件或方法与哪一个请求对应。
@Controller @RequestMapping("/demo") //命名空间 public class HelloController {
@RequestMapping("/hello.do") //地址 public ModelAndView execute(){ System.out.println("hello.Controller"); return new ModelAndView("/jsp/hello"); //返回的jsp对应地址 } } |
Spring3.1版本之前
开启@RequestMapping注解映射时,需要在Spring的XML配置文件中定义RequestMappingHandlerMapping(类定义前)和RequestMappingHandlerAdapter(方法定义前)两个Bean组件。
<!-- 开启注解扫描 --> <context:component-scan base-package="com.xms"/>
<!-- 开启RequestMapping注解扫描 --> <mvc:annotation-driven/>
<!-- 定义视图解析器ViewResolver --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/jsp/"></property> <property name="suffix" value=".jsp"></property> </bean> |
从3.2版本开始可以使用下面XML配置简化(spring.xml)
<mvc:annotation-driven/>
4. 实战技巧
1) 接收请求参数
index.jsp <%@ page language="java" pageEncoding="utf-8"%> <h1>表单</h1> <form action="demo/testThree.do" method="post"> 账号:<input name="username"/><br/> 密码:<input type="password" name="password"/><br/> <input type="submit" value="提交"/> </form> |
springMVC请求提交数据到控制器有以下方式
1.使用HttpServletRequest获取
Spring自动参数注入HttpServletRequest,优点直接,缺点需要自己处理数据类型转换
@Controller @RequestMapping("/demo") public class DemoController { //Request接收参数 @RequestMapping("/testOne.do") public ModelAndView testOne(HttpServletRequest request){ String username = request.getParameter("username"); String password = request.getParameter("password"); System.out.println(username); System.out.println(password); return new ModelAndView("hello"); } |
2.使用@RequestParam注解
Spring会自动将表单参数注入到方法参数(名称一致),
@RequestMapping("/testTwo.do") public ModelAndView testTwo(String username,String password){ System.out.println(username+""+password); return new ModelAndView("hello"); } |
使用@RequestParam注解映射不一致的名称,优点参数类型自动转换,但可能出现类型转换异常
@RequestMapping("/testTwo.do") public ModelAndView testTwo(@RequestParam("username")String name, @RequestParam("password")String pwd){ System.out.println(name+""+pwd); return new ModelAndView("hello"); } |
3.使用自动机制封装成Bean对象
定义实体类,属性名必须与请求参数名相同
@RequestMapping("/testThree.do") public ModelAndView testTwo(User user){ System.out.println(user.getUsername()); System.out.println(user.getPassword()); return new ModelAndView("hello"); } |
2) 向页面传值
当Controller组件处理后,需要向jsp传值时的方式
1.直接使用HttpServletRequest和Session
2.使用ModelAndView对象
在Controller处理方法完成后返回一个ModelAndView对象,包含显示视图名称和模型数据
//使用ModelAndView对象传递数据 @RequestMapping("/testFour.do") public ModelAndView testFour(){ Map<String,Object> data = new HashMap<String,Object>(); data.put("success",true); data.put("message","操作成功"); return new ModelAndView("hello",data); } |
3.使用ModelMap参数对象
在Controller处理办法中追加一个ModelMap参数类型
//ModelMap传递数据 @RequestMapping("/testFive.do") public ModelAndView testFive(ModelMap map){ map.put("success",false); map.put("message","操作失败"); return new ModelAndView("hello"); //只需传viewName即可 } |
4.使用@ModelAttribute注解
在Controller方法的参数部分或Bean属性get方法上使用
//ModelAttribute传递数据 @RequestMapping("/testSix.do") public ModelAndView testSix(@ModelAttribute("username")String name){ name="zs"; return new ModelAndView("hello"); //只需传viewName即可 } |
//@ModelAttribute传递Bean属性 @ModelAttribute("age") public Integer getAge(){ return 25; } |
注意:数据会利用HttpServletRequest的Attribute传递到jsp页面
3) 重定向视图
SpringMVC默认采用转发方式定位视图,如果需要重定向方式,可以采用以下方式
1.使用RedirectView
2. 使用redirect:前缀
如果Controller的请求处理方法返回的是ModelAndView对象,可以使用RedirectView的方式重定向,实例代码:
public ModelAndView checkLogin(){
RedirectView view = new RedirectView(重定向URL)
return new ModelAndView(view);
}
如果Controller的请求处理方法返回的是String类型,可以使用“redirect:前缀”方式重定向,实例对象
public String checkLogin(){
return "redirect:重定向URL"
}
MVC实操练习
1. 登录
开发步骤
1) 创建项目,导包
2) 配置DispatcherServlet
3) 配置spring.xml
请求1:
在Controller中增加打开登录页面的方法,创建登录页面
LoginController: toLogin(登录界面)
LoginService:
请求2:
在DAO中增加账号查询用户的方法
UserDao:
在Service中增加验证账号和密码的方法
创建登录页面:
LoginController:Login(登录界面+返回消息)
2. 练习资费列表
点击资费管理的时候跳转到cost列表
cost表
cost数据
MVC实操问题解决
1.实战技巧问题
1) SpringCharacterEncodingFilter
CharacterEncodingFilterpostweb.xmlCharacterEncodingFilter
!-- 过滤器 设置编码格式为utf-8--> <filter> <filter-name>encodingFilter</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>encodingFilter</filter-name> <url-pattern>/*</url-pattern><!-- 所有的地址都走该过滤器 --> </filter-mapping> |
2) 异常处理SpringMVC处1. 使springMVC提SimpleMappingExceptionResolver
<!-- 全局异常配置 --> <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"> <property name="exceptionMappings"> <props> <prop key="java.lang.Exception">main/error</prop> </props> </property> </bean> |
2. 实现handlerExceptionResolver接口配置
3. 使用exceptionHandler注解
//局部异常处理 @ExceptionHandler public String executeException(Exception ex,HttpServletRequest request) throws Exception{ if(ex instanceof LoginException){ request.setAttribute("message",ex.getMessage()); return "main/error"; }else{ throw ex; } } |
注意:1、3使用较多,2使用不多
3) 拦截器 拦截器必须实现HandlerInterceptor接口
preHandle() 处理器执行前调用,方法返回true表示会继续调用其他拦截器或者处理器,返回false表示中断流程,不会执行后续拦截器和处理器
postHandle() 处理器执行后,视图处理调用前,此时可以通过ModelAndView对象对模型数据进行处理或对视图进行处理
afterCompletion() 整个请求处理完毕后调用,如性能监控中可以在此记录结束时间,输出消耗时间,可以进行资源清理,只有preHandle返回true时才会执行afterCompletion方法。
自定义拦截器的配置 <mvc:interceptors> <mvc:interceptor> -->需要拦截的URL <mvc:mapping path=" "/> -->不需要拦截的URL <mvc:exclude-mapping path=""> -->拦截器组件 <bean class=" "> </mvc:interceptor> </mvc:interceptors>
<!-- 拦截器配置 --> <mvc:interceptors> <mvc:interceptor> <mvc:mapping path="/**"/> <!-- 拦截所有的url地址,除了以下的,比如登录页面 --> <mvc:exclude-mapping path="/login/*"/> <bean class="com.xms.interceptor.LoginInterceptor"/> </mvc:interceptor> </mvc:interceptors> |
提示:Interceptor接口需要实 HandlerInterceptorAdapter
2.完善SpringMyBatisDay05_02
练习
增删改查排序
SpringMVC+JDBC
1. Spring对JDBC整合支持
spring对DAO提供哪些支持?
1) spring对DAO异常提供统一处理
2) spring对DAO编写提供支持的抽象类
3) 提供编程效率,减少JDBC编码量
spring对DAO异常支持
spring把特定某种技术的异常,如SQLException,统一的转化为自己的异常,异常以DataAccessException为父类。它封装原始的异常对象,不会丢失原始的错误信息
DataAccessException继承于RuntimeException,是非检查异常,不会因为没有处理异常而出现编译错误,异常必须处理可以用拦截器或者在页面统一处理
spring对DAO编写支持
spring为了便于以一种一致的方式使用各种数据访问技术,如JDBC,Hibernate,MyBatis,Spring提供一套抽象的DAO类,这些抽象类提供一些方法,通过它们可以获得与数据访问技术相关的数据源和其他配置信息
JdbcTemplate:封装常用JDBC方法
HibernateTemplate:封装常用Hibernate方法
JdbcDaoSupport:JDBC数据访问对象的基类
HibernateDaoSupport:Hibernate数据访问对象的基类
jdbcDaoSupport
利用JDBC技术编写DAO的父类,通过此类提供的方法,可便于获取Connection和JdbcTemplate对象信息
JdbcDaoSupport使用时需要注入一个DataSource对象
JdbcDaoSupport对代码有一定的侵入性
JdbcTemplate
封装了连接获取以及连接释放等工作,从而简化我们对JDBC的使用避免忘记关闭连接等错误
JdbcTemplate提供以下主要方法:
queryForInt()
queryForObject()
query()
update()
execute()
如何编写DAO组件
基于jdbc技术编写DAO组件可以采用以下两种方式:
1) DAO继承JdbcDaoSupport,通过getJdbcTemplate()方法来获取JdbcTemplate对象,需要在DAO实现类中注入一个DataSource对象来完成JdbcTemplate的实例化
2) DAO组件不继承JdbcDaoSupport,在Spring容器中配置一个JdbcTemplate的Bean,然后注入给DAO实现类
员工表
create table emp(
empno int(4) primary key auto_increment,
ename varchar(10) not null,
salary double(7,2),
bonus double(5,2),
hiredate date,
deptno int(4)
);
insert into emp values(1001,'张三',3333.33,333.33,now(),10);
insert into emp values(1002,'李四',4444.44,444.44,now(),20);
insert into emp values(1003,'王五',5555.55,555.55,now(),30);
insert into emp values(1004,'赵六',6666.66,666.66,now(),40);
部门表:
create table dept(
deptno int(4) primary key auto_increment,
deptnamevarchar(20) not null,
deptlevel varchar(20),
deptcreatedate date,
depttotalperson int(4)
);
insert into dept values(10,'技术部','B',now(),66);
insert into dept values(20,'研发部','A',now(),77);
insert into dept values(30,'销售部','B',now(),88);
insert into dept values(40,'市场部','A',now(),99);
2. Spring+ JDBC Template
1) 创建工程,搭建Spring MVC和JDBC技术环境
引入数据库驱动包
引入DBCP连接池开发包
添加Spring相关技术环境
引入Spring IoC
在src下添加spring.xml
web.xml. 配置DispatcherServlet主控制器
2) 基于jdbcTemplate实现DAO组件
根据数据表编写实体类
编写DAO接口和实现类
在Spring容器中配置DAO实现类
定义DAO对象,注入jdbcTemplate
3) 编写和配置Spring MVC 主要组件,如Controller
HandlerMapping, viewResolver
编写Controller和请求处理方法
配置<mvc:annotation-driven/>支持@Requestmapping
配置Controller组件
开启组件扫描,将Controller扫描到Spring容器
需要DAO时采用注入方式注入
在请求处理方法上使用@RequestMapping指定对应请求配置ViewResolver
4) 编写JSP视图组件,利用JSTL标签和EL表达式显示数据