一、Spring mvc是什么?
Spring mvc和Struts2都属于表现层的框架,它是Spring框架的一部分
二、Spring mvc运行流程(架构)
1、用户发送请求至前端控制器DispatcherServlet
2、DispatcherServlet收到请求调用HandlerMapping处理器映射器。
3、处理器映射器根据请求url找到具体的处理器,生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet。
4、DispatcherServlet通过HandlerAdapter处理器适配器调用处理器
5、执行处理器(Controller,也叫后端控制器)。
6、Controller执行完成返回ModelAndView
7、HandlerAdapter将controller执行结果ModelAndView返回给DispatcherServlet
8、DispatcherServlet将ModelAndView传给ViewReslover视图解析器
9、ViewReslover解析后返回具体View
10、DispatcherServlet对View进行渲染视图(即将模型数据填充至视图中)。
11、DispatcherServlet响应用户
三、组件说明
1、DispatcherServlet:前端控制器
用户请求到达前端控制器,它就相当于mvc模式中的c,dispatcherServlet是整个流程控制的中心,由它调用其它组件处理用户的请求,dispatcherServlet的存在降低了组件之间的耦合性。
2、HandlerMapping:处理器映射器
HandlerMapping负责根据用户请求找到Handler即处理器,springmvc提供了不同的映射器实现不同的映射方式,例如:配置文件方式,实现接口方式,注解方式等。
3、Handler:处理器
Handler 是继DispatcherServlet前端控制器的后端控制器,在DispatcherServlet的控制下Handler对具体的用户请求进行处理。
由于Handler涉及到具体的用户业务请求,所以一般情况需要程序员根据业务需求开发Handler。
4、HandlAdapter:处理器适配器
通过HandlerAdapter对处理器进行执行,这是适配器模式的应用,通过扩展适配器可以对更多类型的处理器进行执行。
5、ViewResolver:视图解析器
负责将处理结果生成View视图,ViewResolver首先根据逻辑视图名解析成物理视图名即具体的页面地址,再生成View视图对象,最后对View进行渲染将处理结果通过页面展示给用户。 springmvc框架提供了很多的View视图类型,包括:jstlView、freemarkerView、pdfView等。
四、框架搭建流程
1、导入相关架包,本处不阐述
2、配置前端控制器(DispatcherServlet),在WEB-INF\web.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:config/springmvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>*.action</url-pattern>
</servlet-mapping>
3.5.1 Servlet拦截方式
1、拦截固定后缀的url,比如设置为 .do、.action, 例如:/user/add.action
此方法最简单,不会导致静态资源(jpg,js,css)被拦截。
2、拦截所有,设置为/,例如:/user/add /user/add.action
此方法可以实现REST风格的url,很多互联网类型的应用使用这种方式。
但是此方法会导致静态文件(jpg,js,css)被拦截后不能正常显示。需要特殊处理。
方式一、在web.xml中配置
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.css</url-pattern>
</servlet-mapping>
方式二、在springmvc.xml中配置
<mvc:resources location="/js/" mapping="/js/**"/>
<mvc:resources location="/img/" mapping="/img/**"/>
3、拦截所有,设置为/*,此设置方法错误,因为请求到Action,当action转到jsp时再次被拦截,提示不能根据jsp路径mapping成功。
3、配置处理器映射器(HandlerMapping)和处理器适配器(HandlerAdapter)(注解方式,其他本处不再阐述),在springMVC.xml中配置
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/>
springmvc使用<mvc:annotation-driven>
自动加载RequestMappingHandlerMapping和RequestMappingHandlerAdapter,可用在springmvc.xml配置文件中使用替代注解处理器和适配器的配置
<mvc:annotation-driven />
4、配置试图解析器(viewResolver),在springMVC.xml中配置
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
5、配置主键扫描器
<context:component-scan base-package="com.bl" />
五、注解
1、@Controller
配置此注解的class才能被扫描器扫描为springMVC的Handler
2、@RequestMapping(value = “/getlist”,method = RequestMethod.GET)
此注解用在class上或者method上,表示请求URL和请求方式
3、@RequestParam
value:参数名字,即入参的请求参数名字,如value=“item_id”表示请求的参数区中的名字为item_id的参数的值将传入;
required:是否必须,默认是true
public String editItem(@RequestParam(value="item_id",required=true) String id) {}
六、Controller的返回值
1、返回ModelAndView,controller方法中定义ModelAndView对象并返回,对象中可添加model数据、指定view
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("testlist", testlist);
modelAndView.setViewName("testList");
2、返回void
在controller方法形参上可以定义request和response,使用request或response指定响应结果:
使用request转向页面:
request.getRequestDispatcher(“页面路径”).forward(request,response);
通过response页面重定向:
response.sendRedirect(“url”)
通过response指定响应结果,例如响应json数据如下:
response.setCharacterEncoding(“utf-8”);
response.setContentType(“application/json;charset=utf-8”);
response.getWriter().write(“json串”);
3、返回字符串,controller方法返回字符串可以指定逻辑视图名,通过视图解析器解析为物理视图地址。
//指定逻辑视图名,经过视图解析器解析为jsp物理路径:/WEB-INF/jsp/item/editItem.jsp
return “item/editItem”;
Redirect重定向
return “redirect:queryItem.action”;//如果要传参数可以/item/queryItem.action后边加参数,如:/item/queryItem?name=”张三”&age=24
forward转发
return “forward:editItem.action”;
七、参数绑定
Model
通过model向页面传递数据,如下:
Items item = itemService.findItemById(id);
model.addAttribute("item", item);
页面通过${item.XXXX}获取item对象的属性值
2、@RequestParam
@RequestParam用于绑定单个请求参数。
value:参数名字,即入参的请求参数名字,如value=“item_id”表示请求的参数区中的名字为item_id的参数的值将传入;
required:是否必须,默认是true,表示请求中一定要有相应的参数,否则将报;
TTP Status 400 - Required Integer parameter ‘XXXX’ is not present
defaultValue:默认值,表示如果请求中没有同名参数时的默认值
定义如下:
public String editItem(@RequestParam(value="item_id",required=true) String id) {}
3、简单类型
当请求的参数名称和处理器形参名称一致时会将请求参数与形参进行绑定
public String editItem(Model model,Integer id) throws Exception{
}
4、自定义参数绑定(难点,不阐述)
5、POJO(即java类)
1、简单pojo
将pojo对象中的属性名于传递进来的属性名对应,如果传进来的参数名称和对象中的属性名称一致则将参数值设置在pojo对象中
页面定义如下;
<input type="text" name="name"/>
<input type="text" name="price"/>
Contrller方法定义如下:
@RequestMapping("/editItemSubmit")
public String editItemSubmit(Items items)throws Exception{
System.out.println(items);
}
请求的参数名称和pojo的属性名称一致,会自动将请求参数赋值给pojo的属性。
2、包装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());
}
6、集合类
1、字符串数组
页面定义如下:
页面选中多个checkbox向controller方法传递
<input type="checkbox" name="item_id" value="001"/>
<input type="checkbox" name="item_id" value="002"/>
<input type="checkbox" name="item_id" value="002"/>
传递到controller方法中的格式是:001,002,003
Controller方法中可以用String[]接收,定义如下:
public String deleteitem(String[] item_id)throws Exception{
System.out.println(item_id);
}
2、List
List中存放对象,并将定义的List放在包装类中,action使用包装对象接收。
Public class QueryVo {
Private List<Items> itemList;
}
包装类中定义List对象,并添加get/set方法如下:
页面:
<tr>
<td>
<input type="text" name=" itemList[0].id" value="${item.id}"/>
</td>
<td>
<input type="text" name=" itemList[0].name" value="${item.name }"/>
</td>
<td>
<input type="text" name=" itemList[0].price" value="${item.price}"/>
</td>
</tr>
<tr>
<td>
<input type="text" name=" itemList[1].id" value="${item.id}"/>
</td>
<td>
<input type="text" name=" itemList[1].name" value="${item.name }"/>
</td>
<td>
<input type="text" name=" itemList[1].price" value="${item.price}"/>
</td>
</tr>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
Contrller方法定义如下:
public String useraddsubmit(Model model,QueryVo queryVo)throws Exception{
System.out.println(queryVo.getItemList());
}
5.5.7.3 Map
在包装类中定义Map对象,并添加get/set方法,action使用包装对象接收。
包装类中定义Map对象如下:
Public class QueryVo {
private Map<String, Object> itemInfo = new HashMap<String, Object>();
}
页面定义如下:
<tr>
<td>学生信息:</td>
<td>
姓名:<inputtype="text"name="itemInfo['name']"/>
年龄:<inputtype="text"name="itemInfo['price']"/>
.. .. ..
</td>
</tr>
Contrller方法定义如下:
public String useraddsubmit(Model model,QueryVo queryVo)throws Exception{
System.out.println(queryVo.getStudentinfo());
}
八、乱码问题
1、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>
2、GET乱码
修改tomcat配置文件添加编码与工程编码一致,如下:
<Connector URIEncoding="utf-8" connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443"/>
另外一种方法对参数进行重新编码:
String userName = new String(request.getParamter("userName").getBytes("ISO8859-1"),"utf-8")
ISO8859-1是tomcat默认编码,需要将tomcat编码后的内容按utf-8编码
九、上传图片
1、导入架包
2、配置解析器
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize">
<value>5242880</value>
</property>
</bean>
3、编写controller
@RequestMapping("/editItemSubmit")
public String editItemSubmit(Items items, MultipartFile pictureFile)throws Exception{
String pictureFile_name = pictureFile.getOriginalFilename();
String newFileName = UUID.randomUUID().toString()+pictureFile_name.substring(pictureFile_name.lastIndexOf("."));
File uploadPic = new java.io.File("F:/develop/upload/temp/"+newFileName);
if(!uploadPic.exists()){
uploadPic.mkdirs();
}
pictureFile.transferTo(uploadPic);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
JSP
<input type="file" name="pictureFile" />
十、数据回显
1、贴上一篇文章的连接:http://blog.csdn.net/u012373815/article/details/47205657
2、@ModelAttribute将方法返回值传到页面
1、controller代码
@ModelAttribute("itemsType")
public Map<String, String> getItem(){
Map<String, String> map = new HashMap<String, String>();
map.put("001", "张三");
map.put("002", "李四");
return map;
}
2、JSP代码
<c:forEach items="${testlist }" var="item">
<tr>
<td>${item.id }</td>
<td>${item.val }</td>
<td><a href="${pageContext.request.contextPath }/editItem.action?id=${item.id}">修改</a></td>
</tr>
</c:forEach>
十一、JSON数据交互
需求:要使springMVC支持接收JSON数据和返回JSON数据
1、Springmvc默认用MappingJacksonHttpMessageConverter对json数据进行转换,需要加入jackson的包,如下:
2、在处理器适配器中注入MappingJacksonHttpMessageConverter
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<property name="messageConverters">
<list>
<bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter" />
</list>
</property>
</bean>
3、编写Controller
@RequestMapping(value="testjson")
public void testJson(HttpServletResponse response,@RequestBody Test test){
System.out.println(test.getVal());
try {
PrintWriter out = response.getWriter();
out.print("xxx");
} catch (IOException e) {
e.printStackTrace();
}
}
JAVA类
public class test{
@Basic(optional = false)
private Integer id;
@Column(name="VAL")
@Field
private String val;
}
十二、validation效验
http://haohaoxuexi.iteye.com/blog/1812584
十三、异常处理器(统一异常处理)
1、定义异常
public class CustomException extends Exception {
private String message;
public CustomException(String message){
super(message);
this.message = message;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
2、编写异常解析器
public class CustomExceptionResolver implements HandlerExceptionResolver {
@Override
public ModelAndView resolveException(HttpServletRequest request,
HttpServletResponse response, Object handler, Exception ex) {
ex.printStackTrace();
String message = null;
CustomException customException = null;
if(ex instanceof CustomException){
customException = (CustomException)ex;
}else{
customException = new CustomException("未知错误");
}
message = customException.getMessage();
request.setAttribute("message", message);
try {
request.getRequestDispatcher("/WEB-INF/jsp/error.jsp").forward(request, response);
} catch (ServletException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return new ModelAndView();
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
3、配置统一异常处理器
<bean class="com.xxx.CustomExceptionResolver"/>
4、抛出异常
可以在controller方法、service方法、dao实现类中抛出异常,要求dao、service、controller遇到异常全部向上抛出异常,方法向 上抛出异常throws Exception
if(xxx==null){
throw new CustomException("XXX不存在")
}
十四、设置静态资源解析
当DispatcherServlet拦截/开头的所有请求,对静态资源的访问就报错404:
需要通过设置对静态资源进行解析
<mvc:resources location="/js/" mapping="/js/**"/>
<mvc:resources location="/img/" mapping="/img/**"/>
表示访问/js/**的url从工程下/js/下解析和访问img下的url从img下解析
十五、SpringMvc拦截器
使用拦截器实现用户认证(用户登陆后进行身份校验拦截),用户权限拦截。
1、定义拦截器(实现HandlerInterceptor接口)
Public class HandlerInterceptor1 implements HandlerInterceptor{
/**
* controller执行前调用此方法
* 返回true表示继续执行,返回false中止执行
* 这里可以加入登录校验、权限拦截等
*/
@Override
Public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) throws Exception {
Return false;
}
/**
* controller执行后但未返回视图前调用此方法
* 这里可在返回用户前对模型数据进行加工处理,比如这里加入公用信息以便页面显示
*/
@Override
Public void postHandle(HttpServletRequest request,
HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
}
/**
* controller执行后且视图返回后调用此方法
* 这里可得到执行controller时的异常信息
* 这里可记录操作日志,资源清理等
*/
@Override
Public void afterCompletion(HttpServletRequest request,
HttpServletResponse response, Object handler, Exception ex)
throws Exception {
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
2、在springmvc.xml中配置拦截器
1、针对某种mapping配置
<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"/>
2、针对所有的mapping全局配置
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="cn.itcast.springmvc.filter.HandlerInterceptor1"></bean>
</mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="cn.itcast.springmvc.filter.HandlerInterceptor2"></bean>
</mvc:interceptor>
</mvc:interceptors>
3、拦截器应用
1、用户身份认证
Public class LoginInterceptor implements HandlerInterceptor{
@Override
Public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) throws Exception {
if(request.getRequestURI().indexOf("login.action")>=0){
return true;
}
HttpSession session = request.getSession();
if(session.getAttribute("user")!=null){
return true;
}
request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request, response);
return false;
}
}