1.springmvc是什么:springmvc是spring的一个模块,提供web层解决方案(基于mvc架构)
Spring Web MVC是一种基于Java的实现了Web MVC设计模式的请求驱动类型的轻量级Web框架,
即使用了MVC架构模式的思想,将web层进行职责解耦,基于请求驱动指的就是使用请求-响应模型,
框架的目的就是帮助我们简化开发,Spring Web MVC也是要简化我们日常Web开发的。
2.Spring Web MVC前端控制器是DispatcherServlet,应用控制器其实拆为处理器映射器(Handler Mapping)
进行处理器管理和视图解析器(View Resolver)进行视图管理,页面控制器/动作/处理器为Controller接口
(仅包含ModelAndView handleRequest(request, response) 方法)的实现(也可以是任何的POJO类)
适配器(Adapter)
3.Spring Web MVC处理请求的流程(百度):
①首先用户发送请求到前端控制器(DispatcherServlet),DispatcherServlet根据请求信息(URL)来确定
哪一个页面控制器(Controller)进行处理并把请求委托给它,即以前控制器控制的逻辑部分。
②页面控制器(Controller)接收到请求后,进行功能处理。首先需要收集和绑定请求参数到一个对象,
这个对象在Spring Web MVC中叫命令对象,并进行验证。然后将命令对象委托给业务对象进行处理;
处理完毕后返回一个ModelAndView(模型数据和逻辑视图名)
③ 前端控制器收回控制权,然后根据返回的逻辑视图名,选择相应的视图进行渲染,并把模型数据传入以便视图渲染
④前端控制器再次收回控制权,将响应返回给用户,至此过程结束。
4.Spring Web MVC处理请求的流程(视频):
①用户发起请求到DispatcherServlet前端控制器
②DispatcherServlet前端控制器请求HandlerMapping处理器映射器查找Handler。
DispatcherServlet前端控制器其实是中央处理器,目的是降低各组件之间的耦合度
③HandlerMapping处理器映射器,根据url以及一些配置规则(xml,注解)查找Handler,将Handler返回给
DispatcherServlet前端控制器
④DispatcherServlet前端控制器调用适配器(Adapter)执行Handler,有了适配器在适配器去扩展对不同Handler执行方式
(原始Servlet开发,注解开发)
⑤适配器执行Handler
⑥Handler执行完后返回ModelAndView,它是springMVC的一个对象,对Model和View进行封装
⑦适配器将ModelAndView返回给DispatcherServlet
⑧DispatcherServlet调用视图解析器进行试图解析,解析后生成view。视图解析器解析出真正的视图
View:springMVC视图封装对象,提供了很多view,jsp,pdf,excel。。。
⑨ViewSolver试图解析器给前段端控制器返回view
⑩DisPatcherServlet调用view的渲染视图的方法,将模型数据填充到request域
十一:DisPatcherServlet向用户响应结果
5.springmvc的配置:
在web.xml里配置前端配置器:
<servlet>
<servlet-name>MyFirstSpringMVC</servlet-name><!--在web.xml里配置前端控制器(DispatcherServlet)-->
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>加载springmvc.xml文件
<param-name>contextConfigLocation</param-name>
<param-value>classpath:config/springmvc.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>MyFirstSpringMVC</servlet-name>
<!--url可以配置为.do,.action.然后所有请求的url扩展名为.do,.action由springmvc解析,此方法常用-->
<url-pattern>*.action</url-pattern>
</servlet-mapping>
在springmvc.xml配置三大器(处理器映射器,处理器适配器,视图解析器),还有自己编写的handler
<!--配置Handler-->
<bean name="/ItemsList.action" class="com.fusong.Handler.MyHandler"/>
<!--处理器映射器-->
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
<!--处理器适配器-->
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>
<!--配置视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"/>
分析:
①BeanNameUrlHandlerMapping:根据请求的URL(xxx.action)匹配spring容器Bean的name,找到
对应的Bean,即程序员编写的handler.其实就是根据URL找Handler
所有的处理器映射器都实现了HandlerMapping方法
②SimpleControllerHandlerAdapter:
它要求自己编写的Handler实现Controller接口。
所有处理器适配器都实现了HandlerAdapter方法。
自己编写Handler:
public class MyHandler implements Controller {
@Override
public ModelAndView handleRequest(javax.servlet.http.HttpServletRequest httpServletRequest, javax.servlet.http.HttpServletResponse httpServletResponse) throws Exception {
Items items1 = new Items();
Items items2 = new Items();
Items items3 = new Items();
items1.setUserName("Little cookie");
items1.setUserid(0012);
items1.setMydetail("taste good");
items1.setNewdate(new Date());
items1.setMyprice(563.2);
items2.setUserName("Hello Ketty");
items2.setUserid(0011);
items2.setMydetail("look nice");
items2.setNewdate(new Date());
items2.setMyprice(556.2);
items3.setUserName("Bear");
items3.setUserid(1001);
items3.setMydetail("卡哇伊");
items3.setNewdate(new Date());
items3.setMyprice(1562.3);
List<Items> itemsList = new ArrayList<Items>();
itemsList.add(items1);
itemsList.add(items2);
itemsList.add(items3);
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("itemsList", itemsList);
modelAndView.setViewName("ItemsList.jsp");
return modelAndView;
}
}
6.其他的非注解处理器映射器和处理器适配器的学习:(次重点)
7.注解的处理器映射器和处理器适配器的学习:(重点)
①注解映射器
spring3.1之前默认加载的映射器是:org.springframewok.DefaultAnnotationHandlerMapping.
spring3.1之后要使用org.springframewok.RequestMappingHandlerMapping.
②注解适配器
spring3.1之前默认加载的映射器是:org.springframewok.AnntationMethodHandlerAdapter
spring3.1之后要使用org.springframewok.RequestMappingHandlerAdapter
RequestMappingHandlerAdapter不要求Handler实现任何接口,
注解配置springmvc.xml:
<!--注解配置三大器,以及Handler-->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/>
<!--配置视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"/>
<bean class="com.fusong.Handler.MyHandlerAnnotation"/>
MyHandlerAnnotation类代码如下:
@org.springframework.stereotype.Controller
public class MyHandlerAnnotation {
@RequestMapping("MyHandlerAnnotation")
public ModelAndView handleRequest() throws Exception {
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("itemsList", itemsList);
modelAndView.setViewName("ItemsList.jsp");
return modelAndView;
}
}
<bean class="com.fusong.Handler.MyHandlerAnnotation"/>
批量配置类:
<context:component-scan base-package="com.fusong.Handler"/>
8.几个注解的作用:
①Controller 用于标记在一个类上,使用它标记的类就是一个SpringMVC Controller 对象
这个时候有两种方式可以把MyController 交给Spring 管理,好让它能够识别我们标记的@Controller 。
第一种方式是在SpringMVC 的配置文件中定义MyController 的bean 对象。
<bean class="com.host.app.web.controller.MyController"/>
②RequestMapping是一个用来处理请求地址映射的注解,可用于类或方法上。用于类上,表示类中的所有响应请求
的方法都是以该地址作为父路径。
9.建议使用组件扫描<context:component-scan>,可以扫描@Contorller,@componnet,@Repository.
10.①DispatcherServlet通过HandlerMapping得到Handler
②DispatcherServlet通过选择合适的适配器去执行Handler。得到ModelAndView。
③视图解析器解析后得到一个view
④进行视图渲染。将Model中的数据填充到Request域。
11.SpringMVC与Mybatis整合:
在spring与mybatis的基础上加springmvc的包。
spring管理springmvc的Handler(Controller),mybatis的SqlSessionFactory,mapper。
12.applicationContetx_dao.xml里配置mybatis数据源,sqlSessionFactory和mapper扫描器
applicationContetx_transcation.xml,在此配置声明式事物
<!--在applicationContetx_transcation.xml里建议使用声明式事务,可以有效管理代码-->
13.在springmvc.xml所管理的Handler类里,想要加载service属性所用的方法:
ApplicationContext context = new ClassPathXmlApplicationContext("config/applicationContext_dao.xml");
MyService myService= (MyService) context.getBean("service");
这是原始的spring注入属性的方法。
14.适配器执行Handler。http前端发送Key,Value数据到HandlerAdapter(适配器),适配器早期用
PropertyEditor,目前用converter进行参数绑定。converter支持任意类型转换。将数据绑定到自己编写的Handler方法形参上。 15.参数绑定:
ItemsList.jsp页面:
<td><a href="editItemsList.action?goodId=${item.userid}">编辑</a></td>
Handler方法:
@RequestMapping(value = "/editItemsList",method = {RequestMethod.POST,RequestMethod.GET})
public ModelAndView editItemsList(@RequestParam(value = "goodId",required = false) int id) throws Exception {
ApplicationContext context = new ClassPathXmlApplicationContext("config/applicationContext_dao.xml");
MyService myService= (MyService) context.getBean("service");
ModelAndView modelAndView = new ModelAndView();
Items itemsList=myService.editItems(id);
modelAndView.addObject("itemsList", itemsList);
modelAndView.setViewName("editItems.jsp");
return modelAndView;
}
我们在请求页面里加上要传递的参数以及参数值,传给Handler。需要适配器找到Handler路径。然后在Handler方法里加形参,那个形参即我们要传递的参数。
使用@RequestParam的好处:①可以设置默认值。②可以设置是否必须请求③可以设置的参数名和前端传递的参数名一致。
@RequestParam一般不用,如果request请求的参数名和Handler方法的形参名一致,适配器自动进行参数绑定,如果不一致可以通过
@RequestParam指定的Request请求的参数名绑定到对应的方法形参上。
16.解决post方式提交时中文乱码问题:
在web.xml里配置如下:
<filter>
<filter-name>CharacterEncodingFilter</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>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
17.当ssm整合时,遇到sqlSessionFactory无法加载的问题,原因是没有读取到SqlConfigMap.xml,更改之后的
applicationContetx.xml文件,加载SqlConfigMap.xml文件如下:
<!--定义sqlSessionFactory属性-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!--配置数据源-->
<property name="dataSource" ref="dataSource"/>
<!--mybatis配置文件-->
<property name="configLocation" value="classpath:config/SqlConfigMap.xml"/>
</bean>
只是指定了SqlConfigMap.xml的位置,多了classpath。
18.简单POJO类型的绑定:
request请求的参数名和pojo的属性名一致,就可以绑定成功。代码如下:
<form id="Myform" action="updateItems.action" method="post">
<table width="100%" border="1">
<tr>
<td>商品id</td>
<td><input type="hidden" name="Userid" value="${itemsList.userid}"></td>
</tr>
<tr>
<td>商品名称</td>
<td><input type="text" name="UserName" value="${itemsList.userName}"></td>
</tr>
<tr>
<td rowspan="3">商品介绍</td>
<td rowspan="3"><input type="text" name="Mydetail" value="${itemsList.mydetail}"></td>
</tr>
<br>
<tr>
<td>商品价格</td>
<td><input type="text" name="Myprice" value="${itemsList.myprice}">}</td>
</tr>
<tr>
<td>生产日期</td>
<td><input type="text" value="${itemsList.newdate}"></td>
</tr>
<tr>
<td align="center"><input type="button" value="submit" οnclick="submit()"></td>
</tr>
</table>
</form>
注意属性名name,在通过适配器传给Handler后,会有Request自动解析name,request.getParameter("name");
此时我们需要在Handler方法里传pojo类型的值即可。
@RequestMapping(value = "/updateItems", method = {RequestMethod.POST, RequestMethod.GET})
public ModelAndView updateItems(Items items) throws Exception {
ApplicationContext context = new ClassPathXmlApplicationContext("config/applicationContext.xml");
MyService myService = (MyService) context.getBean("service");
ModelAndView modelAndView = new ModelAndView();
myService.updateItems(items);
List<Items> itemsList = myService.selectItemsMap("Little cookis");
modelAndView.addObject("itemsList", itemsList);
modelAndView.setViewName("ItemsList");
return modelAndView;
}
19.日期类型的绑定:springmvc没有提供默认的对日期类型的绑定,需要自定义日期类型的绑定。
20.springmvc注解开发的高级知识:
使用<mvc:annotation-driven></mvc:annotation-driven>可以替换映射器和适配器。
<!--<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>-->
<!--<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/>-->
②数据回显:表单提交出现错误,重新回到表单,用户重新填写数据。之前提交的参数在页面上回显。
③参数绑定集合类型:
*绑定数组:
jstl和EL取数组,然后遍历得到数组值的方法(对于普通属性的方法):
<c:forEach items="${ids}" var="id">
得到的值为:${id}
</c:forEach>
我们在进行批量操作时,将该类的id的value作为属性值传入请求路径。请求路径通过request.getParameterValues得到一个数组
然后将该数组注入到方法里。代码如下:
<td>选择</td>
<td><input type="checkbox" name="ids" value="${item.userid}"></td>
Handler方法如下:
@RequestMapping(value = "deleteItems", method = {RequestMethod.POST, RequestMethod.GET})
public ModelAndView deleteItems(Integer []ids){
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("ids", ids);
modelAndView.setViewName("ids");
return modelAndView;
}
④图片上传:切记不要把图片放在工程目录,不方便进行维护。
在实际中,使用图片服务器,如(Apache,tomcat)。接下来将使用虚拟目录,和前两者相似的原理。通过虚拟目录
访问硬盘上存储的图片的目录。
springmvc使用commons-fileupload,commons-io进行图片上传。commons-fileupload,commons-io对应的图片上传解析器为:
关于图片上传注意事项:
*from中涉及到图片上传的就要用post提交方式,<form id="Myform" action="updateItems.action" method="post" enctype="multipart/form-data">
<tr>
<td>商品图片</td>
<td><c:if test="${itemsList.mypic!=null}">注意这里,判断是否为空,!=null,一定不能写在${}外面。
<img src="/pic/${itemsList.mypic}" width="80%" height="80%"/>
</c:if>
<input type="file" name="multipartFile" value="${itemsList.mypic}">
</td>
</tr>
*在sprimvc.xml里配置文件上传解析器:
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="200000"/>
<property name="maxInMemorySize" value="10240" />
</bean>
*Handler方法里上传图片,并把图片路径保存到数据库。代码:
if (multipartFile != null) {
String picPath = "D:\\MyPhoto\\temp\\";//一定要在temp之后加\\,不然将不能放到temp目录下。
String originalFilename = multipartFile.getOriginalFilename();
String newpath = UUID.randomUUID() + originalFilename.substring(originalFilename.lastIndexOf("."));
File file=new File(picPath+newpath);
System.out.println(picPath+newpath);
multipartFile.transferTo(file);
items.setMypic(newpath);
}
在jsp页面如果能加载到图片,将会直接下载图片展示给我们。
⑤jSON数据的交互
JSON数据常用于远程接口传输,http传输JSON数据。方便页面进行请求响应,对JSON的解析:
@RequestBody,将Json转成Java对象
@ResponseBody,将Java对象转成Json数据输出。
ajax向Handler请求JSON数据(Key,Value)的方法:
<script src="http://code.jquery.com/jquery-1.4.1.min.js"></script>
<script>
function recallJson() {
$.ajax({
url: "requireJSON.action",
type: "post",
data: {"Userid": "110023", "Myprice": "123.6"},
success:function (data) {
alert(data.Userid)
}
});
}
</script>
Handler方法如下:
@Controller
public class MyJsonHandler {
@RequestMapping(value = "requireJSON", method = {RequestMethod.POST, RequestMethod.GET})
@ResponseBody
public Items rebackData(Items items) {
System.out.println("shoudaoqingqiu");
return items;
}
}
springmvc.xml里的配置:
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<property name="messageConverters">
<list>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"/>
</list>
</property>
</bean>
⑥springmvc之校验器Validator的配置:
在springmvc.xml文件里添加如下配置:
在适配器里添加: <property name="webBindingInitializer" ref="customBinder"></property>
另外配置校验器:
<bean id="validator"
class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean" >
<!--<--校验器–>-->
<property name="providerClass" value="org.hibernate.validator.HibernateValidator"/>
<!--<--指定校验使用的资源文件,如果不指定则默认使用classpath下的ValidationMessages.properties –>-->
<property name="validationMessageSource" ref="customValidationMessages" />
</bean>
配置校验信息错误信息:
<bean id="customValidationMessages"
class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<!--<--资源文件名–>-->
<property name="commonMessages" ref="prop">
</property>
<!--<--资源文件编码格式 –>-->
<property name="fileEncodings" value="utf-8" />
<!-- 对资源文件内容缓存时间,单位秒 -->
<property name="cacheSeconds" value="120" />
</bean>
<bean id="prop" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="locations">
<array>
<value>classpath:config/customValidationMessages.properties</value>
</array>
</property>
</bean>
配置自定义webBindingInitializer:
<!-- 自定义webBinder -->
<bean id="customBinder"
class="org.springframework.web.bind.support.ConfigurableWebBindingInitializer">
<property name="validator" ref="validator" />
</bean>
我在springmvc里配置加载properties文件时,无法写classpath:,于是我定义了一个文件加载类:
org.springframework.beans.factory.config.PropertiesFactoryBean。然后把prop属性传给
<bean id="customValidationMessages"
class="org.springframework.context.support.ReloadableResourceBundleMessageSource">下的
<property name="commonMessages" ref="prop">
⑦统一异常处理
系统中的异常包括预期异常和运行时异常,*①对于预期异常我们只需try,catch
*②对于运行时异常,我们可以自定义异常类型,这些类型通常继承于Exception。
前端控制器DispatchServlet在进行HandingMapper,调用HandlerAdapter执行Handler的过程中,如果遇到
异常,将进行异常处理。在DispatchServlet源码里得到的。
做法:我们需要自定义一个类MyDefinedExcption,让他继承Excption。我们要自定义一个Resolver方法,让他实现
HandlerExceptionResolver,因为适配器在执行Handler时遇到异常会向上抛出。在我们的controller方法里做判断。如果
有异常,则throw new MyDefinedExcption(“message”)。代码如下:
①MyDefinedException:
public class MyDefinedException extends Exception {
String message;
public MyDefinedException(String message) {
super(message);
this.message = message;
}
}
②MyExceptionResolver:
@Controller
public class MyExceptionResolver implements HandlerExceptionResolver {
@Override
public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
String message = null;
ModelAndView modelAndView = new ModelAndView();
MyDefinedException definedException;
if (e instanceof MyDefinedException) {
definedException = (MyDefinedException) e;
} else {
definedException = new MyDefinedException("unknown errror");
}
message = ((MyDefinedException) e).getMessage();
modelAndView.addObject("message",message);
modelAndView.setViewName("error");
return modelAndView;
}
}
③在springmvc.xml文件里配置MyExceptionResolver :
<context:component-scan base-package="com.fusong.Handler,com.fusong.exception"/>
④controller方法里应用如下:
if (itemsList == null) {
throw new MyDefinedException("找不到该商品");
}
21.springmvc对restful的支持:
RESTful的理解:它是Representational State Transfer的缩写,表现层状态转化。它是一种软件开发理念,对http做了很好的诠释。
RESTful架构:
①每一个URL代表一种资源
②客户端与服务器之间,传递这种资源的某种表现层
③客户端通过四个HTTP动词,get(获取资源),post(新建资源),put(更新资源),delete(删除资源)对服务器端资源进行操作,分别对应。实现表现层状态转化。(真正实现上面这三条不多。)
*传统的url:http://localhost:8080/editItemsList.action?goodId=3&goodId=4
RESTful的url很简洁:http://localhost:8080/editItemsList/3/4
*参数通过url传递,rest接口返回json数据。
*想要以这种方式返回数据http://localhost:8080/editItemsList/3/4,需要更改前端配置。
*更改前端配置在web.xml里:
<!--RESTful的配置-->
<servlet>
<servlet-name>RESTfultest</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:config/springmvc.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>RESTfultest</servlet-name>
<!--注意/后面不能加*号-->
<url-pattern>/</url-pattern>
</servlet-mapping>
*参数通过url传递的解决方式:
//RequestMapping中指定restful方式的url中的参数,参数需要{}包
//@PathVariable将url中的参数和方法的形参进行绑定
@RequestMapping(value = "/editItemsMap/{goodId}", method = {RequestMethod.POST, RequestMethod.GET})
public ModelAndView editItemsMap(@PathVariable(value = "goodId") int id) throws Exception {
ApplicationContext context = new ClassPathXmlApplicationContext("config/applicationContext.xml");
MyService myService = (MyService) context.getBean("service");
ModelAndView modelAndView = new ModelAndView();
Items itemsList = myService.queryItem(id);
if (itemsList == null) {
throw new MyDefinedException("找不到该商品");
}
modelAndView.addObject("itemsList", itemsList);
modelAndView.setViewName("editItems");
return modelAndView;
}
访问方式为:http://localhost:8080/editItemsMap/3
<select id="queryItem" parameterType="int" resultMap="ItemsResultMap">
SELECT * FROM items WHERE id=#{Userid}
</select>
22.Controller用String方法返回:
@RequestMapping(value = "/selectItemsList", method = {RequestMethod.POST, RequestMethod.GET})
public String selectItemsList(Model model) throws Exception {
ApplicationContext context = new ClassPathXmlApplicationContext("config/applicationContext.xml");
MyService myService = (MyService) context.getBean("service");
List<Items> itemsList = myService.selectItemsMap("Little cookis");
model.addAttribute("itemsList", itemsList);
return "ItemsList";
}
23.以后我再用spring创建对象的时候,就这样用:
在applicationContext里面:
<!--<!– 扫描service包下所有使用注解的类型 –>-->
<context:component-scan base-package="com.fusong.service" ></context:component-scan>
在service里:
@Component("service")
public class MyServiceImp implements MyService {
在springmvc.xml所管理的handler里:
@Controller
@RequestMapping("Items")
public class MyHandler extends HttpServlet {
//@Resource
@Autowired
public MyService myService;
注意:写测试类@Test,是检测不到myService的,但是在网页上却能用。
24.springmvc拦截器:
拦截器的异常场合:
用户请求到DispatcherServlet中,DispatcherServlet调用HandlerMapping查找Handler,HandlerMapping返回
一个拦截的链(多个拦截),springmvc中的拦截器是通过HandlerMapping发起的。
在企业开发中,使用拦截器实现用户验证,用户权限拦截。
拦截器的定义方法:在springmvc里配置全局拦截器:
<!--全剧配置拦截器-->
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="com.fusong.intercepter.MyInterpter1"/>
</mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="com.fusong.intercepter.MyInterpter2"/>
</mvc:interceptor>
</mvc:interceptors>
25.对于拦截器的认识:
*SpringMVC 中的Interceptor 拦截请求是通过HandlerInterceptor 来实现的
*在SpringMVC 中定义一个Interceptor 非常简单,主要有两种方式,第一种方
式是要定义的Interceptor类要实现了Spring 的HandlerInterceptor 接口
* HandlerInterceptor 接口中定义了三个方法,我们就是通过这三个方法来对用户的请求进行拦截处理的。
*preHandle (HttpServletRequest request, HttpServletResponse response, Object handle) 方法:
①顾名思义,该方法将在请求处理之前进行调用。SpringMVC 中的Interceptor 是链式的调用的,在一个应用中或者说是在一个请求中可以同时存在多个Interceptor 。每个Interceptor 的调用会依据它的声明顺序依次执行,而且最先执行的都是Interceptor 中的preHandle 方法
②该方法的返回值是布尔值Boolean 类型的,当它返回为false 时,表示请求结束,后续的Interceptor 和Controller 都不会再执行;当返回值为true 时就会继续调用下一个Interceptor 的preHandle 方法,如果已经是最后一个Interceptor 的时候就会是调用当前请求的Controller 方法。
*postHandle (HttpServletRequest request, HttpServletResponse response, Object handle, ModelAndView modelAndView) 方法
①由preHandle 方法的解释我们知道这个方法包括后面要说到的afterCompletion 方法都只能是在当前所属的Interceptor 的preHandle 方法的返回值为true 时才能被调用。
②postHandle 方法,顾名思义就是在当前请求进行处理之后,也就是Controller 方法调用之后执行,但是它会在DispatcherServlet 进行视图返回渲染之前被调用,所以我们可以在这个方法中对Controller 处理之后的ModelAndView 对象进行操作
*afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handle, Exception ex) 方法
顾名思义,该方法将在整个请求结束之后,也就是在DispatcherServlet 渲染了对应的视图之后执行。这个方法的主要作用是用于进行资源清理工作的。
26.拦截器,对于每个要访问的URL都会进行一次拦截。
Spring Web MVC是一种基于Java的实现了Web MVC设计模式的请求驱动类型的轻量级Web框架,
即使用了MVC架构模式的思想,将web层进行职责解耦,基于请求驱动指的就是使用请求-响应模型,
框架的目的就是帮助我们简化开发,Spring Web MVC也是要简化我们日常Web开发的。
2.Spring Web MVC前端控制器是DispatcherServlet,应用控制器其实拆为处理器映射器(Handler Mapping)
进行处理器管理和视图解析器(View Resolver)进行视图管理,页面控制器/动作/处理器为Controller接口
(仅包含ModelAndView handleRequest(request, response) 方法)的实现(也可以是任何的POJO类)
适配器(Adapter)
3.Spring Web MVC处理请求的流程(百度):
①首先用户发送请求到前端控制器(DispatcherServlet),DispatcherServlet根据请求信息(URL)来确定
哪一个页面控制器(Controller)进行处理并把请求委托给它,即以前控制器控制的逻辑部分。
②页面控制器(Controller)接收到请求后,进行功能处理。首先需要收集和绑定请求参数到一个对象,
这个对象在Spring Web MVC中叫命令对象,并进行验证。然后将命令对象委托给业务对象进行处理;
处理完毕后返回一个ModelAndView(模型数据和逻辑视图名)
③ 前端控制器收回控制权,然后根据返回的逻辑视图名,选择相应的视图进行渲染,并把模型数据传入以便视图渲染
④前端控制器再次收回控制权,将响应返回给用户,至此过程结束。
4.Spring Web MVC处理请求的流程(视频):
①用户发起请求到DispatcherServlet前端控制器
②DispatcherServlet前端控制器请求HandlerMapping处理器映射器查找Handler。
DispatcherServlet前端控制器其实是中央处理器,目的是降低各组件之间的耦合度
③HandlerMapping处理器映射器,根据url以及一些配置规则(xml,注解)查找Handler,将Handler返回给
DispatcherServlet前端控制器
④DispatcherServlet前端控制器调用适配器(Adapter)执行Handler,有了适配器在适配器去扩展对不同Handler执行方式
(原始Servlet开发,注解开发)
⑤适配器执行Handler
⑥Handler执行完后返回ModelAndView,它是springMVC的一个对象,对Model和View进行封装
⑦适配器将ModelAndView返回给DispatcherServlet
⑧DispatcherServlet调用视图解析器进行试图解析,解析后生成view。视图解析器解析出真正的视图
View:springMVC视图封装对象,提供了很多view,jsp,pdf,excel。。。
⑨ViewSolver试图解析器给前段端控制器返回view
⑩DisPatcherServlet调用view的渲染视图的方法,将模型数据填充到request域
十一:DisPatcherServlet向用户响应结果
5.springmvc的配置:
在web.xml里配置前端配置器:
<servlet>
<servlet-name>MyFirstSpringMVC</servlet-name><!--在web.xml里配置前端控制器(DispatcherServlet)-->
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>加载springmvc.xml文件
<param-name>contextConfigLocation</param-name>
<param-value>classpath:config/springmvc.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>MyFirstSpringMVC</servlet-name>
<!--url可以配置为.do,.action.然后所有请求的url扩展名为.do,.action由springmvc解析,此方法常用-->
<url-pattern>*.action</url-pattern>
</servlet-mapping>
在springmvc.xml配置三大器(处理器映射器,处理器适配器,视图解析器),还有自己编写的handler
<!--配置Handler-->
<bean name="/ItemsList.action" class="com.fusong.Handler.MyHandler"/>
<!--处理器映射器-->
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
<!--处理器适配器-->
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>
<!--配置视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"/>
分析:
①BeanNameUrlHandlerMapping:根据请求的URL(xxx.action)匹配spring容器Bean的name,找到
对应的Bean,即程序员编写的handler.其实就是根据URL找Handler
所有的处理器映射器都实现了HandlerMapping方法
②SimpleControllerHandlerAdapter:
它要求自己编写的Handler实现Controller接口。
所有处理器适配器都实现了HandlerAdapter方法。
自己编写Handler:
public class MyHandler implements Controller {
@Override
public ModelAndView handleRequest(javax.servlet.http.HttpServletRequest httpServletRequest, javax.servlet.http.HttpServletResponse httpServletResponse) throws Exception {
Items items1 = new Items();
Items items2 = new Items();
Items items3 = new Items();
items1.setUserName("Little cookie");
items1.setUserid(0012);
items1.setMydetail("taste good");
items1.setNewdate(new Date());
items1.setMyprice(563.2);
items2.setUserName("Hello Ketty");
items2.setUserid(0011);
items2.setMydetail("look nice");
items2.setNewdate(new Date());
items2.setMyprice(556.2);
items3.setUserName("Bear");
items3.setUserid(1001);
items3.setMydetail("卡哇伊");
items3.setNewdate(new Date());
items3.setMyprice(1562.3);
List<Items> itemsList = new ArrayList<Items>();
itemsList.add(items1);
itemsList.add(items2);
itemsList.add(items3);
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("itemsList", itemsList);
modelAndView.setViewName("ItemsList.jsp");
return modelAndView;
}
}
6.其他的非注解处理器映射器和处理器适配器的学习:(次重点)
7.注解的处理器映射器和处理器适配器的学习:(重点)
①注解映射器
spring3.1之前默认加载的映射器是:org.springframewok.DefaultAnnotationHandlerMapping.
spring3.1之后要使用org.springframewok.RequestMappingHandlerMapping.
②注解适配器
spring3.1之前默认加载的映射器是:org.springframewok.AnntationMethodHandlerAdapter
spring3.1之后要使用org.springframewok.RequestMappingHandlerAdapter
RequestMappingHandlerAdapter不要求Handler实现任何接口,
注解配置springmvc.xml:
<!--注解配置三大器,以及Handler-->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/>
<!--配置视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"/>
<bean class="com.fusong.Handler.MyHandlerAnnotation"/>
MyHandlerAnnotation类代码如下:
@org.springframework.stereotype.Controller
public class MyHandlerAnnotation {
@RequestMapping("MyHandlerAnnotation")
public ModelAndView handleRequest() throws Exception {
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("itemsList", itemsList);
modelAndView.setViewName("ItemsList.jsp");
return modelAndView;
}
}
<bean class="com.fusong.Handler.MyHandlerAnnotation"/>
批量配置类:
<context:component-scan base-package="com.fusong.Handler"/>
8.几个注解的作用:
①Controller 用于标记在一个类上,使用它标记的类就是一个SpringMVC Controller 对象
这个时候有两种方式可以把MyController 交给Spring 管理,好让它能够识别我们标记的@Controller 。
第一种方式是在SpringMVC 的配置文件中定义MyController 的bean 对象。
<bean class="com.host.app.web.controller.MyController"/>
②RequestMapping是一个用来处理请求地址映射的注解,可用于类或方法上。用于类上,表示类中的所有响应请求
的方法都是以该地址作为父路径。
9.建议使用组件扫描<context:component-scan>,可以扫描@Contorller,@componnet,@Repository.
10.①DispatcherServlet通过HandlerMapping得到Handler
②DispatcherServlet通过选择合适的适配器去执行Handler。得到ModelAndView。
③视图解析器解析后得到一个view
④进行视图渲染。将Model中的数据填充到Request域。
11.SpringMVC与Mybatis整合:
在spring与mybatis的基础上加springmvc的包。
spring管理springmvc的Handler(Controller),mybatis的SqlSessionFactory,mapper。
12.applicationContetx_dao.xml里配置mybatis数据源,sqlSessionFactory和mapper扫描器
applicationContetx_transcation.xml,在此配置声明式事物
<!--在applicationContetx_transcation.xml里建议使用声明式事务,可以有效管理代码-->
13.在springmvc.xml所管理的Handler类里,想要加载service属性所用的方法:
ApplicationContext context = new ClassPathXmlApplicationContext("config/applicationContext_dao.xml");
MyService myService= (MyService) context.getBean("service");
这是原始的spring注入属性的方法。
14.适配器执行Handler。http前端发送Key,Value数据到HandlerAdapter(适配器),适配器早期用
PropertyEditor,目前用converter进行参数绑定。converter支持任意类型转换。将数据绑定到自己编写的Handler方法形参上。 15.参数绑定:
ItemsList.jsp页面:
<td><a href="editItemsList.action?goodId=${item.userid}">编辑</a></td>
Handler方法:
@RequestMapping(value = "/editItemsList",method = {RequestMethod.POST,RequestMethod.GET})
public ModelAndView editItemsList(@RequestParam(value = "goodId",required = false) int id) throws Exception {
ApplicationContext context = new ClassPathXmlApplicationContext("config/applicationContext_dao.xml");
MyService myService= (MyService) context.getBean("service");
ModelAndView modelAndView = new ModelAndView();
Items itemsList=myService.editItems(id);
modelAndView.addObject("itemsList", itemsList);
modelAndView.setViewName("editItems.jsp");
return modelAndView;
}
我们在请求页面里加上要传递的参数以及参数值,传给Handler。需要适配器找到Handler路径。然后在Handler方法里加形参,那个形参即我们要传递的参数。
使用@RequestParam的好处:①可以设置默认值。②可以设置是否必须请求③可以设置的参数名和前端传递的参数名一致。
@RequestParam一般不用,如果request请求的参数名和Handler方法的形参名一致,适配器自动进行参数绑定,如果不一致可以通过
@RequestParam指定的Request请求的参数名绑定到对应的方法形参上。
16.解决post方式提交时中文乱码问题:
在web.xml里配置如下:
<filter>
<filter-name>CharacterEncodingFilter</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>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
17.当ssm整合时,遇到sqlSessionFactory无法加载的问题,原因是没有读取到SqlConfigMap.xml,更改之后的
applicationContetx.xml文件,加载SqlConfigMap.xml文件如下:
<!--定义sqlSessionFactory属性-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!--配置数据源-->
<property name="dataSource" ref="dataSource"/>
<!--mybatis配置文件-->
<property name="configLocation" value="classpath:config/SqlConfigMap.xml"/>
</bean>
只是指定了SqlConfigMap.xml的位置,多了classpath。
18.简单POJO类型的绑定:
request请求的参数名和pojo的属性名一致,就可以绑定成功。代码如下:
<form id="Myform" action="updateItems.action" method="post">
<table width="100%" border="1">
<tr>
<td>商品id</td>
<td><input type="hidden" name="Userid" value="${itemsList.userid}"></td>
</tr>
<tr>
<td>商品名称</td>
<td><input type="text" name="UserName" value="${itemsList.userName}"></td>
</tr>
<tr>
<td rowspan="3">商品介绍</td>
<td rowspan="3"><input type="text" name="Mydetail" value="${itemsList.mydetail}"></td>
</tr>
<br>
<tr>
<td>商品价格</td>
<td><input type="text" name="Myprice" value="${itemsList.myprice}">}</td>
</tr>
<tr>
<td>生产日期</td>
<td><input type="text" value="${itemsList.newdate}"></td>
</tr>
<tr>
<td align="center"><input type="button" value="submit" οnclick="submit()"></td>
</tr>
</table>
</form>
注意属性名name,在通过适配器传给Handler后,会有Request自动解析name,request.getParameter("name");
此时我们需要在Handler方法里传pojo类型的值即可。
@RequestMapping(value = "/updateItems", method = {RequestMethod.POST, RequestMethod.GET})
public ModelAndView updateItems(Items items) throws Exception {
ApplicationContext context = new ClassPathXmlApplicationContext("config/applicationContext.xml");
MyService myService = (MyService) context.getBean("service");
ModelAndView modelAndView = new ModelAndView();
myService.updateItems(items);
List<Items> itemsList = myService.selectItemsMap("Little cookis");
modelAndView.addObject("itemsList", itemsList);
modelAndView.setViewName("ItemsList");
return modelAndView;
}
19.日期类型的绑定:springmvc没有提供默认的对日期类型的绑定,需要自定义日期类型的绑定。
20.springmvc注解开发的高级知识:
使用<mvc:annotation-driven></mvc:annotation-driven>可以替换映射器和适配器。
<!--<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>-->
<!--<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/>-->
②数据回显:表单提交出现错误,重新回到表单,用户重新填写数据。之前提交的参数在页面上回显。
③参数绑定集合类型:
*绑定数组:
jstl和EL取数组,然后遍历得到数组值的方法(对于普通属性的方法):
<c:forEach items="${ids}" var="id">
得到的值为:${id}
</c:forEach>
我们在进行批量操作时,将该类的id的value作为属性值传入请求路径。请求路径通过request.getParameterValues得到一个数组
然后将该数组注入到方法里。代码如下:
<td>选择</td>
<td><input type="checkbox" name="ids" value="${item.userid}"></td>
Handler方法如下:
@RequestMapping(value = "deleteItems", method = {RequestMethod.POST, RequestMethod.GET})
public ModelAndView deleteItems(Integer []ids){
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("ids", ids);
modelAndView.setViewName("ids");
return modelAndView;
}
④图片上传:切记不要把图片放在工程目录,不方便进行维护。
在实际中,使用图片服务器,如(Apache,tomcat)。接下来将使用虚拟目录,和前两者相似的原理。通过虚拟目录
访问硬盘上存储的图片的目录。
springmvc使用commons-fileupload,commons-io进行图片上传。commons-fileupload,commons-io对应的图片上传解析器为:
关于图片上传注意事项:
*from中涉及到图片上传的就要用post提交方式,<form id="Myform" action="updateItems.action" method="post" enctype="multipart/form-data">
<tr>
<td>商品图片</td>
<td><c:if test="${itemsList.mypic!=null}">注意这里,判断是否为空,!=null,一定不能写在${}外面。
<img src="/pic/${itemsList.mypic}" width="80%" height="80%"/>
</c:if>
<input type="file" name="multipartFile" value="${itemsList.mypic}">
</td>
</tr>
*在sprimvc.xml里配置文件上传解析器:
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="200000"/>
<property name="maxInMemorySize" value="10240" />
</bean>
*Handler方法里上传图片,并把图片路径保存到数据库。代码:
if (multipartFile != null) {
String picPath = "D:\\MyPhoto\\temp\\";//一定要在temp之后加\\,不然将不能放到temp目录下。
String originalFilename = multipartFile.getOriginalFilename();
String newpath = UUID.randomUUID() + originalFilename.substring(originalFilename.lastIndexOf("."));
File file=new File(picPath+newpath);
System.out.println(picPath+newpath);
multipartFile.transferTo(file);
items.setMypic(newpath);
}
在jsp页面如果能加载到图片,将会直接下载图片展示给我们。
⑤jSON数据的交互
JSON数据常用于远程接口传输,http传输JSON数据。方便页面进行请求响应,对JSON的解析:
@RequestBody,将Json转成Java对象
@ResponseBody,将Java对象转成Json数据输出。
ajax向Handler请求JSON数据(Key,Value)的方法:
<script src="http://code.jquery.com/jquery-1.4.1.min.js"></script>
<script>
function recallJson() {
$.ajax({
url: "requireJSON.action",
type: "post",
data: {"Userid": "110023", "Myprice": "123.6"},
success:function (data) {
alert(data.Userid)
}
});
}
</script>
Handler方法如下:
@Controller
public class MyJsonHandler {
@RequestMapping(value = "requireJSON", method = {RequestMethod.POST, RequestMethod.GET})
@ResponseBody
public Items rebackData(Items items) {
System.out.println("shoudaoqingqiu");
return items;
}
}
springmvc.xml里的配置:
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<property name="messageConverters">
<list>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"/>
</list>
</property>
</bean>
⑥springmvc之校验器Validator的配置:
在springmvc.xml文件里添加如下配置:
在适配器里添加: <property name="webBindingInitializer" ref="customBinder"></property>
另外配置校验器:
<bean id="validator"
class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean" >
<!--<--校验器–>-->
<property name="providerClass" value="org.hibernate.validator.HibernateValidator"/>
<!--<--指定校验使用的资源文件,如果不指定则默认使用classpath下的ValidationMessages.properties –>-->
<property name="validationMessageSource" ref="customValidationMessages" />
</bean>
配置校验信息错误信息:
<bean id="customValidationMessages"
class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<!--<--资源文件名–>-->
<property name="commonMessages" ref="prop">
</property>
<!--<--资源文件编码格式 –>-->
<property name="fileEncodings" value="utf-8" />
<!-- 对资源文件内容缓存时间,单位秒 -->
<property name="cacheSeconds" value="120" />
</bean>
<bean id="prop" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="locations">
<array>
<value>classpath:config/customValidationMessages.properties</value>
</array>
</property>
</bean>
配置自定义webBindingInitializer:
<!-- 自定义webBinder -->
<bean id="customBinder"
class="org.springframework.web.bind.support.ConfigurableWebBindingInitializer">
<property name="validator" ref="validator" />
</bean>
我在springmvc里配置加载properties文件时,无法写classpath:,于是我定义了一个文件加载类:
org.springframework.beans.factory.config.PropertiesFactoryBean。然后把prop属性传给
<bean id="customValidationMessages"
class="org.springframework.context.support.ReloadableResourceBundleMessageSource">下的
<property name="commonMessages" ref="prop">
⑦统一异常处理
系统中的异常包括预期异常和运行时异常,*①对于预期异常我们只需try,catch
*②对于运行时异常,我们可以自定义异常类型,这些类型通常继承于Exception。
前端控制器DispatchServlet在进行HandingMapper,调用HandlerAdapter执行Handler的过程中,如果遇到
异常,将进行异常处理。在DispatchServlet源码里得到的。
做法:我们需要自定义一个类MyDefinedExcption,让他继承Excption。我们要自定义一个Resolver方法,让他实现
HandlerExceptionResolver,因为适配器在执行Handler时遇到异常会向上抛出。在我们的controller方法里做判断。如果
有异常,则throw new MyDefinedExcption(“message”)。代码如下:
①MyDefinedException:
public class MyDefinedException extends Exception {
String message;
public MyDefinedException(String message) {
super(message);
this.message = message;
}
}
②MyExceptionResolver:
@Controller
public class MyExceptionResolver implements HandlerExceptionResolver {
@Override
public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
String message = null;
ModelAndView modelAndView = new ModelAndView();
MyDefinedException definedException;
if (e instanceof MyDefinedException) {
definedException = (MyDefinedException) e;
} else {
definedException = new MyDefinedException("unknown errror");
}
message = ((MyDefinedException) e).getMessage();
modelAndView.addObject("message",message);
modelAndView.setViewName("error");
return modelAndView;
}
}
③在springmvc.xml文件里配置MyExceptionResolver :
<context:component-scan base-package="com.fusong.Handler,com.fusong.exception"/>
④controller方法里应用如下:
if (itemsList == null) {
throw new MyDefinedException("找不到该商品");
}
21.springmvc对restful的支持:
RESTful的理解:它是Representational State Transfer的缩写,表现层状态转化。它是一种软件开发理念,对http做了很好的诠释。
RESTful架构:
①每一个URL代表一种资源
②客户端与服务器之间,传递这种资源的某种表现层
③客户端通过四个HTTP动词,get(获取资源),post(新建资源),put(更新资源),delete(删除资源)对服务器端资源进行操作,分别对应。实现表现层状态转化。(真正实现上面这三条不多。)
*传统的url:http://localhost:8080/editItemsList.action?goodId=3&goodId=4
RESTful的url很简洁:http://localhost:8080/editItemsList/3/4
*参数通过url传递,rest接口返回json数据。
*想要以这种方式返回数据http://localhost:8080/editItemsList/3/4,需要更改前端配置。
*更改前端配置在web.xml里:
<!--RESTful的配置-->
<servlet>
<servlet-name>RESTfultest</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:config/springmvc.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>RESTfultest</servlet-name>
<!--注意/后面不能加*号-->
<url-pattern>/</url-pattern>
</servlet-mapping>
*参数通过url传递的解决方式:
//RequestMapping中指定restful方式的url中的参数,参数需要{}包
//@PathVariable将url中的参数和方法的形参进行绑定
@RequestMapping(value = "/editItemsMap/{goodId}", method = {RequestMethod.POST, RequestMethod.GET})
public ModelAndView editItemsMap(@PathVariable(value = "goodId") int id) throws Exception {
ApplicationContext context = new ClassPathXmlApplicationContext("config/applicationContext.xml");
MyService myService = (MyService) context.getBean("service");
ModelAndView modelAndView = new ModelAndView();
Items itemsList = myService.queryItem(id);
if (itemsList == null) {
throw new MyDefinedException("找不到该商品");
}
modelAndView.addObject("itemsList", itemsList);
modelAndView.setViewName("editItems");
return modelAndView;
}
访问方式为:http://localhost:8080/editItemsMap/3
<select id="queryItem" parameterType="int" resultMap="ItemsResultMap">
SELECT * FROM items WHERE id=#{Userid}
</select>
22.Controller用String方法返回:
@RequestMapping(value = "/selectItemsList", method = {RequestMethod.POST, RequestMethod.GET})
public String selectItemsList(Model model) throws Exception {
ApplicationContext context = new ClassPathXmlApplicationContext("config/applicationContext.xml");
MyService myService = (MyService) context.getBean("service");
List<Items> itemsList = myService.selectItemsMap("Little cookis");
model.addAttribute("itemsList", itemsList);
return "ItemsList";
}
23.以后我再用spring创建对象的时候,就这样用:
在applicationContext里面:
<!--<!– 扫描service包下所有使用注解的类型 –>-->
<context:component-scan base-package="com.fusong.service" ></context:component-scan>
在service里:
@Component("service")
public class MyServiceImp implements MyService {
在springmvc.xml所管理的handler里:
@Controller
@RequestMapping("Items")
public class MyHandler extends HttpServlet {
//@Resource
@Autowired
public MyService myService;
注意:写测试类@Test,是检测不到myService的,但是在网页上却能用。
24.springmvc拦截器:
拦截器的异常场合:
用户请求到DispatcherServlet中,DispatcherServlet调用HandlerMapping查找Handler,HandlerMapping返回
一个拦截的链(多个拦截),springmvc中的拦截器是通过HandlerMapping发起的。
在企业开发中,使用拦截器实现用户验证,用户权限拦截。
拦截器的定义方法:在springmvc里配置全局拦截器:
<!--全剧配置拦截器-->
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="com.fusong.intercepter.MyInterpter1"/>
</mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="com.fusong.intercepter.MyInterpter2"/>
</mvc:interceptor>
</mvc:interceptors>
25.对于拦截器的认识:
*SpringMVC 中的Interceptor 拦截请求是通过HandlerInterceptor 来实现的
*在SpringMVC 中定义一个Interceptor 非常简单,主要有两种方式,第一种方
式是要定义的Interceptor类要实现了Spring 的HandlerInterceptor 接口
* HandlerInterceptor 接口中定义了三个方法,我们就是通过这三个方法来对用户的请求进行拦截处理的。
*preHandle (HttpServletRequest request, HttpServletResponse response, Object handle) 方法:
①顾名思义,该方法将在请求处理之前进行调用。SpringMVC 中的Interceptor 是链式的调用的,在一个应用中或者说是在一个请求中可以同时存在多个Interceptor 。每个Interceptor 的调用会依据它的声明顺序依次执行,而且最先执行的都是Interceptor 中的preHandle 方法
②该方法的返回值是布尔值Boolean 类型的,当它返回为false 时,表示请求结束,后续的Interceptor 和Controller 都不会再执行;当返回值为true 时就会继续调用下一个Interceptor 的preHandle 方法,如果已经是最后一个Interceptor 的时候就会是调用当前请求的Controller 方法。
*postHandle (HttpServletRequest request, HttpServletResponse response, Object handle, ModelAndView modelAndView) 方法
①由preHandle 方法的解释我们知道这个方法包括后面要说到的afterCompletion 方法都只能是在当前所属的Interceptor 的preHandle 方法的返回值为true 时才能被调用。
②postHandle 方法,顾名思义就是在当前请求进行处理之后,也就是Controller 方法调用之后执行,但是它会在DispatcherServlet 进行视图返回渲染之前被调用,所以我们可以在这个方法中对Controller 处理之后的ModelAndView 对象进行操作
*afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handle, Exception ex) 方法
顾名思义,该方法将在整个请求结束之后,也就是在DispatcherServlet 渲染了对应的视图之后执行。这个方法的主要作用是用于进行资源清理工作的。
26.拦截器,对于每个要访问的URL都会进行一次拦截。