1 简介
Spring MVC是当前最优秀的 MVC 框架,自从Spring 2.5 版本发布后,由于支持注解配置,易用性有了大幅度的提高。
Spring 3.0 更加完善,实现了对Struts 2 的超越。现在越来越多的开发团队选择了Spring MVC。
1)Spring3 MVC使用简单,学习成本低。学习难度小于Struts2,Struts2用不上的多余功能太多
2)Spring3 MVC很容易就可以写出性能优秀的程序,Struts2要处处小心才可以写出性能优秀的程序(指MVC部分)
3)灵活
√让我们能非常简单的设计出干净的Web层和薄薄的Web层;
√进行更简洁的Web层的开发;
√天生与Spring框架集成(如IoC容器、AOP等);
√提供强大的约定大于配置的契约式编程支持;
√能简单的进行Web层的单元测试;
√支持灵活的URL到页面控制器的映射;
√非常容易与其他视图技术集成,如Velocity、FreeMarker等等,因为模型数据不放在特定的API里,
而是放在一个Model里(Map数据结构实现,因此很容易被其他框架使用);
√非常灵活的数据验证、格式化和数据绑定机制,能使用任何对象进行数据绑定,不必实现特定框架的API;
√提供一套强大的JSP标签库,简化JSP开发;
√支持灵活的本地化、主题等解析;
√更加简单的异常处理;
√对静态资源的支持;
√支持Restful风格
前端控制器是DispatcherServlet;
应用控制器其实拆为处理器映射器(Handler Mapping)进行处理器管理和视图解析器(View Resolver)进行视图管理;
页面控制器/动作/处理器为Controller接口(仅包含ModelAndView handleRequest(request, response) 方法)的实现(也可以是任何的POJO类);
支持本地化(Locale)解析、主题(Theme)解析及文件上传等;提供了非常灵活的数据验证、格式化和数据绑定机制;
提供了强大的约定大于配置(惯例优先原则)的契约式编程支持。
2 配置核心控制器
搭建springmvc 的环境,要以下几步
1) 导包
aopalliance-1.0.jar
bean-validator.jar
commons-fileupload-1.2.2.jar
commons-io-2.1.jar
commons-logging-1.2.jar
*javax.servlet.jsp.jstl-1.2.1.jar
*jsp-api-2.1.jar
*jstl-1.2.jar
*jstl-api-1.2.jar
mysql-connector-java-5.1.7-bin.jar
*servlet-api-2.5.jar
spring-aop-4.1.4.RELEASE.jar
spring-beans-4.1.4.RELEASE.jar
spring-context-4.1.4.RELEASE.jar
spring-core-4.1.4.RELEASE.jar
spring-expression-4.1.4.RELEASE.jar //可以看出来,用的Spring版本是4.1.4
spring-web-4.1.4.RELEASE.jar
spring-webmvc-4.1.4.RELEASE.jar
*standard-1.1.2.jar
2) 配置核心控制器
<?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_3_0.xsd" id="WebApp_ID" version="3.0">
...
<servlet>
<servlet-name>springAAA</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springAAA</servlet-name>
<url-pattern>/</url-pattern> <!-- 也可以写成 *.do, *.action 等 但,不要写成 杠*
</servlet-mapping>
</web-app>
注意:
默认情况下,这个servlet会加载一个配置文件 => WEB-INF/ 这个servlet的名称-servlet.xml 这个文件 springAAA-servlet.xml(里面是什么我们不用管,这是默认情况会有这个文件,但是现在工程里没有)
如果不使用默认值的情况下,我们也可以指定文件的名称和路径,可以如下配置
<servlet>
<servlet-name>springAAA</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name> //这个名称是固定的
<param-value>classpath*:springmvc-config.xml</param-value> //配置springmvc主配置文件的路径
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springAAA</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
3 配置 配置处理器映射器, 配置处理器适配器, 配置视图解析器 (即配置主文件)
1) 创建 springmvc-config.xml 这个配置文件 ,放在类路径下(src 就是)
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd">
处理器映射器
处理器适配器
视图解析器
</beans>
2) 处理器映射器
<bean name="/search_all" class="com.controller.AdminAction" />
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping" />
//控制层的方法
public class AdminAction implements Controller{
private AdminDao dao=new AdminDao();
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
List<AdminInfo> adminList=dao.getAllAdmin();
ModelAndView mv=new ModelAndView();
mv.addObject("adminList",adminList); //=>request.setAttribute("adminList",adminList);
//mv.setViewName("WEB-INF/jsp/admin_manage.jsp");
mv.setViewName("admin_manage"); // 前缀+ 视图名称 + 后缀 =>/WEB-INF/jsp/admin_manage.jsp
return mv;
}
}
注意: 这个类要实现 Controller接口, 这个接口中的方法,传过来了request,response等对象,这些对象可以使用
3) 处理器适配器
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter" /> //Adapter 适配器的意思
4) 视图解析器
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" >
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
5) WEB-INF 下的 jsp 文件夹 admin_manage.jsp:
<table width=80% border=1px>
<c:forEach var="admin" items="${adminList }">
<tr>
<td>${admin.id }</td>
<td>${admin.adminName }</td>
<td>${admin.password }</td>
<td>${admin.note }</td>
</tr>
</c:forEach>
</table>
测试:程序运行流程: web.xml 拦下所有的请求,这个核心控制器把他交给springmvc处理,
也就是 springmvc-config.xml,处理器映射器把 请求 /search_all 交给 AdminAction,
然后走 handleRequest 方法,进行查询转向。
在浏览器地址栏中输入: http://localhost:8080/springmvc/search_all , 就可以看到数据了
4 基于注解的 处理器映射器 和 处理器适配器
1) 开启扫描
<context:component-scan base-package="com.controller" />
2) 使用下面的处理器映射器和处理器适配器
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"></bean>
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"></bean>
也可以写成
<mvc:annotation-driven /> 有了这句,上面的两个类就可以不用配置了 //开启注解驱动
3) 视图解析器,和以前一样即可
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" >
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
控制层:
@Controller
public class UserAction {
UserDao dao=new UserDao();
@RequestMapping("/search_all_user")
public ModelAndView getAllUser(){
List<UserInfo> userList=dao.getAllUser();
ModelAndView mv=new ModelAndView();
mv.addObject("userList",userList);
mv.setViewName("user_manage");
return mv;
}
}
userlist.jsp
<table border="1" width="500">
<c:forEach var="user" items="${userList}" >
<tr>
<td>${user.id }</td>
<td>${user.userName }</td>
<td>${user.password }</td>
<td>${user.school }</td>
</tr>
</c:forEach>
</table>
5 @RequestMapping 注解, 和 Action中方法的返回值
1) @RequestMapping 注解的说明
@RequestMapping 将请求的url和处理这个请求的方法进行映射 ,一个url对应一个方法
@RequestMapping 也可以用在类体上
例子:
@Controller @RequestMapping("/user") //@RequestMapping
public class UserAction {
UserDao dao=new UserDao();
@RequestMapping("/search_all_user")
public ModelAndView getAllUser(){
....
}
}
访问地址: http://localhost:8080/springmvc-01/user/search_all_user
@RequestMapping 注解一共有六个属性 value , method , consumes , produces , params , headers
(1) value
@RequestMapping("/search_all_user") 等效于 @RequestMapping(value= "/search_all_user")
(2) method 指定请求的类型 GET,POST,PUT,DELETE
例子:查询出用户信息 进行修改
user_manage.jsp:
添加一列 <td><a href="update_user?id=${user.id }" >修改</a></td>
UserAction:
创建 WEB-INF 下的 user_edit.jsp:
<form action="update_user" method="post">
<input type="hidden" name="id" value="${user.id }" >
<input type="text" name="userName" value="${user.userName }" >
<input type="text" name="password" value="${user.password }" >
<input type="text" name="note" value="${user.note }" >
<input type="submit" value="提交" >
</form>
@RequestMapping(value="/update_user",method=RequestMethod.GET) //表示只对get请求有效
public ModelAndView searchForUpdate(HttpServletRequest request){ //根据id查询出户信息 转到用户修改页面
int id=Integer.parseInt(request.getParameter("id"));
UserInfo user=dao.getUserById(id);
ModelAndView mv=new ModelAndView("user_edit","user",user);
return mv;
}
@RequestMapping(value="/update_user",method=RequestMethod.POST)
public String updateUser(){
//....
return null;
}
如果一个方法不区分get请求和post请求 , 可以不写 method属性
或 @RequestMapping(value= "/search_all_user" ,method={RequestMethod.GET,RequestMethod.POST }
(3) consumes: 指定处理请求的提交内容类型(Content-Type),例如application/json, text/html;
(4) produces: 指定返回的内容类型,仅当request请求头中的(Accept)类型中包含该指定类型才返回
(5) params: 指定request中必须包含某些参数值时,才让该方法处理。 //实测发现如果指定了,不传将出错
(6) headers: 指定request中必须包含某些指定的 header 值,才能让该方法处理请求。
2) Action中方法的返回
(1) ModelAndView 模型数据和视图
(2) String 这个返回值就是逻辑视图的名称 真正的视图=前缀+逻辑视图+后缀 例如 return "success" => WEB-INF/jsp/success.jsp
@RequestMapping(value="/update_user",method=RequestMethod.POST)
public String updateUser(UserInfo user){
dao.updateUser(user);
return "user_edit"; =>WEB-INF/jsp/user_edit.jsp
}
3) void
@RequestMapping(value="/update_user",method=RequestMethod.POST) //传参顺序可以串
public void updateUser(UserInfo user,HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException{
dao.updateUser(user);
//要写全名称,配置文件里的前缀和后缀在这不起作用
request.getRequestDispatcher("/WEB-INF/jsp/user_edit.jsp").forward(request, response);
//可以这样返回 json数据
//response.getWriter().print("{\"id\":\"10\",\"userName\":\"admin\",\"password\":\"123\"}");
}