spring MVC 学习
首先来个hello world例子。
我们在index.jsp中弄一个超链接
1 2
| <a href="helloworld">helloworld</a>
|
新建个handler,用来处理请求的url,这里我们使用注解的方式来映射url。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| @Controller public class HelloWorld {
@RequestMapping("/helloworld") private String hello() {
System.out.println("hellow world...................");
return "success"; } }
|
在spingmvc.xml中我们要配置
1 2 3 4 5 6 7 8 9 10
| <context:component-scan base-package="com.mamh.springmvc.demo.handlers"/>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/views/"/> <property name="suffix" value=".jsp"/> </bean>
|
web.xml文件的配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
|
<web-app>
<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> <load-on-startup>1</load-on-startup> </servlet>
<servlet-mapping> <servlet-name>dispatcherServlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>
</web-app>
|
整个工程使用maven来管理,其中pom文件
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 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201
| <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>mamh</groupId> <artifactId>spring</artifactId> <packaging>war</packaging> <version>1.0-SNAPSHOT</version> <name>spring Maven Webapp</name> <url>http://maven.apache.org</url>
<properties> <spring.version>5.0.4.RELEASE</spring.version> </properties>
<dependencies>
<dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.7.21</version> </dependency>
<dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> <scope>provided</scope> </dependency> <dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>jsp-api</artifactId> <version>2.2</version> </dependency>
<dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency>
<dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.35</version> </dependency>
<dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>1.3.1</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency>
<dependency> <groupId>com.mchange</groupId> <artifactId>c3p0</artifactId> <version>0.9.5.2</version> </dependency>
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-orm</artifactId> <version>${spring.version}</version> </dependency>
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.8.13</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjrt</artifactId> <version>1.8.13</version> </dependency>
<dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>5.2.15.Final</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-c3p0</artifactId> <version>5.2.15.Final</version> </dependency>
<dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-core</artifactId> <version>2.9.1</version> </dependency> <dependency> <groupId>commons-dbutils</groupId> <artifactId>commons-dbutils</artifactId> <version>1.7</version> </dependency>
<dependency> <groupId>com.oracle</groupId> <artifactId>ojdbc8</artifactId> <version>12.2.0.1.0</version> </dependency>
<dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-ehcache</artifactId> <version>5.2.15.Final</version> </dependency>
<dependency> <groupId>org.apache.struts</groupId> <artifactId>struts2-core</artifactId> <version>2.5.16</version> </dependency> <dependency> <groupId>org.apache.struts</groupId> <artifactId>struts2-spring-plugin</artifactId> <version>2.5</version> </dependency>
</dependencies>
<build> <finalName>spring</finalName>
<resources> <resource> <directory>${basedir}/src/main/java</directory> <includes> <include>**/*.properties</include> <include>**/*.xml</include> </includes> </resource> <resource> <directory>${basedir}/src/main/resources</directory> </resource> </resources> <plugins> <plugin> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-maven-plugin</artifactId> <version>9.3.10.v20160621</version> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.6</source> <target>1.6</target> </configuration> </plugin> </plugins> </build> </project>
|
@RequestMapping(“/helloworld”)详解
这个注解也能加到class上。如果同时class上和method都加的有,那url的映射是2个加到一起的。
类上没有就是相对于web应用的根目录的。方法出的相对于类定义处的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| @RequestMapping("/class") @Controller public class HelloWorld {
@RequestMapping("/helloworld") private String hello() {
System.out.println("hellow world...................");
return "success"; } }
|
这样类上加了@RequestMapping(“/class”) 之后 的url就是这样http://localhost:8080/class/helloworld来访问了。
先前的没有加的是http://localhost:8080/helloworld来访问了
@RequestMapping()请求方式,value,method属性
@RequestMapping 的 value、method、params 及 heads
分别表示请求 URL、请求方法、请求参数及请求头的映射条
件,他们之间是与的关系,联合使用多个条件可让请求映射
更加精确化。
常用的method的两个值:
RequestMethod.POST ,RequestMethod.GET
1 2 3 4 5 6 7 8 9 10
| @RequestMapping(value = "/testMethod", method = RequestMethod.POST) private String testMethod() { System.out.println("hellow world....testMethod...............");
return "success";
}
|
@RequestMapping()请求参数,请求头
params 和 headers支持简单的表达式:
1 2 3 4
| param1: 表示请求必须包含名为 param1 的请求参数 – !param1: 表示请求不能包含名为 param1 的请求参数 – param1 != value1: 表示请求包含名为 param1 的请求参数,但其– 值不能为 value1 {“param1=value1”, “param2”}: 请求必须包含名为 param1 和param2 –的两个请求参数,且 param1 参数的值必须为 value1
|
1 2 3 4 5 6 7 8 9 10 11
|
@RequestMapping(value = "/testParams", params = {"username", "age!=10"}) private String testParams() { System.out.println("hellow world....testParams...............");
return "success";
}
|
http://localhost:8080/testParams?username=mamh&age=101这个就能访问,age改为10就不行了。
1 2 3 4 5 6 7 8 9
| @RequestMapping(value = "/testParams", params = {"username", "age!=10"}, headers = {"Accept-Language=zh-CN,en-US;q=0.7,en;q=0.3"}) private String testParams() { System.out.println("hellow world....testParams..............."); return "success"; }
|
@RequestMapping()支持 ant风格统配匹配
Ant 风格资源地址支持 3 种匹配符:
1 2 3
| ?:匹配文件名中的一个字符 – *:匹配文件名中的任意字符 – **:** 匹配多层路径
|
@RequestMapping 还支持 Ant 风格的 URL :
1 2 3 4 5 6 7 8
| /user/*/createUser: 匹配 /user/aaa/createUser、/user/bbb/createUser 等 URL
/user/**/createUser: 匹配 /user/createUser、/user/aaa/bbb/createUser 等 URL
/user/createUser??: 匹配 /user/createUseraa、/user/createUserbb 等 URL
|
1 2 3 4 5 6 7 8 9
|
@RequestMapping(value = "/testPath/*/abc") private String testPath() { System.out.println("hellow world....testPath..............."); return "success"; }
|
http://localhost:8080/testPath/a/abc可以。
http://localhost:8080/testPath/b/abc也可以匹配
@PathVariable 映射 URL 绑定的占位符
1 2 3 4 5 6 7 8
| @RequestMapping(value = "/testPathVariable{id}") private String testPathVariable(@PathVariable(value = "id") int id) { System.out.println("hellow world....PathVariable............... id = " + id); return "success"; }
|
访问这样http://localhost:8080/testPathVariable2323访问,会得到参数id是2323.
通过 @PathVariable 可以将 URL 中占位符参数绑定到控制器处理方法的入参中:URL 中的 {xxx} 占位符可以通过
@PathVariable(“xxx”) 绑定到操作方法的入参中。
REST:即 Representational State Transfer。(资源)表现层状态转化。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| REST:即 Representational State Transfer。(资源)表现层状态转化。是目前 • 最流行的一种互联网软件架构。它结构清晰、符合标准、易于理解、扩展方便, 所以正得到越来越多网站的采用 资源(Resources):网络上的一个实体,或者说是网络上的一个具体信息。它 • 可以是一段文本、一张图片、一首歌曲、一种服务,总之就是一个具体的存在。 可以用一个URI(统一资源定位符)指向它,每种资源对应一个特定的 URI 。要 获取这个资源,访问它的URI就可以,因此 URI 即为每一个资源的独一无二的识 别符。 表现层(Representation):把资源具体呈现出来的形式,叫做它的表现层 • (Representation)。比如,文本可以用 txt 格式表现,也可以用 HTML 格 式、XML 格式、JSON 格式表现,甚至可以采用二进制格式。 状态转化(State Transfer):每• 发出一个请求,就代表了客户端和服务器的一 次交互过程。HTTP协议,是一个无状态协议,即所有的状态都保存在服务器 端。因此,如果客户端想要操作服务器,必须通过某种手段,让服务器端发生“ 状态转化”(State Transfer)。而这种转化是建立在表现层之上的,所以就是 “ 表现层状态转化”。具体说,就是 HTTP 协议里面,四个表示操作方式的动 词:GET、POST、PUT、DELETE。它们分别对应四种基本操作:GET 用来获 取资源,POST 用来新建资源,PUT 用来更新资源,DELETE 用来删除资源。
|
form表单是不支持delete,和put的,不过我们可以添加一个隐藏域使用post方式转换到delete或put
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
|
<form action="springmvc/testREST/1" method="post"> <input type="hidden" name="_method" value="PUT"/> <input type="submit" value="TestRest PUT"/> </form> <br><br>
<form action="springmvc/testREST/1" method="post"> <input type="hidden" name="_method" value="DELETE"/> <input type="submit" value="TestRest DELETE"/> </form> <br><br>
<form action="springmvc/testREST" method="post"> <input type="submit" value="TestRest POST"/> </form> <br><br>
<a href="springmvc/testREST/1">Test Rest Get</a> <br><br>
|
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
|
@RequestMapping(value = "/testREST/{id}", method = RequestMethod.GET) private String testGET(@PathVariable(value = "id") int id) { System.out.println("testREST GET : " + id); return "success"; }
@RequestMapping(value = "/testREST/{id}", method = RequestMethod.PUT) private String testPUT(@PathVariable(value = "id") int id) { System.out.println("testREST PUT : " + id); return "success"; }
@RequestMapping(value = "/testREST/{id}", method = RequestMethod.DELETE) private String testDELETE(@PathVariable(value = "id") int id) { System.out.println("testREST DELETE : " + id); return "success"; }
@RequestMapping(value = "/testREST", method = RequestMethod.POST) private String testPOST() { System.out.println("testREST POST : "); return "success"; }
|
这里使用HiddenHttpMethodFilter过滤器来把post请求转换为delete或put请求,
1 2 3 4 5 6 7 8 9 10 11
|
<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>
|
从java中的代码我们可以看到 需要 在post请求中传过滤的参数是DEFAULT_METHOD_PARAM = “_method”
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 39
| public class HiddenHttpMethodFilter extends OncePerRequestFilter { public static final String DEFAULT_METHOD_PARAM = "_method"; private String methodParam = "_method";
public HiddenHttpMethodFilter() { }
public void setMethodParam(String methodParam) { Assert.hasText(methodParam, "'methodParam' must not be empty"); this.methodParam = methodParam; }
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { HttpServletRequest requestToUse = request; if ("POST".equals(request.getMethod()) && request.getAttribute("javax.servlet.error.exception") == null) { String paramValue = request.getParameter(this.methodParam); if (StringUtils.hasLength(paramValue)) { requestToUse = new HiddenHttpMethodFilter.HttpMethodRequestWrapper(request, paramValue); } }
filterChain.doFilter((ServletRequest)requestToUse, response); }
private static class HttpMethodRequestWrapper extends HttpServletRequestWrapper { private final String method;
public HttpMethodRequestWrapper(HttpServletRequest request, String method) { super(request); this.method = method.toUpperCase(Locale.ENGLISH); }
public String getMethod() { return this.method; } } }
|
@RequestParam 映射请求参数
value值就是请求参数值
required决定这个请求参数是否是必须的
defaultValue可以给这个请求参数设置个默认值
1 2 3 4 5 6 7 8 9
| @RequestMapping("/testRequestParam") private String testRequestParam(@RequestParam(value = "username") String username, @RequestParam(value = "password") String password) { System.out.println("hellow world....testRequestParam..............username = " + username + " password = " + password);
return "success"; }
|
http://localhost:8080/springmvc/testRequestParam?username=123&password=abc
访问的时候如果没带请求参数是会报错的。 可以加上required = false来设置是否需要,还可以设置个defaultValue。
@RequestHeader 绑定请求报头的属性值
1 2 3 4 5
| @RequestMapping("/testRequestHeader") private String testRequestHeader(@RequestHeader(value = "Accept-Language") String al) { System.out.println("hellow world.....testRequestHeader............\"Accept-Language\" = " + al); return "success"; }
|
http://localhost:8080/springmvc/testRequestHeader
@CookieValue 绑定请求中的 Cookie 值
1 2 3 4 5 6 7
| @RequestMapping("/testCookieValue") private String testCookieValue(@CookieValue(value = "JSESSIONID") String c) { System.out.println("hellow world.....testCookieValue....CookieValue = " + c); return "success"; }
|
使用 POJO 对象绑定请求参数值
Spring MVC 会按• 请求参数名和 POJO 属性名进行自动匹配,自动为该对象填充属性值。支持级联属性。
如:dept.deptId、dept.address.tel 等
1 2 3 4 5 6
| @RequestMapping("/testPOJO") private String testPOJO(User user) { System.out.println("hellow world.....testPOJO..." + user); return "success"; }
|
使用 Servlet API 原生API
1 2 3 4 5 6 7 8 9 10 11
| HttpServletRequest HttpServletResponse HttpSession java.security.Principal Locale InputStream OutputStream Reader Writer
|
@SessionAttributes
若希望在多个请求之间共用某个模型属性数据,则可以在 控制器类上标注一个 @SessionAttributes, Spring MVC 将在模型中对应的属性暂存到 HttpSession 中。
@SessionAttributes 除了可以通过属性名指定需要放到会话中的属性外,还可以通过模型属性的对象类型指定哪些模型属性需要放到会话中
1 2 3 4 5 6 7 8 9
| @SessionAttributes(types=User.class) 会将隐含模型中所有类型为 User.class 的属性添加到会话中。
@SessionAttributes(value={“user1”, “user2”})
@SessionAttributes(types={User.class, Dept.class})
@SessionAttributes(value={“user1”, “user2”}, types={Dept.class})
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
|
@RequestMapping("/testSessionAttributes") public String testSessionAttributes(Map<String, Object> map) { User user = new User(); user.setAge(123); user.setUsername("Tom"); user.setEmail("123@mm.com"); user.setPassword("123456"); map.put("user", user); map.put("string1", "xxxxxxxxxxxxxxxxxxx this is a stirng ...."); map.put("int1", 123321);
return "success"; }
|
@ModelAttribute
在方法定义上使用 @ModelAttribute 注解:Spring MVC 在调用目标处理方法前,会先逐个调用在方法级上标注了@ModelAttribute 的方法。
在方法的入参前使用@ModelAttribute 注解可以从隐含对象中获取隐含的模型数据中获取对象,再将请求参数绑定到对象中,再传入入参.将方法入参对象添加到模型中.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| @ModelAttribute public void getUser(@RequestParam(value = "id", required = false) Integer id, Map<String, Object> map) { if (id != null) { User user = new User(1, "tom", "123456", "tom@123.com", 12, null);
System.out.println("从数据库获取一个对象" + user); map.put("user", user); } }
@RequestMapping("/testModelAttribute") public String testModelAttribute(User user) { System.out.println("testModelAttribute=== " + user);
return "success"; }
|
@ModelAttribute注解,可以修身目标方法POJO入参。 当那个键不是类名第一个字母小写的时候,我们可以用
@ModelAttribute注解修饰入参,里面value就是自定义的那个键名 。例如下面我们把键名改为了“abc”,
在testModelAttribute(User user)方法中如果不使用注解那个user就是一个新建的,而不是从map中获得的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| @ModelAttribute public void getUser(@RequestParam(value = "id", required = false) Integer id, Map<String, Object> map) { if (id != null) { User user = new User(1, "tom", "123456", "tom@123.com", 12, null);
System.out.println("从数据库获取一个对象" + user); map.put("abc", user); } }
@RequestMapping("/testModelAttribute") public String testModelAttribute(@ModelAttribute(value = "abc") User user) { System.out.println("testModelAttribute=== " + user);
return "success"; }
|
国际化
使用i18n国际化的时候,需要建2个properties文件
new file: src/main/resources/i18n_en_US.properties
new file: src/main/resources/i18n_zh_CN.properties
1 2 3 4 5 6
| i18n.username=username i18n.passowrd=password
i18n.username=\u7528\u6237\u540D i18n.passowrd=\u7528\u6237\u540D
|
properties文件中要使用编码后的,也就是中文要变成\u 开头这样的。
1 2 3 4 5
| <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource"> <property name="basename" value="i18n"/> </bean>
|
view-controller
1 2 3 4
|
<mvc:view-controller path="/success" view-name="success"/>
|
可以直接访问 http://localhost:8080/success了。
这个时候那个 @RequestMapping() 配置的那个返回的view就会报404错误了。这个时候可以加上
annotation-driven
1 2 3
| <mvc:annotation-driven/>
|
自定义View
1 2 3 4 5 6 7
| <context:component-scan base-package="com.mamh.springmvc.demo.views"/>
<bean id="beanNameViewResolver" class="org.springframework.web.servlet.view.BeanNameViewResolver"> <property name="order" value="100"/> </bean>
|
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
| package com.mamh.springmvc.demo.views;
import org.springframework.lang.Nullable; import org.springframework.stereotype.Component; import org.springframework.web.servlet.View;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.util.Date; import java.util.Map;
@Component public class HelloView implements View { @Override public void render(@Nullable Map<String, ?> model, HttpServletRequest request, HttpServletResponse response) throws Exception { response.getWriter().println("hello view, time: " + new Date());
}
@Nullable @Override public String getContentType() { return "text/html"; } }
|
CRUD操作
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
| @Controller public class EmployeeHandler {
@Autowired private EmployeeDao employeeDao;
@Autowired private DepartmentDao departmentDao;
@RequestMapping(value = "/emp", method = RequestMethod.GET) public String input( Map<String, Object> map) { System.out.println("input.........."); map.put("departments", departmentDao.getDepartments()); map.put("employee",new Employee());
return "input"; }
@RequestMapping("/emps") public String list(Map<String, Object> map) {
map.put("employees", employeeDao.getAll());
return "list"; }
}
|
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
|
<c:if test="${empty requestScope.employees}"> 没有任何信息 </c:if> <c:if test="${!empty requestScope.employees}"> <table border="1" cellpadding="10" cellspacing="0"> <tr> <th>ID</th> <th>LastName</th> <th>Email</th> <th>Gender</th> <th>Department</th> <th>Edit</th> <th>Delete</th> </tr> <c:forEach items="${requestScope.employees}" var="emp"> <tr> <td>${emp.id}</td> <td>${emp.lastName}</td> <td>${emp.email}</td> <td>${emp.gender == 0? 'Female': 'Male'}</td> <td>${emp.department.departmentName}</td> <td><a href="">Edit</a></td> <td><a href="">Delete</a></td> </tr> </c:forEach>
</table> </c:if>
<br/> <a href="/emp">Add new Employee.........</a>
|
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
| <!-- 可以更快速的开发出表单页面,方便表单值回显
java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'command' available as request attribute
可以通过 modelAttribute 属性指定绑定的模型属性, 若没有指定该属性,则默认从 request 域对象中读取 command 的表单 bean,如果该属性值也不存在,则会 发生错误。
-->
<form:form action="/emp" method="POST" modelAttribute="employee"> LastName: <form:input path="lastName"/> <br/>
Email: <form:input path="email"/> <br/>
<% Map<String, String> genders = new HashMap(); genders.put("1", "Male"); genders.put("0", "Female"); request.setAttribute("genders", genders); %> Gender: <form:radiobuttons path="gender" items="${genders}"/> <br/>
Department: <form:select path="department" items="${departments}" itemLabel="departmentName" itemValue="id"/> <br/>
<input type="submit" value="submit"/> </form:form>
|
注意在使用<form:form>
标签的时候,modelAttribute=”employee”设置的值要和放到map中的键一致。
1 2 3 4 5 6 7 8 9 10 11 12 13
|
删除操作 ```java
@RequestMapping(value = "/emp/{id}", method = RequestMethod.DELETE) public String delete(@PathVariable(value = "id") Integer id) { System.out.println("delete.........." + id); employeeDao.delete(id); return "redirect:/emps"; }
|
注意spingmvc对静态资源的过滤,可以加上
1 2 3
| <mvc:default-servlet-handler/>
|
mvc:annotation-driven
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| RequestMappingHandlerAdapter,ExceptionHandlerExceptionResolver。 支持ConversionService实例对表单参数进行类型转换。 支持使用@NumberFormat、@DateTimeFormat 注解完成数据类型的格式化。 支持使用 @Valid 注解对 JavaBean 实例进行 JSR 303 验证。 支持使用 @RequestBody 和 @ResponseBody 注解。
@InitBinder
由 @InitBinder 标识的方法• ,可以对 WebDataBinder 对 象进行初始化。WebDataBinder 是 DataBinder 的子类,用 于完成由表单字段到 JavaBean 属性的绑定
@InitBinder方法不能有返回值,它必须声明为void 。
@InitBinder方法的参数通常是是 WebDataBinder
```java
@InitBinder public void initBinder(WebDataBinder webDataBinder){ webDataBinder.setDisallowedFields("lastName"); }
|
JSR 303验证标准
@ResponseBody
这个注意版本问题,有时候版本不对会报错的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.9.5</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-core</artifactId> <version>2.9.5</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-annotations</artifactId> <version>2.9.5</version> </dependency>
|
1 2 3 4 5 6 7 8 9
| @ResponseBody @RequestMapping("/testJson") public Collection<Employee> testJson( ) { System.out.println("testJson......." );
return employeeDao.getAll(); }
|
使用@ResponseBody,返回值可以直接显示到页面上,使用@RequestBody可以直接得到请求内容。
1 2 3 4 5 6 7 8 9
| @ResponseBody @RequestMapping("/testHttpMessageConverter") public String testHttpMessageConverter(@RequestBody String body) { System.out.println("testHttpMessageConverter.......\n" + body + "\n\n");
return "hello world! " + new Date(); }
|
文件的上传
springmvc.xml中需要配置个 multipartResolver。 这个ID必须是这个名称,如果不是会报错的。
1 2 3 4 5
| <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <property name="defaultEncoding" value="utf-8"/> <property name="maxUploadSize" value="2000000"/> <property name="maxInMemorySize" value="40960"/> </bean>
|
1 2 3 4 5 6 7 8 9 10 11 12
| @RequestMapping("/testFileUpload") public String testFileUpload(@RequestParam(value = "desc", required = false) String desc, @RequestParam(value = "file",required = false) MultipartFile file) { System.out.println("testFileUpload.......\n"); System.out.println(desc); System.out.println(file.getOriginalFilename()); System.out.println(file.getSize());
return "success"; }
|
html中的表单需要设置 enctype=”multipart/form-data”。
1 2 3 4 5 6 7
| <form action="testFileUpload" method="POST" enctype="multipart/form-data"> File: <input type="file" name="file"/> Desc: <input type="text" name="desc"/> <input type="submit" value="Submit"/> </form>
|
自定义拦截器
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 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
| public class FirstInterceptor implements HandlerInterceptor {
@Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("preHandle"); return true; }
@Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception { System.out.println("postHandle"); }
@Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception { System.out.println("afterCompletion"); } }
|
配置多个拦截器
1 2 3 4 5 6 7 8 9 10 11
| <mvc:interceptors> <bean id="firstInterceptor" class="com.mamh.springmvc.demo.interceptor.FirstInterceptor"/>
<mvc:interceptor> <mvc:mapping path="/emps"/> <bean class="com.mamh.springmvc.demo.interceptor.SecondInterceptor"/> </mvc:interceptor> </mvc:interceptors>
|
Redirect, foward区别
1 2 3 4 5 6 7 8 9
| 1、foward是服务器端控制页面转向,在客户端的浏览器地址中不会显示转向后的地址;sendRedirect则是完全的跳转,浏览器中会显示跳转的地址并重新发送请求链接。
原理:forward是服务器请求资源,服务器直接访问目标地址的URL,把那个URL的响应内容读取过来,然后再将这些内容返回给浏览器, 浏览器根本不知道服务器发送的这些内容是从哪来的,所以地址栏还是原来的地址。
redirect是服务器端根据逻辑,发送一个状态码,告诉浏览器重新去请求的那个地址,浏览器会用刚才的所有参数重新发送新的请求。
|