前言:一年前看視頻學(xué)習(xí)這個(gè)框架的時(shí)候做的筆記。渗柿「雠瑁〈滂耄現(xiàn)在自己看來(lái)覺(jué)得還是有點(diǎn)蛋疼玫鸟。谅将。中跌。想了想還是放上來(lái)了谋逻,萬(wàn)一開(kāi)發(fā)要看呢沼死,求勿噴也搓。和媳。声登。
springmvc
- 執(zhí)行流程的過(guò)程圖:
- 具體執(zhí)行流程(這個(gè)就是現(xiàn)在自己手寫的啦):
1.用戶提交請(qǐng)求狠鸳。
2.DispatchServlet接收到請(qǐng)求,將請(qǐng)求交給 HandlerMapping處理悯嗓,而HandlerMapping將會(huì)把請(qǐng)求映射為HandlerExecutionChain對(duì)象(包含一個(gè)Handler處理器(頁(yè)面控制器)對(duì)象件舵、多個(gè)HandlerInterceptor攔截器)對(duì)象。
3.DispatchSerlvet調(diào)用HandlerAdapter來(lái)調(diào)用Handler(Controller)脯厨,HandlerAdapter將會(huì)把處理器包裝為適配器铅祸,HandlerAdapter將會(huì)根據(jù)適配的結(jié)果調(diào)用真正的處理器的功能處理方法,完成功能處理合武;并返回一個(gè)ModelAndView對(duì)象(包含模型數(shù)據(jù)临梗、邏輯視圖名)
4.DispatchServlet調(diào)用ViewResolver,ViewResolver將把邏輯視圖名解析為具體的View稼跳。
5.將Model的數(shù)據(jù)渲染到View上盟庞。
6.將View返回到用戶。
-
基本配置(xml版):
先導(dǎo)入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中配置核心過(guò)濾器:
<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后綴名的請(qǐng)求才可以提交到后臺(tái)
<url-pattern>*.action</url-pattern>
</servlet-mapping>
</code>開(kāi)發(fā)action(實(shí)現(xiàn)controller接口):
<code>
public class HelloAction implements Controller{
// 構(gòu)造函數(shù)什猖,下文有驚喜
public HelloAction() {
System.out.println("HelloAction():"+this.hashCode());
}
@Override
public ModelAndView handleRequest(HttpServletRequest request,
HttpServletResponse response) throws Exception {
// ModelAndView表示封裝的Model數(shù)據(jù)和View視圖
System.out.println("handleRequest()");
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("message", "this is my first springmvc app");
// 沒(méi)配置邏輯視圖的要配置文件路徑
// 如:modelAndView.setViewName("./jsp/success.jsp");
modelAndView.setViewName("success");
return modelAndView;
}
}
</code>在配置xml中配置映射(要注意的是票彪,上面的配置核心過(guò)濾器步驟,沒(méi)有指定配置文件不狮,所以默認(rèn)叫做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>-
配置邏輯視圖(直接返回頁(yè)面的名字),需要在springmvc.xml(我的配置叫這個(gè)名字而已)那里配置:
<code>
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/jsp/"></property>
<property name="suffix" value=".jsp"></property>
</bean></code>
-
注解版:
直接加注解铃彰,無(wú)需在springmvc.xml那里配置action,只需要配置好掃描的包就可以直接使用芯咧,賊他媽迅速牙捉。
代碼:<code>
@Controller
@RequestMapping(value="/json")
public class JsonAction</code>
@Controller的意思是把類聲明為controller。@RequestMapping是請(qǐng)求的控制敬飒,比如value就是控制namespace(映射路徑)邪铲,還有method之類的參數(shù)。掃描配置:
<code>
<context:component-scan base-package="com.ycTime.action"></context:component-scan>
這個(gè)的前提:
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標(biāo)簽
</code>
收集參數(shù)(不分版本):
收集參數(shù)并封裝為對(duì)象
<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", "注冊(cè)成功");
model.addAttribute("user", user);
return "success";
}</code>
直接在函數(shù)的參數(shù)列表里面寫上就好了带到,參數(shù)名字與提交的值的名字必須對(duì)應(yīng),例子中的user是直接將參數(shù)封裝成User對(duì)象英染,注意參數(shù)的名字在user類里面必須有setter方法
參數(shù)里面里面有個(gè)model揽惹,這個(gè)就是可以操作request域數(shù)據(jù)的對(duì)象
![可以直接收集提交的數(shù)據(jù),也可以收集URL中的數(shù)據(jù)四康,后者需要在value上用{}標(biāo)注關(guān)鍵詞名字搪搏,在參數(shù)列表中使用@PathVariable收集到該參數(shù)-
收集多類型參數(shù):
list:
<code>
在表單那里:
<input type="text" name="userList[0].username" >
// action中的方法
public String getArray(Model model, Bean bean){
// 在代碼中直接獲取list或者數(shù)組就可以了
List<User> userList = bean.getUserList();
}
// Bean對(duì)象
public class Bean {
private List<User> userList;
public List<User> getUserList() {
return userList;
}
public void setUserList(List<User> userList) {
this.userList = userList;
}
}</code>
其實(shí)這個(gè)和收集并封裝成user是一樣的,因?yàn)榉庋buser的時(shí)候是用表單中提交的值來(lái)完成user的實(shí)例化操作闪金,其中表單的name和user的屬性名是一致的疯溺。
而封裝list的話,表單名字中的userList[0]正好作為bean里面的setList(List<User> userList)的參數(shù)哎垦,也就是用userList來(lái)完成實(shí)例化操作囱嫩。數(shù)組:<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("被選中的序號(hào)是:");
for (String string : ids) {
System.out.print(string+" ");
}
model.addAttribute("message", "xuanzhong成功");
return "success";
}</code>
返回Json數(shù)據(jù)
- 首先需要導(dǎo)包
<code>jackson-core-asl-1.9.11.jar
jackson-mapper-asl-1.9.11.jar</code> - 然后在action函數(shù)返回值那里加一個(gè)類型標(biāo)簽@ResponseBody,返回值直接返回某個(gè)對(duì)象漏设,不返回字符串
<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配置下適配器(不然會(huì)報(bào)找不到適配器的錯(cuò)誤):
<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攔截器
- 創(chuàng)建攔截器墨闲,實(shí)現(xiàn)HandlerInterceptor接口(也可以實(shí)現(xiàn)WebRequestInterceptor接口):
<code>public class FirstInterceptor implements HandlerInterceptor{
@Override
public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
throws Exception {
System.out.println("執(zhí)行afterCompletion方法");
}
// modelAndView參數(shù):可以控制需要顯示的視圖
@Override
public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView modelAndView)
throws Exception {
System.out.println("執(zhí)行postHandle方法");
}
/* 返回值:表示我們是否需要將當(dāng)前的請(qǐng)求攔截下來(lái)
false: 請(qǐng)求被中止
true: 請(qǐng)求繼續(xù)
obj參數(shù):表示的當(dāng)前被攔截的請(qǐng)求目標(biāo)(請(qǐng)求對(duì)應(yīng)的類,比如說(shuō)user2json請(qǐng)求愿题,即obj是UserAction類)
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object obj) throws Exception {
System.out.println("執(zhí)行preHandle方法");
return true;
}
}
jieguo :
FirstInterceptor執(zhí)行preHandle方法
FirstInterceptor執(zhí)行postHandle方法
FirstInterceptor執(zhí)行afterCompletion方法
</code>
其中损俭,preHandle方法是在請(qǐng)求被處理之前執(zhí)行,postHandle在請(qǐng)求被處理之后執(zhí)行潘酗,afterCompletion方法是在請(qǐng)求結(jié)束之后執(zhí)行
在springmvc的配置文件中注冊(cè)攔截器:
<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>-
當(dāng)有多個(gè)攔截器一起工作的時(shí)候杆兵,工作流程如圖:
<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>
結(jié)果:
FirstInterceptor執(zhí)行preHandle方法
SecondInterceptor執(zhí)行preHandle方法
1 Liming 注冊(cè)于 :26 Mon Mar 13 17:59:40 CST 2017
SecondInterceptor執(zhí)行postHandle方法
FirstInterceptor執(zhí)行postHandle方法
SecondInterceptor執(zhí)行afterCompletion方法
FirstInterceptor執(zhí)行afterCompletion方法</code> 攔截起使用場(chǎng)景:解決業(yè)務(wù)共性問(wèn)題
比如:
1)字符編碼例如request.setCharacterEncoding("utf-8");response.setCharacterEncoding("utf-8");(假設(shè)沒(méi)配置字符串過(guò)濾器,)
2)權(quán)限校驗(yàn)(request.getSession().getAttribute("user")!=null等)
方法和struts2都是一樣的惰蜜,通過(guò)request或者response加以控制來(lái)實(shí)現(xiàn)昂拂。
- 提一下過(guò)濾器
配置字符過(guò)濾器:
<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> - 攔截器與過(guò)濾器區(qū)別:
①攔截器是基于java的反射機(jī)制的,而過(guò)濾器是基于函數(shù)回調(diào)抛猖。
②攔截器不依賴與servlet容器格侯,過(guò)濾器依賴與servlet容器。
③攔截器只能對(duì)action請(qǐng)求起作用财著,而過(guò)濾器則可以對(duì)幾乎所有的請(qǐng)求起作用联四。
④攔截器可以訪問(wèn)action上下文、值棧里的對(duì)象撑教,而過(guò)濾器不能訪問(wèn)朝墩。
⑤在action的生命周期中,攔截器可以多次被調(diào)用伟姐,而過(guò)濾器只能在容器初始化時(shí)被調(diào)用一次收苏。
⑥攔截器可以獲取IOC容器中的各個(gè)bean,而過(guò)濾器就不行愤兵,這點(diǎn)很重要倒戏,在攔截器里注入一個(gè)service,可以調(diào)用業(yè)務(wù)邏輯