springmvc概述
SpringMvc介绍
什么是springmvc
Spring Web MVC是一种基于Java的实现了Web MVC设计模式的请求驱动类型的轻量级Web框架,即使用了MVC架构模式的思想,将web层进行职责解耦,基于请求驱动指的就是使用请求-响应模型,框架的目的就是帮助我们简化开发,Spring Web MVC也是要简化我们日常Web开发的。
springmvc优势
1、清晰的角色划分:前端控制器(DispatcherServlet)、请求到处理器映射(HandlerMapping)、处理器适配器(HandlerAdapter)、视图解析器(ViewResolver)、处理器或页面控制器(Controller)、验证器( Validator)、命令对象(Command 请求参数绑定到的对象就叫命令对象)、表单对象(Form Object 提供给表单展示和提交到的对象就叫表单对象)。
2、分工明确,而且扩展点相当灵活,可以很容易扩展,虽然几乎不需要;
3、由于命令对象就是一个POJO,无需继承框架特定API,可以使用命令对象直接作为业务对象;
4、和Spring 其他框架无缝集成,是其它Web框架所不具备的;
5、可适配,通过HandlerAdapter可以支持任意的类作为处理器;
6、可定制性,HandlerMapping、ViewResolver等能够非常简单的定制;
7、功能强大的数据验证、格式化、绑定机制;
8、利用Spring提供的Mock对象能够非常简单的进行Web层单元测试;
9、本地化、主题的解析的支持,使我们更容易进行国际化和主题的切换。
10、强大的JSP标签库,使JSP编写更容易。
还有比如RESTful风格的支持、简单的文件上传、约定大于配置的契约式编程支持、基于注解的零配置支持等等。
springmvc运行原理
核心架构的具体流程步骤如下:
1、 首先用户发送请求——>DispatcherServlet,前端控制器收到请求后自己不进行处理,而是委托给其他的解析器进行处理,作为统一访问点,进行全局的流程控制;
2、DispatcherServlet——>HandlerMapping,HandlerMapping将会把请求映射为HandlerExecutionChain对象(包含一个Handler处理器(页面控制器)对象、多个HandlerInterceptor拦截器)对象,通过这种策略模式,很容易添加新的映射策略;
3、 DispatcherServlet——>HandlerAdapter,HandlerAdapter将会把处理器包装为适配器,从而支持多种类型的处理器,即适配器设计模式的应用,从而很容易支持很多类型的处理器;
4、 HandlerAdapter——>处理器功能处理方法的调用,HandlerAdapter将会根据适配的结果调用真正的处理器的功能处理方法,完成功能处理;并返回一个ModelAndView对象(包含模型数据、逻辑视图名);
5、 ModelAndView的逻辑视图名——> ViewResolver, ViewResolver将把逻辑视图名解析为具体的View,通过这种策略模式,很容易更换其他视图技术;
6、 View——>渲染,View会根据传进来的Model模型数据进行渲染,此处的Model实际是一个Map数据结构,因此很容易支持其他视图技术;
7、返回控制权给DispatcherServlet,由DispatcherServlet返回响应给用户,到此一个流程结束。
框架组件
DispatcherServlet:前端控制器
用户请求到达前端控制器,它就相当于mvc模式中的c,dispatcherServlet是整个流程控制的中心,由它调用其它组件处理用户的请求,dispatcherServlet的存在降低了组件之间的耦合性。
HandlerMapping:处理器映射器
HandlerMapping负责根据用户请求找到Handler即处理器,springmvc提供了不同的映射器实现不同的映射方式,例如:配置文件方式,实现接口方式,注解方式等。
Handler:处理器
Handler 是继DispatcherServlet前端控制器的后端控制器,在DispatcherServlet的控制下Handler对具体的用户请求进行处理。
由于Handler涉及到具体的用户业务请求,所以一般情况需要程序员根据业务需求开发Handler。
HandlAdapter:处理器适配器
通过HandlerAdapter对处理器进行执行,这是适配器模式的应用,通过扩展适配器可以对更多类型的处理器进行执行。
View Resolver:视图解析器
View Resolver负责将处理结果生成View视图,View Resolver首先根据逻辑视图名解析成物理视图名即具体的页面地址,再生成View视图对象,最后对View进行渲染将处理结果通过页面展示给用户。
View:视图
springmvc框架提供了很多的View视图类型的支持,包括:jstlView、freemarkerView、pdfView等。我们最常用的视图就是jsp。
一般情况下需要通过页面标签或页面模版技术将模型数据通过页面展示给用户,需要由程序员根据业务需求开发具体的页面。
说明:在springmvc的各个组件中,处理器映射器、处理器适配器、视图解析器称为springmvc的三大组件。
需要用户开放的组件有handler、view
springmvc与struts2不同
springmvc的入口是一个servlet即前端控制器,而struts2入口是一个filter过虑器。
springmvc是基于方法开发(一个url对应一个方法),请求参数传递到方法的形参,可以设计为单例或多例(建议单例),struts2是基于类开发,传递参数是通过类的属性,只能设计为多例。
Struts采用值栈存储请求和响应的数据,通过OGNL存取数据, springmvc通过参数解析器是将request请求内容解析,并给方法形参赋值,将数据和视图封装成ModelAndView对象,最后又将ModelAndView中的模型数据通过reques域传输到页面。Jsp视图解析器默认使用jstl。
springmvc与struts2有什么区别?
1. 底层实现机制
struts2:filter
springmvc:servlet
2. 运行效率
struts2:底层是Servlet,参数基于属性封装,如果配置单例,会出现线程安全问题,所以配置多例
springmvc:底层是Servlet,单例
3. 参数封装
struts2:基于属性封装
springmvc:基于方法进行封装
入门案例
- 创建工程
- 导jar包
- 写好页面
- 创建Controller
@Controller
public class UserController {
/**
* 测试modelandview
* @return
*/
@RequestMapping("hello")
public ModelAndView hello(){
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("username", "张三");
// modelAndView.setViewName("/WEB-INF/jsp/hello.jsp");//物理视图
modelAndView.setViewName("hello");//设置逻辑视图
return modelAndView;
}
}
创建springmvc.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xmlns:dubbo="http://code.alibabatech.com/schema/dubbo" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd"> <!-- 包扫描,指定扫描包,把Controller交给spring管理 --> <context:component-scan base-package="cn.aric.controller" /> <!-- 注解 --> <mvc:annotation-driven /> <!-- 处理器映射器:根据bean的name进行查找Handler 将action的url配置在bean的name中 --> <!-- 这是一个默认的映射处理器,即使不配置,那么也是默认就是这个 --> <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"></bean> <!-- 处理器适配器:这个适配器不是必须配置的,这是默认的、他在servlet容器已启动就被加载 --> <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"></bean> <!-- 配置视图解析器 --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <!-- 配置逻辑视图前缀 --> <property name="prefix" value="/WEB-INF/jsp/" /> <!-- 配置逻辑视图后缀 --> <property name="suffix" value=".jsp" /> </bean> </beans>
在web.xml中配置前端控制器
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5"> <display-name>springmvc</display-name> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> <!-- 配置编码过滤器 --> <filter> <filter-name>characterEncoding</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>characterEncoding</filter-name> <!-- 拦截所有的请求 ,所有的请求都被编码--> <url-pattern>/*</url-pattern> </filter-mapping> <!-- 前端控制器 --> <servlet> <servlet-name>springmvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <!-- springmvc默认加载springmvc配置文件,满足规范:命名规范:<servlet-name>-servlet.xml如:springmvc-servlet.xml 路径存储规范:WEB-INF/ --> <!-- 加载自定义配置文件 --> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:springmvc.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> </web-app>
注解驱动的作用:
1. 自动创建处理器映射器
2. 自动创建处理器适配器
3. 支持所有注解
4. 支持json格式数据
参数绑定
springmvc接收参数方式:直接把接收参数变量放在方法中自动接收参数
解决参数乱码
get请求乱码:
1. 再次编码,String(request.getParamter(“userName”).getBytes(“ISO8859-1”),”utf-8”)
2. server.xml设置 URIEncoding=”UTF-8”
<Connector URIEncoding="utf-8" connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443"/>
post请求乱码:
1. 使用spring编码过滤器(web.xml),必须配置在前端控制器之前.
<!-- 配置编码过滤器 -->
<filter>
<filter-name>characterEncoding</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>characterEncoding</filter-name>
<!-- 拦截所有的请求 ,所有的请求都被编码-->
<url-pattern>/*</url-pattern>
</filter-mapping>
接收自定义参数
- 注解:@InitBinder:转换参数
/**
* 需求:接收自定义类型参数,把参数进行转换
*/
@InitBinder
public String transferDate(WebDataBinder binder){
binder.registerCustomEditor(Date.class, new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd"), true));
return "page/sucess";
}
- 自定义转换工具
/**
* 时间转换工具类
*/
public class DateConvert implements Converter<String,Date> {
@Override
public Date convert(String source) {
Date date = null;
//解析页面传递参数
try {
date = new SimpleDateFormat("yyyy-MM-dd").parse(source);
return date;
} catch (ParseException e) {
e.printStackTrace();
}
return date;
}
}
在springmvc.xml中配置
<!-- 转换自定义参数工厂 -->
<bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
<property name="converters">
<set>
<!-- 自定义转换器 -->
<bean class="cn.aric.utils.DateConvert"></bean>
</set>
</property>
</bean>
<!-- 在注解上加上 -->
<mvc:annotation-driven conversion-service="conversionService" />
默认支持的参数类型
- HttpServletRequest:通过request对象获取请求信息
- HttpServletResponse:通过response处理响应信息
- HttpSession:通过session对象得到session中存放的对象
Model/ModelMap:ModelMap是Model接口的实现类,通过Model或ModelMap向页面传递数据.
model.addAttribute("item", item);
页面通过${item.XXXX}获取item对象的属性值。
如果使用Model则可以不使用ModelAndView对象,Model对象可以向页面传递数据,View对象则可以使用String返回值替代。不管是Model还是ModelAndView,其本质都是使用Request对象向jsp传递数据。绑定简单类型:当请求的参数名称和处理器形参名称一致时会将请求参数与形参进行绑定。从Request取参数的方法可以进一步简化。
@RequestMapping("/itemEdit")
public String itemEdit(Integer id, Model model) {
Items items = itemService.getItemById(id);
//向jsp传递数据
model.addAttribute("item", items);
//设置跳转的jsp页面
return "editItem";
}
支持的数据类型
参数类型推荐使用包装数据类型,因为基础数据类型不可以为null
整形:Integer、int
字符串:String
单精度:Float、float
双精度:Double、double
布尔型:Boolean、boolean
接收POJO
如果提交的参数很多,或者提交的表单中的内容很多的时候可以使用pojo接收数据。要求pojo对象中的属性名和表单中input的name属性一致。
如果是包装类型的POJO,包装对象.
public class QueryVo {
private Items items;
}
页面定义:
<input type="text" name="items.name" />
<input type="text" name="items.price" />
Controller方法定义如下:
public String useraddsubmit(Model model,QueryVo queryVo)throws Exception{
System.out.println(queryVo.getItems());
接收数组
/**
* 需求:接收数组类型参数
*/
@RequestMapping("receiveArray")
public String receiveArray(Integer[] ids,Model model){
System.out.println(ids);
model.addAttribute("ids", ids);
return "page/success";
}
接收list
/**
* 需求:接受list类型参数
*/
@RequestMapping("receiveList")
public String receiveList(QueryVo vo,Model model){
model.addAttribute("user", vo.getUser());
return "page/sucess";
}
标签中varStatus属性常用参数总结下:
status.index输出行号,从0开始。
{status.count} 输出行号,从1开始。
status.current当前这次迭代的(集合中的)项
{status.first} 判断当前项是否为集合中的第一项,返回值为true或false
${status.last} 判断当前项是否为集合中的最后一项,返回值为true或false
begin、end、step分别表示:起始序号,结束序号,跳跃步伐。
springmvc注解
常用注解:
1. Controller
2. RequestMapping
3. RequestParam
4. Redirect
5. Forward
6. RequestBody/ResponseBody
Controller
- @Controller:用于标识是处理器类.表示把我的控制器对象交给spring来创建。
Controller起作用:只需要扫描即可。
<!-- 包扫描,指定扫描包,把Controller交给spring管理 --> <context:component-scan base-package="cn.aric.controller" />
RequestMapping
@RequestMapping :请求映射注解
用法举例:
1. @RequestMapping(“list.do”)
2. @RequestMapping(“/list.do”)
3. @RequestMapping(“list”)
4. @RequestMapping(value=”list”)
5. @RequestMapping(value=”list”,method.RequestMethod.POST)
get请求:
1. 所有从浏览器直接发送的请求,都是get请求
2. href发送的请求都是get请求
post:
1. 表单提交是post请求
2. ajax是post请求
URL路径映射
- @RequestMapping:请求到处理器功能方法的映射规则;
- URL路径映射:@RequestMapping(value=”/user”)或@RequestMapping(“/user”)
- RequestMethod请求方法限定
URL模板映射
@RequestMapping(value=”/useredit/{userId}”):{×××}占位符,请求的URL可以是“/useredit/001”或“/useredit/abc”,通过在方法中使用@PathVariable获取{×××}中的×××变量
@RequestMapping("/item/editItem/{id}")
public String editItem(@PathVariable Integer id,Model model){
//调用service接口代理对象
Items items = itemsService.findItemsById(id);
model.addAttribute("item", items);
return "editItem";
}
实现restFul,所有的url都是一个资源的链接,有利于搜索引擎对网址收录。
多个占位符
如果有多个pojo、并且里面具有相同的属性,解决方案:
我们使用包装类来包装pojo、经过包装的pojo相当于加了一层包结构。所以后面即使具有相同的属性也无所谓。
RequestParam
- value:参数名字,即入参的请求参数名字,如value=“studentid”表示请求的参数区中的名字为studentid的参数的值将传入;
- required:是否必须,默认是true,表示请求中一定要有相应的参数,否则将报400错误码;
- defaultValue:默认值,表示如果请求中没有同名参数时的默认值
@RequestParam(defaultValue=”1”,value=”myid”)
功能1:设置默认值
功能2:给参数定义别名,别名和页面传递参数匹配即可
Redirect
Contrller方法返回结果重定向到一个url地址.
- 同一个类内跳转
redirect:add.do 与 redirect:/user/add.do” 在同一个类里面进行跳转。上面2个都可以实现跳转。但是有区别:第一个是同一个根路径下面跳转。第二个是在项目路径下进行跳转。
- 不同的类进行跳转
不同的类进行跳转只能使用:redirect:/user/add.do进行跳转。即是从项目路径下来查询。
redirect方式相当于“response.sendRedirect()”,转发后浏览器的地址栏变为转发后的地址,因为转发即执行了一个新的request和response。
由于新发起一个request原来的参数在转发时就不能传递到下一个url,如果要传参数可以/user/userlist.do后边加参数,如下:
/user/userlist.action?groupid=2&…..
Forward
controller方法执行后继续执行另一个controller方法。
return “forward:/user/userlist.action”;
forward方式相当于“request.getRequestDispatcher().forward(request,response)”,转发后浏览器地址栏还是原来的地址。转发并没有执行新的request和response,而是和转发前的请求共用一个request和response。所以转发前请求的参数在转发后仍然可以读取到。
json数据交互
- @RequestBody注解用于读取http请求的内容(字符串),通过springmvc提供的HttpMessageConverter接口将读到的内容转换为json、xml等格式的数据并绑定到controller方法的参数上。
@RequestBody注解实现接收http请求的json数据,将json数据转换为java对象
@RequestBody/@ResponseBody要依赖Jackson
支持注解,注解映射器和注解适配器可以使用
<mvc:annotation-driven />
代替。<mvc:annotation-driven />
默认注册了注解映射器和注解适配器等bean。
异常处理
springmvc在处理请求过程中出现异常信息交由异常处理器进行处理,自定义异常处理器可以实现一个系统的异常处理逻辑。
自定义异常
全局异常解析接口 HandlerExceptionResolver
/**
* 自定义异常类
*/
public class CustomException extends Exception {
//定义一个异常消息
private String message;
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
//异常消息封装构造
public CustomException(String message) {
super(message);
this.message = message;
}
}
自定义异常处理器
/**
* 自定义全局异常处理器
*/
public class ExceptionResolver implements HandlerExceptionResolver {
@Override
public ModelAndView resolveException(HttpServletRequest req, HttpServletResponse resp, Object obj,
Exception ex) {
CustomException ce = null;
//判断此异常是否是自定义异常
if (ex instanceof CustomException) {
//自定义异常
ce = (CustomException) ex;
} else {
//如果抛出的不是系统自定义异常则重新构造一个系统错误异常
ce = new CustomException("网络异常!");
}
//创建modelAndView对象,封装数据,视图页面
ModelAndView modelAndView = new ModelAndView();
//设置数据
modelAndView.addObject("error", ce.getMessage());
//设置返回页面
modelAndView.setViewName("error/error");
return modelAndView;
}
}
新建错误提示页面
略
异常处理器配置
在springmvc.xml中配置:
<!-- 配置全局异常处理器 -->
<bean class="com.aric.exception.ExceptionResolver"></bean>
上传文件
采用跨服务器异步上传方式.
jar包
依赖:commons-io,commons-fileupload,jersey框架下的jar包
配置解析器
配置springmvc.xml
<!-- 配置springmvc文件上传解析器 -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!--设置文件上传最大尺寸-->
<property name="maxUploadSize" value="10240000"></property>
</bean>
配置图片服务器权限
<init-param>
<param-name>readonly</param-name>
<param-value>false</param-value>
</init-param>
Controller编写
/**
* 文件上传
*/
@Controller
public class UploadController {
/**
* 上传文件,页面不刷新,图片里面回显
* 技术:ajax,跨服务器上传
* 请求:uploadPic.do
* 参数:String imgSize1File
* 返回值:图片地址,json格式
*/
@RequestMapping("uploadPic")
public void uploadPic(HttpServletRequest request ,String fileName,PrintWriter pw){
//把request转成多部件请求对象
MultipartHttpServletRequest mhsr = (MultipartHttpServletRequest) request;
//根据文件名称name属性名称获取文件对象
CommonsMultipartFile cmf = (CommonsMultipartFile) mhsr.getFile(fileName);
//获取文件名称
String originalFilename = cmf.getOriginalFilename();
//获取文件扩展名
String extName = originalFilename.substring(originalFilename.lastIndexOf("."));
//使用毫秒加随机数定义文件名
long currentTimeMillis = System.currentTimeMillis();
//文件名
String fn = currentTimeMillis+"" ;
//随机数
Random random = new Random();
for(int i = 0; i<4;i++){
fn = fn+random.nextInt(10);
}
//文件名
fn = fn+extName;
//上传文件,跨服务器上传文件,使用jersey客户端
Client client = Client.create();
//指定远程服务器绝对路径
WebResource resource = client.resource(Constants.IMAGE_HOST+ "upload/"+fn);
//上传文件
resource.put(String.class,cmf.getBytes());
//图片回显
//把远程图片服务图片地址返回给页面ajax解析
String fullPath = Constants.IMAGE_HOST+"upload/"+fn;
//打印路径,路径json格式
String jsonResult = "{\"fullPath\":\""+fullPath+"\"}";
//打印出去
pw.print(jsonResult);
}
}
页面编写
<form id="itemForm" action="${pageContext.request.contextPath}/item/updateItems" method="post" >
<table width="100%" border=1>
<tr>
<td>商品图片</td>
<td>
<p><label></label>
<!-- img回显图片 -->
<img id='imgSize1ImgSrc' src='${picPath }${item.pic }' height="100" width="100" />
<!-- 上传图片 -->
<input type='file' id='imgSize1File' name='imgSize1File' class="file" onchange='submitImgSize1Upload()' /><span class="pos" id="imgSize1FileSpan">请上传图片的大小不超过3MB</span>
<!-- 保存图片上传远程服务器地址 -->
<input type='hidden' id='imgSize1' name='pic' value='' reg="^.+$" tip="亲!您忘记上传图片了。" />
</p>
</td>
</tr>
</table>
</form>
js代码:
<script type="text/javascript">
function submitImgSize1Upload() {
//上传图片流程,把图片流对象,放入request,现在图片对象在表单中,要提交表单
//ajax提交表单
var option = {
type:'post',
url:'${pageContext.request.contextPath}/uploadPic',
dataType:'text',
data:{
fileName:'imgSize1File'
},
success:function(data){
//把json字符串转换为对象
var obj = $.parseJSON(data);
//图片回显,把图片地址设置为img标签即可,图片回显
$("#imgSize1ImgSrc").attr("src",obj.fullPath);
//回显路径
$("#imgSize1").val(obj.fullPath);
}
};
//提交表单
$("#itemForm").ajaxSubmit(option);
}
</script>
RESTful支持
Restful就是一个资源定位及资源操作的风格。不是标准也不是协议,只是一种风格,是对http协议的诠释。
资源定位:互联网所有的事物都是资源,要求url中没有动词,只有名词。没有参数
Url格式:http://blog.dn.net/beat_the_world/article/details/45621673
资源操作:使用put、delete、post、get,使用不同方法对资源进行操作。分别对应添加、删除、修改、查询。
前端控制器设置
<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:springmvc.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
静态资源访问
<!-- 放行静态资源 -->
<!-- <mvc:resources location="/js/" mapping="/js/**"/>
<mvc:resources location="/css/" mapping="/css/**"/> -->
<!-- 默认放行所有静态资源 -->
<mvc:default-servlet-handler/>
springmvc支持restFull风格软件架构模式:
1. 没有扩展名
2. 没有?方式传递参数,参数都在url链接中
3. springmvc提供url默认映射,映射:@RequestMapping(“/item/deitItem/{id}”)
4. 通过@Pathvariable 映射参数传递
拦截器
Spring Web MVC 的处理器拦截器类似于Servlet 开发中的过滤器Filter,用于对处理器进行预处理和后处理。
自定义拦截器
/**
* 登陆拦截器
*/
public class LoginInterceptor implements HandlerInterceptor{
/**
* controller执行后且视图返回后调用此方法
* 这里可得到执行controller时的异常信息
* 这里可记录操作日志,资源清理等
*/
@Override
public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
throws Exception {
}
/**
* controller执行后但未返回视图前调用此方法
* 这里可在返回用户前对模型数据进行加工处理,比如这里加入公用信息以便页面显示
*/
@Override
public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
throws Exception {
}
/**
* controller执行前调用此方法
* 返回true表示继续放行,返回false拦截
* 这里可以加入登录校验、权限拦截等
*/
@Override
public boolean preHandle(HttpServletRequest req, HttpServletResponse resp, Object obj) throws Exception {
//1.登陆请求,放行
if (req.getRequestURI().contains("login")) {
return true;
}
//2.如果用户登陆,放行
if (req.getSession().getAttribute("user") != null) {
return true;
}
//3.否则,拦截
//跳转登陆页面登陆
req.getRequestDispatcher("/WEB-INF/jsps/login.jsp").forward(req, resp);
return false;
}
}
拦截器配置
在springmvc中配置
<!--配置局部拦截器-->
<bean
class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping">
<property name="interceptors">
<list>
<ref bean="handlerInterceptor1"/>
<ref bean="handlerInterceptor2"/>
</list>
</property>
</bean>
<bean id="handlerInterceptor1" class="springmvc.intercapter.HandlerInterceptor1"/>
<bean id="handlerInterceptor2" class="springmvc.intercapter.HandlerInterceptor2"/>
<!-- 配置全局拦截器 -->
<mvc:interceptors>
<!-- 登陆拦截器 -->
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="com.aric.interceptor.LoginInterceptor"></bean>
</mvc:interceptor>
</mvc:interceptors>
拦截器执行顺序
preHandle按拦截器定义顺序调用
postHandler按拦截器定义逆序调用
afterCompletion按拦截器定义逆序调用
postHandler在拦截器链内所有拦截器返成功调用
afterCompletion只有preHandle返回true才调用
拦截器与过滤器的区别
- 过滤器Filter依赖于Servlet容器,基于回调函数,过滤范围大
- 拦截器Inerceptor依赖于框架容器,基于反射机制,只过滤请求
ssm整合
控制层采用springmvc、持久层使用mybatis实现.
需求
实现商品查询列表,从mysql数据库查询商品信息。
导jar包
包括:spring(包括springmvc)、mybatis、mybatis-spring整合包、数据库驱动、第三方连接池、日志等。
spring与mybatis整合
db.properties
jdbc.driver=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8 jdbc.username=root jdbc.password=123
log4j.properties
# Global logging configuration,建议开发环境中要用debug log4j.rootLogger=DEBUG, stdout # Console output... log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
配置sqlMapConfig.xml
在classpath下创建mybatis/sqlMapConfig.xml<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <!—使用自动扫描器时,mapper.xml文件如果和mapper.java接口在一个目录则此处不用定义mappers --> <mappers> <package name="cn.aric.ssm.mapper" /> </mappers> </configuration>
配置applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd"> <!-- 配置db.properties --> <context:property-placeholder location="classpath:db.properties" /> <!-- 配置数据库连接池 --> <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"> <property name="url" value="${jdbc.url}" /> <property name="driverClassName" value="${jdbc.driver}" /> <property name="username" value="${jdbc.username}" /> <property name="password" value="${jdbc.password}" /> </bean> <!-- spring管理selSessionfactory,使用mybatis与spring整合包中的SqlSessionFactoryBean --> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <!-- 数据库连接池--> <property name="dataSource" ref="dataSource" /> <!-- 配置mybatis中别名 --> <property name="typeAliasesPackage" value="com.aric.domain" /> <!-- 加载mybatis全局配置文件 --> <property name="configLocation" value="classpath:mybatis/SqlMapConfig.xml" /> </bean> <!-- mapper扫描器 --> <!-- 接口代理开发满足规范 --> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com.aric.mapper" /> </bean> </beans>
配置ItemsMapper.xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="cn.itcast.ssm.mapper.ItemsMapper"> <!-- sql片段 --> <!-- 商品查询条件 --> <sql id="query_items_where"> <if test="items!=null"> <if test="items.name!=null and items.name!=''"> and items.name like '%${items.name}%' </if> </if> </sql> <!-- 查询商品信息 --> <select id="findItemsList" parameterType="queryVo" resultType="items"> select * from items <where> <include refid="query_items_where"/> </where> </select> </mapper>
- ItemsMapper.java
public interface ItemsMapper {
//商品列表
public List<Items> findItemsList(QueryVo queryVo) throws Exception;
}
spring管理service
1、Service由spring管理。
2、spring对Service进行事务控制。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-4.0.xsd">
<!-- spring管理service -->
<context:component-scan base-package="com.aric.service" />
<!-- 指定事务管理平台 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!-- 数据源 -->
<property name="dataSource" ref="dataSource" />
</bean>
<!-- 管理事务策略 -->
<!-- 通知 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="save*" propagation="REQUIRED"/>
<tx:method name="delete*" propagation="REQUIRED"/>
<tx:method name="update*" propagation="REQUIRED"/>
<tx:method name="select*" propagation="REQUIRED"/>
<tx:method name="*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<!-- 切面 -->
<aop:config>
<aop:advisor advice-ref="txAdvice" pointcut="execution(* com.aric.service.*.*(..))" />
</aop:config>
</beans>
service层代码:
public interface OrderService {
//商品查询列表
public List<Items> findItemsList(QueryVo queryVo)throws Exception;
}
@Autowired
private ItemsMapper itemsMapper;
@Override
public List<Items> findItemsList(QueryVo queryVo) throws Exception {
//查询商品信息
return itemsMapper.findItemsList(queryVo);
}
spring与springmvc整合
配置springmvc.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xmlns:dubbo="http://code.alibabatech.com/schema/dubbo" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd"> <!-- 包扫描:指定将Controller交给spring管理 --> <context:component-scan base-package="com.aric.controller" /> <!-- 开启注解 --> <mvc:annotation-driven /> <!-- 放行静态资源 --> <!-- <mvc:resources location="/js/" mapping="/js/**"/> <mvc:resources location="/css/" mapping="/css/**"/> --> <!-- 默认放行所有静态资源 --> <mvc:default-servlet-handler/> <!-- 配置拦截器 --> <mvc:interceptors> <!-- 登陆拦截器 --> <mvc:interceptor> <mvc:mapping path="/**"/> <bean class="com.aric.interceptor.LoginInterceptor"></bean> </mvc:interceptor> </mvc:interceptors> <!-- 配置全局异常处理器 --> <bean class="com.aric.exception.ExceptionResolver"></bean> <!-- 配置springmvc文件上传解析器 --> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <property name="maxUploadSize" value="10240000"></property> </bean> <!-- 配置视图解析器 --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <!-- 配置前缀 --> <property name="prefix" value="/WEB-INF/jsps/" /> <!-- 配置后缀 --> <property name="suffix" value=".jsp" /> </bean> </beans>
web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5"> <display-name>ssm01</display-name> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> <!-- 加载spring配置文件applicaitonContext --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!-- 配置spring文件位置 --> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext-*.xml</param-value> </context-param> <!-- 配置编码过滤器 ,解决post乱码--> <filter> <filter-name>encoding</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>encoding</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!-- 前端控制器 --> <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:springmvc.xml</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>springmvc</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> </web-app>
Controller编写
@Controller
public class OrderController {
@Autowired
private OrderService orderService;
@RequestMapping("/queryItem")
public String queryItem() throws Exception {
// 商品列表
List<Items> itemsList = orderService.findItemsList();
// 填充数据
model.addAttribute("itemsList", itemsList);
return "order/itemsList";
}
}