SpringMvc 深入讲解 一
简介:本文讲解了请求路径,简单参数传递,post的分类方法,@ModelAttribute的使用,国际化,自定义视图。
1、项目清单
2、顺序源码(后台)
package com.bean;
public class Address {
private String province;
private String city;
public String getProvince() {
return province;
}
public void setProvince(String province) {
this.province = province;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
@Override
public String toString() {
return "Address [province=" + province + ", city=" + city + "]";
}
}
package com.bean;
public class User {
private Integer id;
private String username;
private String password;
private String email;
private int age;
private Address address;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
// @Override
// public String toString() {
// return "User [username=" + username + ", password=" + password
// + ", email=" + email + ", age=" + age + ", address=" + address
// + "]";
// }
@Override
public String toString() {
return "User [id=" + id + ", username=" + username + ", password="
+ password + ", email=" + email + ", age=" + age + "]";
}
public User(String username, String password, String email, int age) {
super();
this.username = username;
this.password = password;
this.email = email;
this.age = age;
}
public User(Integer id, String username, String password, String email,
int age) {
super();
this.id = id;
this.username = username;
this.password = password;
this.email = email;
this.age = age;
}
public User() {}
}
package com.handler;
import java.io.IOException;
import java.io.Writer;
import java.util.Arrays;
import java.util.Date;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.CookieValue;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestHeader;
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.bind.annotation.SessionAttributes;
import org.springframework.web.servlet.ModelAndView;
import com.bean.User;
@SessionAttributes(value={"user"}, types={String.class})
@Controller
@RequestMapping("/springMvc")
public class SpringMvc {
private static String SUCCESS = "success";
/**
* 常用: 使用 method 属性来指定请求方式
*/
@RequestMapping(value = "/testMethod", method = RequestMethod.POST)
public String testMethod() {
System.out.println("testMethod");
return SUCCESS;
}
/**
* 不使用@RequestParam来接受参数
*/
@RequestMapping("/noRequestParam")
public String testRequestMapping(String name) {
System.out.println(name);
System.out.println("testRequestMapping");
return SUCCESS;
}
/**
* @RequestParam 来映射请求参数. value 值即请求参数的参数名 required 该参数是否必须. 默认为 true
* defaultValue 请求参数的默认值
*/
@RequestMapping(value = "/testRequestParam")
public String testRequestParam(
@RequestParam(value = "username") String un,
@RequestParam(value = "age", required = false, defaultValue = "0") int age) {
System.out.println("testRequestParam, username: " + un + ", age: "
+ age);
return SUCCESS;
}
/**
* 了解: 映射请求头信息 用法同 @RequestParam ---------------------------------------------------------直接请求(将headers中的值传入当成参数)
*/
@RequestMapping("/testRequestHeader")
public String testRequestHeader(@RequestHeader(value = "Accept-Language") String al) {
System.out.println("testRequestHeader, Accept-Language: " + al);
return SUCCESS;
}
/**
* 了解:
*
* @CookieValue: 映射一个 Cookie 值. 属性同 @RequestParam
*/
@RequestMapping("/testCookieValue")
public String testCookieValue(@CookieValue("JSESSIONID") String sessionId) {
System.out.println("testCookieValue: sessionId: " + sessionId);
return SUCCESS;
}
/**
* 了解: 可以使用 params 和 headers 来更加精确的映射请求. params 和 headers 支持简单的表达式.------------确认请求(只有在headers中满足条件才会请求)
*/
@RequestMapping(value = "/testParamsAndHeaders", params = { "username",
"age!=10" }, headers = { "Accept-Language=zh-CN" })
public String testParamsAndHeaders() {
System.out.println("testParamsAndHeaders");
return SUCCESS;
}
/**
* 通配符使用
*/
@RequestMapping("/testAntPath/*/abc")
public String testAntPath() {
System.out.println("testAntPath");
return SUCCESS;
}
/**
* @PathVariable 可以来映射 URL 中的占位符到目标方法的参数中.
* @param id
*/
@RequestMapping("/testPathVariable/{id}")
public String testPathVariable(@PathVariable("id") Integer id) {
System.out.println("testPathVariable: " + id);
return SUCCESS;
}
/**
* Rest 风格的 URL. 以 CRUD 为例: 新增: /order POST 修改: /order/1 PUT update?id=1 获取:
* /order/1 GET get?id=1 删除: /order/1 DELETE delete?id=1
*
* 如何发送 PUT 请求和 DELETE 请求呢 ?
* 1. 需要配置 HiddenHttpMethodFilter
* 2. 需要发送 POST 请求
* 3. 需要在发送 POST 请求时携带一个 name="_method" 的隐藏域, 值为 DELETE 或 PUT
* 在 SpringMVC 的目标方法中如何得到 id 呢? 使用 @PathVariable 注解
*
*/
@RequestMapping(value = "/testRest", method = RequestMethod.POST)
public String testRest() {
System.out.println("testRest POST");
return SUCCESS;
}
@RequestMapping(value = "/testRest/{id}", method = RequestMethod.DELETE)
public String testRestDelete(@PathVariable Integer id) {
System.out.println("testRest Delete: " + id);
return SUCCESS;
}
@RequestMapping(value = "/testRest/{id}", method = RequestMethod.PUT)
public String testRestPut(@PathVariable Integer id) {
System.out.println("testRest Put: " + id);
return SUCCESS;
}
/**
* Spring MVC 会按请求参数名和 POJO 属性名进行自动匹配, 自动为该对象填充属性值。支持级联属性。
* 如:dept.deptId、dept.address.tel 等
*/
@RequestMapping("/testPojo")
public String testPojo(com.bean.User user) {
System.out.println("testPojo: " + user);
return SUCCESS;
}
/**
* 可以使用 Serlvet 原生的 API 作为目标方法的参数 具体支持以下类型
*
* HttpServletRequest
* HttpServletResponse
* HttpSession
* java.security.Principal
* Locale InputStream
* OutputStream
* Reader
* Writer
* @throws IOException
*/
@RequestMapping("/testServletAPI")
public void testServletAPI(HttpServletRequest request,HttpServletResponse response, Writer out) throws IOException {
System.out.println("testServletAPI, " + request + ", " + response);
out.write("hello springmvc");
// return SUCCESS;
}
/**
* 目标方法的返回值可以是 ModelAndView 类型。
* 其中可以包含视图和模型信息
* SpringMVC 会把 ModelAndView 的 model 中数据放入到 request 域对象中.
* @return
*/
@RequestMapping("/testModelAndView")
public ModelAndView testModelAndView(){
String viewName = SUCCESS;
ModelAndView modelAndView = new ModelAndView(viewName);
//添加模型数据到 ModelAndView 中.
modelAndView.addObject("time", new Date());
return modelAndView;
}
/**
* 目标方法可以添加 Map 类型(实际上也可以是 Model 类型或 ModelMap 类型)的参数.
* 其实这三类都是属于Modle类型,最后都是要将其中的键值放入request中
*/
@RequestMapping("/testMap")
public String testMap(Map<String, Object> map){
System.out.println(map.getClass().getName());
map.put("names", Arrays.asList("Tom", "Jerry", "Mike"));
return SUCCESS;
}
/**
* @SessionAttributes 除了可以通过属性名指定需要放到会话中的属性外(实际上使用的是 value 属性值),
* 还可以通过模型属性的对象类型指定哪些模型属性需要放到会话中(实际上使用的是 types 属性值)
* 注意: 该注解只能放在类的上面. 而不能修饰放方法.
*/
@RequestMapping("/testSessionAttributes")
public String testSessionAttributes(Map<String, Object> map){
User user = new User("Tom", "123456", "tom@atguigu.com", 15);
map.put("user", user);
map.put("school", "atguigu");
return SUCCESS;
}
/**
* @ModelAttribute 作用在方法体上,能在请求运行任何方法之前运行,多使用在updata数据库的时候,现将其取出来,有不修改的字段就封装好,不修改了.
* 详解:1.先运行了getUser方法,就会在request和@ModelAttribute("user")的中存入一个user,在页面上传过来一个user的时候呢,就会进行融合;
*/
@RequestMapping("/testModelAttribute")
public String testModelAttribute(com.bean.User user){
System.out.println("修改: " + user);
return SUCCESS;
}
@ModelAttribute
public void getUser(@RequestParam(value="id",required=false) Integer id,
Map<String, Object> map){
System.out.println("modelAttribute method");
if(id != null){
//模拟从数据库中获取对象
User user = new User(1, "Tom", "123456", "tom@atguigu.com", 12);
System.out.println("从数据库中获取一个对象: " + user);
map.put("user", user);
}
}
/**
* @ModelAttribute("stack")可以使用返回值,那么这个key=stack的value将会出现在request中
* map model 等都会将键值对村放入request作用中
* @ModelAttribute("stack") 作用在参数内,会取到值,并赋值给参数
* 资料 http://www.360doc.com/content/12/1007/23/7471983_240136215.shtml
*/
@ModelAttribute("stack")
public String getUser(Map<String, Object> map,Model model){
System.out.println("modelAttribute method");
//模拟从数据库中获取对象
User user = new User(1, "Tom", "123456", "tom@atguigu.com", 12);
map.put("user", user);
model.addAttribute("modelTest", "modelTest");
return "user has bean create";
}
@RequestMapping("/ModelAttributeReturn")
public String ModelAttributeReturn(@ModelAttribute("stack")String un){
System.out.println("当前状态"+un);
return SUCCESS;
}
/**
* 跳转
*/
@RequestMapping("/testRedirect")
public String testRedirect(){
System.out.println("testRedirect");
return "redirect:/index.jsp";
}
/**
* 自定义视图 1.配置BeanNameViewResolver解析自定义视图
* 2.类名首字母小写
* @return
*/
@RequestMapping("/testView")
public String testView(){
System.out.println("testView");
return "myselfView";
}
}
package com.myself.view;
import java.util.Date;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.View;
@Component("myselfView")
public class HelloView implements View{
public String getContentType() {
System.out.println("返回的页面类型");
return "text/html";
}
public void render(Map<String, ?> arg0, HttpServletRequest arg1,
HttpServletResponse arg2) throws Exception {
arg2.getWriter().print("hello view, time: " + new Date());
}
}
3、dispatcherServlet-servlet.xml 配置
<?xml version="1.0" encoding="UTF-8"?>
<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/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd">
<!-- 配置自定扫描的包 -->
<context:component-scan base-package="com"></context:component-scan>
<!-- 配置视图解析器: 如何把 handler 方法返回值解析为实际的物理视图 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
<!-- 配置视图 BeanNameViewResolver 解析器: 使用视图的名字来解析视图 -->
<!-- 通过 order 属性来定义视图解析器的优先级, order 值越小优先级越高 -->
<bean class="org.springframework.web.servlet.view.BeanNameViewResolver">
<property name="order" value="100"></property>
</bean>
<!-- 配置国际化资源文件 -->
<bean id="messageSource"
class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basename" value="i18n"></property>
</bean>
<!-- 配置直接转发的页面 -->
<!-- 可以直接相应转发的页面, 而无需再经过 Handler 的方法.
web-inf下success页面无法直接访问,通过这种办法可解决
-->
<mvc:view-controller path="/success" view-name="success"/>
<!--处理静态资源的方式有两种,第二种我能行得通--> <pre class="html" name="code"> <mvc:default-servlet-handler />
<mvc:resources mapping="/js/**" location="/js/" />
<!--或者在web.xml中写入下面的
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.html</url-pattern>
<url-pattern>*.js</url-pattern>
<url-pattern>*.png</url-pattern>
<url-pattern>*.jpg</url-pattern>
<url-pattern>*.css</url-pattern>
<url-pattern>*.json</url-pattern>
</servlet-mapping>-->
<!-- 在实际开发中通常都需配置 mvc:annotation-driven 标签 如果不配置下面的内容,上面的内容配置了以后呢,handler中的方法都不能使用了,必须配置下面 --><mvc:annotation-driven></mvc:annotation-driven></beans>
4、web.xml 配置
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<!--
配置 org.springframework.web.filter.HiddenHttpMethodFilter: 可以把 POST 请求转为 DELETE 或 POST 请求
-->
<filter>
<filter-name>HiddenHttpMethodFilter</filter-name>
<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>HiddenHttpMethodFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- 配置 DispatcherServlet -->
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
5、页面源码
① index.jsp
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>My JSP 'index.jsp' starting page</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->
</head>
<body>
<form action="springMvc/testMethod" method="POST">
<input type="submit" value="testMethod"/>
</form>
<br/>
<a href="springMvc/noRequestParam?name=atguigu">noRequestParam</a>
<br>
<a href="springMvc/testParamsAndHeaders?username=atguigu&age=11">Test ParamsAndHeaders</a>
<br>
<a href="springMvc/testAntPath/mnxyz/abc">Test AntPath</a>
<br>
<a href="springMvc/testPathVariable/1">Test PathVariable</a>
<br>
<form action="springMvc/testRest" method="post">
<input type="submit" value="TestRest POST"/>
</form>
<br>
<form action="springMvc/testRest/1" method="post">
<input type="hidden" name="_method" value="DELETE"/>
<input type="submit" value="TestRest DELETE"/>
</form>
<br>
<form action="springMvc/testRest/1" method="post">
<input type="hidden" name="_method" value="PUT"/>
<input type="submit" value="TestRest PUT"/>
</form>
<br>
<a href="springMvc/testCookieValue">CookieValue</a>
<br>
<a href="springMvc/testRequestHeader">RequestHeader</a>
<br>
<a href="springMvc/testRequestParam?username=atguigu&age=11">RequestParam</a>
<br><br>
<form action="springMvc/testPojo" method="post">
username: <input type="text" name="username"/>
<br>
password: <input type="password" name="password"/>
<br>
email: <input type="text" name="email"/>
<br>
age: <input type="text" name="age"/>
<br>
city: <input type="text" name="address.city"/>
<br>
province: <input type="text" name="address.province"/>
<br>
<input type="submit" value="Submit"/>
</form>
<br>
<a href="springMvc/testServletAPI">ServletAPI</a>
<br>
<a href="springMvc/testModelAndView">ModelAndView</a>
<br>
<a href="springMvc/testMap">Map</a>
<br>
<a href="springMvc/testSessionAttributes">SessionAttributes</a>
<br>
<!--
模拟修改操作
1. 原始数据为: 1, Tom, 123456,tom@atguigu.com,12
2. 密码不能被修改.
3. 表单回显, 模拟操作直接在表单填写对应的属性值
-->
<form action="springMvc/testModelAttribute" method="Post">
<input type="hidden" name="id" value="1"/>
username: <input type="text" name="username" value="Jack"/>
<br>
email: <input type="text" name="email" value="tom@atguigu.com"/>
<br>
age: <input type="text" name="age" value="12"/>
<br>
<input type="submit" value="Submit"/>
</form>
<br>
<a href="springMvc/ModelAttributeReturn">ModelAttributeReturn</a>
<br>
<a href="springMvc/testRedirect">TRedirect</a>
<br>
<a href="springMvc/testView">自定义视图</a>
<br><br>
</body>
</html>
②success.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<h4>Sucess Page</h4>
time: ${requestScope.time }
<br>
names: ${requestScope.names }
<br>
request user: ${requestScope.user }
<br>
request modelAttribut: ${requestScope.stack }
<br>
session user: ${sessionScope.user }
<br>
request school: ${requestScope.school }
<br>
session school: ${sessionScope.school }
<br>
abc user: ${requestScope.abc }
<br>
mnxyz user: ${requestScope.mnxyz }
<br>
name : ${requestScope.name }
name : ${sessionScope.name }<br>
<fmt:message key="i18n.username"></fmt:message>
<br>
<fmt:message key="i18n.password"></fmt:message>
<br>
</body>
</html>