是基于Spring3.1的。从Spring3.0之后,SpringMVC开始广泛使用基于注解的控制器,而不是继承AbstractController 类或者实现Controller接口了。虽然Struts2现在很流行,但是,个人觉得SpringMVC十分优雅,不比Struts2差。至少我在公司中,从来没用用过SpringMVC,而且貌似在国内的公司用SpringMVC做WEB层的不多吧。不过对Spring感兴趣的话,可以自己有空研究一下。
这下的是自己的一点总结,是一些常用的SpringMVC知识点。
- -------------------------------------------------启动SpringMVC-------------------------------------------------
- 1.要导入的JAR文件
- 必须的
- org.springframework.aop-3.1.0.RELEASE.jar
- org.springframework.asm-3.1.0.RELEASE.jar
- org.springframework.beans-3.1.0.RELEASE.jar
- org.springframework.context-3.1.0.RELEASE.jar
- org.springframework.core-3.1.0.RELEASE.jar
- org.springframework.expression-3.1.0.RELEASE.jar
- 数据访问
- org.springframework.jdbc-3.1.0.RELEASE.jar
- org.springframework.orm-3.1.0.RELEASE.jar
- org.springframework.transaction-3.1.0.RELEASE.jar
- 测试
- org.springframework.test-3.1.0.RELEASE.jar
- com.springsource.org.junit-4.7.0.jar
- WEB
- org.springframework.web-3.1.0.RELEASE.jar
- org.springframework.web.servlet-3.1.0.RELEASE.jar
- JSTL标签
- com.springsource.javax.servlet.jsp.jstl-1.1.2.jar
- com.springsource.org.apache.taglibs.standard-1.1.2.jar
- AOP
- com.springsource.org.aopalliance-1.0.0.jar
- com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar
- 日志
- com.springsource.org.apache.commons.logging-1.1.1.jar
- com.springsource.org.apache.log4j-1.2.15.jar
- 文件上传
- com.springsource.org.apache.commons.fileupload-1.2.0.jar
- com.springsource.org.apache.commons.io-1.4.0.jar
- 2.启动SpringMVC
- web.xml
- <context-param>
- <param-name>contextConfigLocation</param-name>
- <param-value>classpath:beans.xml</param-value>
- </context-param>
- <listener>
- <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
- </listener>
- <servlet>
- <servlet-name>spring</servlet-name>
- <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
- <load-on-startup>1</load-on-startup>
- </servlet>
- <servlet-mapping>
- <servlet-name>spring</servlet-name>
- <url-pattern>*.html</url-pattern>
- </servlet-mapping>
- 3.spring-servlet.xml
- <!-- 配置要扫描的控制器 -->
- <context:annotation-config/>
- <context:component-scan base-package="org.springfuncs.web.controller"/>
- <!-- 配置视图解析器 -->
- <bean 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>
- -------------------------------------------------@Controller详解-------------------------------------------------
- 在一个POJO的上面打上@Controller注解,就表示此类是一个MVC控制器
- 例如:
- @Controller
- public class UserController {
- }
- -------------------------------------------------@RequestMapping详解-------------------------------------------------
- 用于处理映射路径,一本可以用于类上面或方法上面
- value 请求的URL
- method 请求的方法
- params 请求参数 http://localhost:8080/spring1/registerUI.html?id=123&name=tom
- headers 请求头信息
- consumes
- produces
- 例如:
- @Controller
- @RequestMapping("/")
- public class UserController {
- @RequestMapping("/registerUI.html")
- public String registerUI() {
- return "registerUI";
- }
- 或者
- @RequestMapping(value = "/registerUI.html", method = RequestMethod.GET, params = { "id", "name" })
- public String registerUI(Integer id, String name) {
- System.out.println("请求参数:" + id);
- System.out.println("请求参数:" + name);
- return "registerUI";
- }
- //要是有 params = { "id", "name" }则HTTP地址必须提供参数
- //若写成 http://localhost:8080/spring1/registerUI.html报错
- }
- -------------------------------------------------ModelAndView详解-------------------------------------------------
- 用于返回模型与视图
- 用法一:(推荐)
- return new ModelAndView("registerSuccess", "user", user); 视图名、属性名、属性值
- 用法二:(推荐)
- 用Map构造 属性名、属性值
- Map<String, Object> modelMap = new HashMap<String, Object>();
- modelMap.put("user", user);
- modelMap.put("aaa", "one");
- modelMap.put("bbb", "two");
- return new ModelAndView("registerSuccess", modelMap); 视图名、Map对象
- 用法三:
- ModelAndView modelAndView = new ModelAndView();
- modelAndView.addObject("user", user);
- Map<String, Object> modelMap = new HashMap<String, Object>();
- modelMap.put("aaa", "one");
- modelMap.put("bbb", "two");
- modelAndView.addAllObjects(modelMap);
- modelAndView.setViewName("registerSuccess");
- return modelAndView;
- -------------------------------------------------@RequestParam详解-------------------------------------------------
- 用于绑定请求参数
- 例如:
- value 请求参数的名
- required 是否必须
- defaultValue 默认值(支持不好,不推荐使用)
- @RequestMapping(value = "/register.html", method = RequestMethod.POST)
- public ModelAndView register(
- @RequestParam(value = "username", required = true) String username,
- @RequestParam(value = "password", required = true) String password,
- @RequestParam(value = "email", required = false, defaultValue = "unknown") String email,
- @RequestParam(value = "age", required = false) Integer age) {
- User user = new User();
- user.setUsername(username);
- user.setPassword(password);
- user.setEmail(email);
- user.setAge(age);
- userService.register(user);
- return new ModelAndView("registerSuccess", "user", user);
- }
- -------------------------------------------------使用命令表单绑定请求参数 详解-------------------------------------------------
- @RequestMapping(value = "/register.html", method = RequestMethod.POST)
- public ModelAndView register(User user) { //这里的User对象绑定提交的表单
- userService.register(user);
- return new ModelAndView("registerSuccess", "user", user);
- }
- -------------------------------------------------使用 Servlet原生API 详解-------------------------------------------------
- @RequestMapping(value = "/register.html", method = RequestMethod.POST)
- public ModelAndView register(HttpServletRequest request,HttpServletResponse response,HttpSession session) {
- //session
- session.setAttribute("sessionId", "9876");
- String sessionid=(String) session.getAttribute("sessionId");
- //response和cookie
- response.addCookie(new Cookie("c_name", "c_value"));
- Cookie[]cookies=request.getCookies();
- for(Cookie c:cookies){
- if(c.getName().equals("c_name")){
- System.out.println(c.getValue());
- }
- //System.out.println(c.getName()+"-->"+c.getValue());
- }
- //request
- String username = WebUtils.findParameterValue(request, "username");
- 或者
- String username = null;
- Integer age = null;
- try {
- username = ServletRequestUtils.getStringParameter(request, "username");
- age = ServletRequestUtils.getIntParameter(request, "age");
- } catch (ServletRequestBindingException e) {
- e.printStackTrace();
- }
- return null;
- }
- ------------------------------------------------验证 详解-------------------------------------------------
- package org.springfuncs.web.validator;
- import org.springframework.stereotype.Component;
- import org.springframework.validation.Errors;
- import org.springframework.validation.ValidationUtils;
- import org.springframework.validation.Validator;
- import org.springfuncs.domain.User;
- /**
- * 表单验证组件 实现Validator接口
- */
- @Component
- public class UserValidtor implements Validator {
- @Override
- public boolean supports(Class<?> clazz) {
- return User.class.isAssignableFrom(clazz);
- }
- @Override
- public void validate(Object target, Errors errors) {
- ValidationUtils.rejectIfEmptyOrWhitespace(errors, "username", "required.username");
- ValidationUtils.rejectIfEmptyOrWhitespace(errors, "password", "required.password");
- ValidationUtils.rejectIfEmptyOrWhitespace(errors, "email", "required.email");
- ValidationUtils.rejectIfEmptyOrWhitespace(errors, "birthday", "required.birthday");
- ValidationUtils.rejectIfEmptyOrWhitespace(errors, "age", "required.age");
- User user = (User) target;
- if (user.getEmail() != null && !"".equals(user.getEmail())) {
- // Email的正则表达式
- String regex = "^\\s*\\w+(?:\\.{0,1}[\\w-]+)*@[a-zA-Z0-9]+(?:[-.][a-zA-Z0-9]+)*\\.[a-zA-Z]+\\s*$";
- if (!user.getEmail().matches(regex)) {
- errors.rejectValue("email", "invalid.email");
- }
- }
- }
- }
- messages_zh_CN.properties
- required.username=username 是必须的
- required.password=password 是必须的
- required.email=email 是必须的
- required.birthday=birthday 是必须的
- required.age=age 是必须的
- invalid.email=非法的Email地址
- typeMismatch.birthday=非法的 birthday 格式
- typeMismatch.age=非法的 age 格式
- spring-servlet.xml 添加如下配置
- <context:component-scan base-package="org.springfuncs.web.validator"/>
- <!-- 配置资源文件 -->
- <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
- <property name="basename" value="messages"/>
- </bean>
- UserController 编写如下:
- @RequestMapping(value = "/register.html", method = RequestMethod.POST)
- public String register(@ModelAttribute("user") User user, BindingResult result) {
- userValidtor.validate(user, result); // 验证
- if (result.hasErrors()) {
- return "registerUI";
- } else {
- userService.register(user);
- return "registerSuccess";
- }
- }
- ------------------------------------------------Spring表单详解-------------------------------------------------
- package org.springfuncs.web.controller;
- import org.springframework.stereotype.Controller;
- import org.springframework.web.bind.annotation.ModelAttribute;
- import org.springframework.web.bind.annotation.RequestMapping;
- import org.springframework.web.servlet.ModelAndView;
- import org.springfuncs.domain.Form;
- @Controller
- @RequestMapping("/")
- public class FormController {
- @RequestMapping("/formUI.html")
- public String formUI(@ModelAttribute("form") Form form) {
- /** 设置默认值 */
- form.setId(9999);
- form.setName("your name");
- // form.setPassword("your password"); //TODO 密码框怎么设置默认值呢?
- form.setSex("1");
- form.setLove(new String[] { "1", "2", "3" });
- form.setCity("2");
- form.setInfo("write something...");
- return "formUI";
- }
- /** 这是一个很笨的方法,仅仅为了演示而已 */
- @RequestMapping("/doForm.html")
- public ModelAndView doForm(@ModelAttribute("form") Form form) {
- // 处理 sex
- if (form.getSex().equals("1")) {
- form.setSex("男");
- } else {
- form.setSex("女");
- }
- // 处理 city
- if (form.getCity().equals("1")) {
- form.setCity("北京");
- } else if (form.getCity().equals("2")) {
- form.setCity("上海");
- } else if (form.getCity().equals("3")) {
- form.setCity("广州");
- }
- // 处理 love
- String[] love = form.getLove();
- StringBuffer bufLove = new StringBuffer();
- for (int i = 0; love != null && i < love.length; i++) {
- if (love[i].equals("1")) {
- bufLove.append("struts").append(",");
- } else if (love[i].equals("2")) {
- bufLove.append("hibernate").append(",");
- } else if (love[i].equals("3")) {
- bufLove.append("spring").append(",");
- }
- }
- bufLove.deleteCharAt(bufLove.length() - 1);
- form.setLove(new String[] { bufLove.toString() });
- return new ModelAndView("formSuccess", "form", form);
- }
- }
- formUI.jsp
- <%@ taglib uri="http://www.springframework.org/tags/form" prefix="form" %>
- <form:form action="${pageContext.request.contextPath }/doForm.html" method="post" modelAttribute="form">
- <form:errors path="*" cssClass="error"/>
- <form:hidden path="id"/>
- <table>
- <tr>
- <td>姓名:</td>
- <td><form:input path="name"/></td>
- </tr>
- <tr>
- <td>密码:</td>
- <td><form:password path="password"/></td>
- </tr>
- <tr>
- <td>性别:</td>
- <td>
- <form:radiobutton path="sex" value="1"/>男
- <form:radiobutton path="sex" value="2"/>女
- </td>
- </tr>
- <tr>
- <td>爱好:</td>
- <td>
- <form:checkbox path="love" value="1"/>struts
- <form:checkbox path="love" value="2"/>hibernate
- <form:checkbox path="love" value="3"/>spring
- </td>
- </tr>
- <tr>
- <td>城市:</td>
- <td>
- <form:select path="city">
- <form:option value="">--请选择--</form:option>
- <form:option value="1">北京</form:option>
- <form:option value="2">上海</form:option>
- <form:option value="3">广州</form:option>
- </form:select>
- </td>
- </tr>
- <tr>
- <td>简介:</td>
- <td><form:textarea path="info" rows="3" cols="20"/></td>
- </tr>
- <tr>
- <td colspan="2"><input type="submit" value="注册"/></td>
- </tr>
- </table>
- </form:form>
- formSuccess.jsp
- 姓名:${form.name }<br />
- 密码:${form.password }<br />
- 性别:${form.sex }<br />
- 爱好:<c:forEach items="${form.love }" var="love">${love }</c:forEach><br />
- 城市:${form.city }<br />
- 简介:${form.info }<br />
- ------------------------------------------------Spring表单详解 2(推荐)-------------------------------------------------
- ***************************************
- 通常select的值都是从数据库中读取出后,
- 封装成一个对象,
- 然后存入集合中,比如List
- ***************************************
- package org.springfuncs.web.controller;
- import java.util.ArrayList;
- import java.util.List;
- import org.springframework.stereotype.Controller;
- import org.springframework.web.bind.annotation.ModelAttribute;
- import org.springframework.web.bind.annotation.RequestMapping;
- import org.springframework.web.servlet.ModelAndView;
- import org.springfuncs.domain.City;
- import org.springfuncs.domain.Form;
- @Controller
- @RequestMapping("/")
- public class FormController {
- // 重点
- @ModelAttribute("cityList")
- public List<City> populateCity() {
- List<City> cityList = new ArrayList<City>();
- cityList.add(new City(1, "北京"));
- cityList.add(new City(2, "上海"));
- cityList.add(new City(3, "广州"));
- return cityList;
- }
- @RequestMapping("/formUI.html")
- public String formUI(@ModelAttribute("form") Form form) {
- /** 设置默认值 */
- form.setId(9999);
- form.setName("your name");
- // form.setPassword("your password"); //TODO 密码框怎么设置默认值呢?
- form.setSex("1");
- form.setLove(new String[] { "1", "2", "3" });
- // form.setCity(new City(2, "上海")); //不好用啊
- form.setInfo("write something...");
- return "formUI";
- }
- /** 这是一个很笨的方法,仅仅为了演示而已 */
- @RequestMapping("/doForm.html")
- public ModelAndView doForm(@ModelAttribute("form") Form form) {
- // 处理 sex
- if (form.getSex().equals("1")) {
- form.setSex("男");
- } else {
- form.setSex("女");
- }
- // 处理 love
- String[] love = form.getLove();
- StringBuffer bufLove = new StringBuffer();
- for (int i = 0; love != null && i < love.length; i++) {
- if (love[i].equals("1")) {
- bufLove.append("struts").append(",");
- } else if (love[i].equals("2")) {
- bufLove.append("hibernate").append(",");
- } else if (love[i].equals("3")) {
- bufLove.append("spring").append(",");
- }
- }
- bufLove.deleteCharAt(bufLove.length() - 1);
- form.setLove(new String[] { bufLove.toString() });
- return new ModelAndView("formSuccess", "form", form);
- }
- }
- 创建自定义类型
- package org.springfuncs.web.propertyeditor;
- import java.beans.PropertyEditorSupport;
- import org.springfuncs.domain.City;
- import org.springfuncs.service.CityService;
- /**
- * 实现自定义属性类型 继承PropertyEditorSupport类
- */
- public class CityEditor extends PropertyEditorSupport {
- private CityService cityService;
- public CityEditor(CityService cityService) {
- this.cityService = cityService;
- }
- @Override
- public void setAsText(String text) throws IllegalArgumentException {
- if (text != null && !"".equals(text)) {
- Integer id = Integer.parseInt(text);
- City city = cityService.findById(id);
- setValue(city);
- }
- }
- }
- 装配自定义类型
- package org.springfuncs.web.util;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.web.bind.WebDataBinder;
- import org.springframework.web.bind.support.WebBindingInitializer;
- import org.springframework.web.context.request.WebRequest;
- import org.springfuncs.domain.City;
- import org.springfuncs.service.CityService;
- import org.springfuncs.web.propertyeditor.CityEditor;
- /**
- * 绑定自定义类型 实现WebBindingInitializer接口
- */
- public class FormBindingInitializer implements WebBindingInitializer {
- @Autowired
- private CityService cityService;
- @Override
- public void initBinder(WebDataBinder binder, WebRequest request) {
- SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
- dateFormat.setLenient(false);
- binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, true));
- binder.registerCustomEditor(City.class, new CityEditor(cityService));
- }
- }
- 在spring-servlet.xml 中配置
- <!-- 自定义属性类型 -->
- <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
- <property name="webBindingInitializer">
- <bean class="org.springfuncs.web.util.FormBindingInitializer"/>
- </property>
- </bean>
- package org.springfuncs.service.impl;
- import org.springframework.stereotype.Service;
- import org.springfuncs.domain.City;
- import org.springfuncs.service.CityService;
- @Service
- public class CityServiceImpl implements CityService {
- public static final City BEIJING = new City(1, "北京");
- public static final City SHANGHAI = new City(2, "上海");
- public static final City GUANGZHOU = new City(3, "广州");
- @Override
- public City findById(Integer id) {
- switch (id) {
- case 1:
- return BEIJING;
- case 2:
- return SHANGHAI;
- case 3:
- return GUANGZHOU;
- default:
- return null;
- }
- }
- }
- <form:select path="city">
- <form:option value="">--请选择--</form:option>
- <form:options items="${cityList }" itemLabel="name" itemValue="id"/>
- </form:select>
- 另一种
- <form:select path="city">
- <form:option value="">--请选择--</form:option>
- <form:options items="${cityMap }" itemLabel="value" itemValue="key"/>
- </form:select>
- ------------------------------------------------文件上传-------------------------------------------------
- spring-servlet.xml
- <!-- 配置文件上传 -->
- <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
- <property name="defaultEncoding" value="UTF-8"/>
- <property name="maxUploadSize" value="5242880"/> <!-- 5M -->
- <property name="uploadTempDir" value="upload"/> <!-- 要在WebContent下建立一个upload文件夹 -->
- </bean>
- uploadUI.jsp
- <form action="<c:url value="/upload.html"/>" method="post" enctype="multipart/form-data">
- 文件名称:<input type="text" name="name"/><br />
- 上传文件:<input type="file" name="file"/><br />
- <input type="submit" value="上传"/>
- </form>
- UploadController.java
- package org.springfuncs.web.controller;
- import java.io.File;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpSession;
- import org.springframework.stereotype.Controller;
- import org.springframework.web.bind.annotation.RequestMapping;
- import org.springframework.web.bind.annotation.RequestMethod;
- import org.springframework.web.bind.annotation.RequestParam;
- import org.springframework.web.multipart.MultipartFile;
- @Controller
- @RequestMapping("/")
- public class UploadController {
- @RequestMapping("/uploadUI.html")
- public String uploadUI() {
- return "uploadUI";
- }
- @RequestMapping(value = "/upload.html", method = RequestMethod.POST)
- public String upload(HttpServletRequest request, @RequestParam("name") String name, @RequestParam("file") MultipartFile file) throws Exception {
- if (!file.isEmpty()) {
- // System.out.println("文件的MIME类型:" + file.getContentType());
- // System.out.println("表单的类型为file的name属性名:" + file.getName());
- // System.out.println("原始文件名:" + file.getOriginalFilename());
- // System.out.println("文件大小" + file.getSize());
- String path = request.getSession().getServletContext().getRealPath(File.separator) + "upload" + File.separator + file.getOriginalFilename();
- file.transferTo(new File(path));
- // System.out.println(path); //打印上传路径
- // HttpSession session=request.getSession();
- // session.setAttribute("name", name);
- // session.setAttribute("path", path);
- return "redirect:uploadSuccess.html";
- } else {
- return "redirect:uploadFailure.html";
- }
- }
- @RequestMapping("/uploadSuccess.html")
- public String uploadSuccess() {
- return "uploadSuccess";
- }
- @RequestMapping("/uploadFailure.html")
- public String uploadFailure() {
- return "uploadFailure";
- }
- }
- uploadSuccess.jsp
- 上传成功!
- <br />
- 文件名称:<br />
- ${name }
- <br />
- 图片样张:<br />
- <img alt="${name }" src="${path }"/>
- uploadFailure.jsp
- 上传失败!
- ------------------------------------------------异常处理-------------------------------------------------
- spring-servlet.xml
- <!-- 映射异常 -->
- <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
- <property name="defaultErrorView" value="error" />
- <property name="exceptionMappings">
- <props>
- <prop key="java.sql.SQLException">errorDB</prop>
- <prop key="java.lang.RuntimeException">errorRT</prop>
- </props>
- </property>
- <property name="defaultStatusCode" value="500"/>
- <property name="warnLogCategory" value="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"/>
- </bean>
- error.jsp
- 发生了未知的错误,请联系管理员。
- errorRT.jsp
- <%Exception e=(Exception)request.getAttribute("exception");%>
- <h1>Exception:</h1>
- <%e.printStackTrace(new PrintWriter(out));%>
- <hr/>
- <%-- ${exception} --%>
- -------------------------------------------------单元测试-------------------------------------------------
- package junit.test;
- import java.util.Date;
- import org.junit.Test;
- import org.junit.runner.RunWith;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.test.context.ContextConfiguration;
- import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
- import org.springframework.test.context.transaction.TransactionConfiguration;
- import org.springframework.transaction.annotation.Transactional;
- import org.springfuncs.domain.User;
- import org.springfuncs.service.UserService;
- @RunWith(SpringJUnit4ClassRunner.class)
- @ContextConfiguration(locations = { "classpath:beans.xml" })
- @Transactional
- @TransactionConfiguration(transactionManager = "txManager", defaultRollback = true)
- public class SpringTest {
- @Autowired
- private UserService userService;
- @Test
- public void testRegister() {
- User user = new User();
- user.setUsername("monday");
- user.setPassword("1234");
- user.setEmail("monday@qq.com");
- user.setBirthday(new Date());
- user.setAge(23);
- userService.register(user);
- }
- }