前言:一年前看视频学习这个框架的时候做的笔记。。。现在自己看来觉得还是有点蛋疼。。。想了想还是放上来了,万一开发要看呢,求勿喷。。。
springmvc
- 执行流程的过程图:
- 具体执行流程(这个就是现在自己手写的啦):
1.用户提交请求。
2.DispatchServlet接收到请求,将请求交给 HandlerMapping处理,而HandlerMapping将会把请求映射为HandlerExecutionChain对象(包含一个Handler处理器(页面控制器)对象、多个HandlerInterceptor拦截器)对象。
3.DispatchSerlvet调用HandlerAdapter来调用Handler(Controller),HandlerAdapter将会把处理器包装为适配器,HandlerAdapter将会根据适配的结果调用真正的处理器的功能处理方法,完成功能处理;并返回一个ModelAndView对象(包含模型数据、逻辑视图名)
4.DispatchServlet调用ViewResolver,ViewResolver将把逻辑视图名解析为具体的View。
5.将Model的数据渲染到View上。
6.将View返回到用户。
-
基本配置(xml版):
先导入jar包,如下:
<code>commons-logging.jar
org.springframework.asm-3.0.5.RELEASE.jar
org.springframework.beans-3.0.5.RELEASE.jar
org.springframework.context-3.0.5.RELEASE.jar
org.springframework.core-3.0.5.RELEASE.jar
org.springframework.expression-3.0.5.RELEASE.jar
org.springframework.web.servlet-3.0.5.RELEASE.jar
org.springframework.web-3.0.5.RELEASE.jar</code>在web.xml中配置核心过滤器:
<code><servlet>
<servlet-name>DispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>DispatcherServlet</servlet-name>
// 确保了只有action后缀名的请求才可以提交到后台
<url-pattern>*.action</url-pattern>
</servlet-mapping>
</code>开发action(实现controller接口):
<code>
public class HelloAction implements Controller{
// 构造函数,下文有惊喜
public HelloAction() {
System.out.println("HelloAction():"+this.hashCode());
}
@Override
public ModelAndView handleRequest(HttpServletRequest request,
HttpServletResponse response) throws Exception {
// ModelAndView表示封装的Model数据和View视图
System.out.println("handleRequest()");
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("message", "this is my first springmvc app");
// 没配置逻辑视图的要配置文件路径
// 如:modelAndView.setViewName("./jsp/success.jsp");
modelAndView.setViewName("success");
return modelAndView;
}
}
</code>在配置xml中配置映射(要注意的是,上面的配置核心过滤器步骤,没有指定配置文件,所以默认叫做DispatcherServlet-servlet.xml,而且是放在WEB-INF目录下):
<code>
<bean name="/hello.action" class="com.ycTime.action.HelloAction"></bean></code>自定义配置文件路径:
<code>
<servlet>
<servlet-name>DispatcherServlet</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>
</code>-
配置逻辑视图(直接返回页面的名字),需要在springmvc.xml(我的配置叫这个名字而已)那里配置:
<code>
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/jsp/"></property>
<property name="suffix" value=".jsp"></property>
</bean></code>
-
注解版:
直接加注解,无需在springmvc.xml那里配置action,只需要配置好扫描的包就可以直接使用,贼他妈迅速。
代码:<code>
@Controller
@RequestMapping(value="/json")
public class JsonAction</code>
@Controller的意思是把类声明为controller。@RequestMapping是请求的控制,比如value就是控制namespace(映射路径),还有method之类的参数。扫描配置:
<code>
<context:component-scan base-package="com.ycTime.action"></context:component-scan>
这个的前提:
xmlns:context="http://www.springframework.org/schema/context"
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
在xml那里配置声明,不然用不了context标签
</code>
收集参数(不分版本):
收集参数并封装为对象
<code>
@RequestMapping(value="/register",method=RequestMethod.POST)
public String register(Model model, User user){
System.out.println(user.getUsername()+":"+user.getPassword()+
":"+user.getJoinDate().toLocaleString());
model.addAttribute("message", "注册成功");
model.addAttribute("user", user);
return "success";
}</code>
直接在函数的参数列表里面写上就好了,参数名字与提交的值的名字必须对应,例子中的user是直接将参数封装成User对象,注意参数的名字在user类里面必须有setter方法
参数里面里面有个model,这个就是可以操作request域数据的对象
![可以直接收集提交的数据,也可以收集URL中的数据,后者需要在value上用{}标注关键词名字,在参数列表中使用@PathVariable收集到该参数-
收集多类型参数:
list:
<code>
在表单那里:
<input type="text" name="userList[0].username" >
// action中的方法
public String getArray(Model model, Bean bean){
// 在代码中直接获取list或者数组就可以了
List<User> userList = bean.getUserList();
}
// Bean对象
public class Bean {
private List<User> userList;
public List<User> getUserList() {
return userList;
}
public void setUserList(List<User> userList) {
this.userList = userList;
}
}</code>
其实这个和收集并封装成user是一样的,因为封装user的时候是用表单中提交的值来完成user的实例化操作,其中表单的name和user的属性名是一致的。
而封装list的话,表单名字中的userList[0]正好作为bean里面的setList(List<User> userList)的参数,也就是用userList来完成实例化操作。数组:<code>
// 表单
<td><input type="checkbox" name="ids" value="1">1</td>
<td>sivan</td>
<td><input type="checkbox" name="ids" value="2">2</td>
<td>tom</td>
// action 方法
@RequestMapping(value="/getArray")
public String getArray(Model model, String[] ids){
System.out.print("被选中的序号是:");
for (String string : ids) {
System.out.print(string+" ");
}
model.addAttribute("message", "xuanzhong成功");
return "success";
}</code>
返回Json数据
- 首先需要导包
<code>jackson-core-asl-1.9.11.jar
jackson-mapper-asl-1.9.11.jar</code> - 然后在action函数返回值那里加一个类型标签@ResponseBody,返回值直接返回某个对象,不返回字符串
<code>
@RequestMapping(value="/map2json")
public @ResponseBody Map<String,User> map2Json(){
Map<String,User> userMap = new HashMap<>();
for(int i = 0;i<4;i++){
User user = new User();
user.setId(i);
user.setJoinDate(new Date());
user.setUsername("Liming");
user.setAge(i*6-i+3);
userMap.put(i+"", user);
}
return userMap;
}
</code> - 最后在springmvc.xml配置下适配器(不然会报找不到适配器的错误):
<code><bean
class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="messageConverters">
<list>
<bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"></bean>
</list>
</property>
</bean></code>
springmvc拦截器
- 创建拦截器,实现HandlerInterceptor接口(也可以实现WebRequestInterceptor接口):
<code>public class FirstInterceptor implements HandlerInterceptor{
@Override
public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
throws Exception {
System.out.println("执行afterCompletion方法");
}
// modelAndView参数:可以控制需要显示的视图
@Override
public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView modelAndView)
throws Exception {
System.out.println("执行postHandle方法");
}
/* 返回值:表示我们是否需要将当前的请求拦截下来
false: 请求被中止
true: 请求继续
obj参数:表示的当前被拦截的请求目标(请求对应的类,比如说user2json请求,即obj是UserAction类)
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object obj) throws Exception {
System.out.println("执行preHandle方法");
return true;
}
}
jieguo :
FirstInterceptor执行preHandle方法
FirstInterceptor执行postHandle方法
FirstInterceptor执行afterCompletion方法
</code>
其中,preHandle方法是在请求被处理之前执行,postHandle在请求被处理之后执行,afterCompletion方法是在请求结束之后执行
在springmvc的配置文件中注册拦截器:
<code>
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/user/*.action"/>
<mvc:mapping path="/json/user2json.action"/>
<bean class="com.ycTime.interceptor.FirstInterceptor"></bean>
</mvc:interceptor>
</mvc:interceptors>
</code>-
当有多个拦截器一起工作的时候,工作流程如图:
<code>
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/user/.action"/>
<mvc:mapping path="/json/user2json.action"/>
<bean class="com.ycTime.interceptor.FirstInterceptor"></bean>
</mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="/user/.action"/>
<mvc:mapping path="/json/user2json.action"/>
<bean class="com.ycTime.interceptor.SecondInterceptor"></bean>
</mvc:interceptor>
</mvc:interceptors>
结果:
FirstInterceptor执行preHandle方法
SecondInterceptor执行preHandle方法
1 Liming 注册于 :26 Mon Mar 13 17:59:40 CST 2017
SecondInterceptor执行postHandle方法
FirstInterceptor执行postHandle方法
SecondInterceptor执行afterCompletion方法
FirstInterceptor执行afterCompletion方法</code> 拦截起使用场景:解决业务共性问题
比如:
1)字符编码例如request.setCharacterEncoding("utf-8");response.setCharacterEncoding("utf-8");(假设没配置字符串过滤器,)
2)权限校验(request.getSession().getAttribute("user")!=null等)
方法和struts2都是一样的,通过request或者response加以控制来实现。
- 提一下过滤器
配置字符过滤器:
<code><filter>
<filter-name>encoding</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encoding</filter-name>
<url-pattern>*</url-pattern>
</filter-mapping></code> - 拦截器与过滤器区别:
①拦截器是基于java的反射机制的,而过滤器是基于函数回调。
②拦截器不依赖与servlet容器,过滤器依赖与servlet容器。
③拦截器只能对action请求起作用,而过滤器则可以对几乎所有的请求起作用。
④拦截器可以访问action上下文、值栈里的对象,而过滤器不能访问。
⑤在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次。
⑥拦截器可以获取IOC容器中的各个bean,而过滤器就不行,这点很重要,在拦截器里注入一个service,可以调用业务逻辑