SpringMVC HelloWorld
HelloWorld运行流程
- 客户端点击链接会发送http://localhost:8080/springmvc/hello请求
- 来到tomcat服务器:
- SpringMVC的前端控制器收到所有请求
- 来看请求地址和@RequestMapping标注的那个匹配,来找到使用哪个类的哪个方法处理
- 前端控制器找到了目标处理器类和目标方法,直接利用反射执行目标方法
- 方法执行完成后会有一个返回值,若无其他注解,SpringMVC会认为这个返回值就是要去的页面地址
- 拿到方法返回之后,用视图解析器拼串得到完整的页面地址
- 拿到页面地址,前端控制器帮我们转发到页面
构建Maven项目,搭建SpringMVC开发环境
<?xml version="1.0" encoding="UTF-8"?>
<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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com</groupId>
<artifactId>springmvc-07-restful</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<name>springmvc-07-restful Maven Webapp</name>
<!-- FIXME change it to the project's website -->
<url>http://www.example.com</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.1.9.RELEASE</version>
</dependency>
</dependencies>
<build>
<finalName>springmvc-07-restful</finalName>
<pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
<plugins>
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging -->
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.2</version>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
配置web.xml
- 注册DispatcherServlet,DispatcherServlet需要绑定Spring的配置文件。有以下注意事项。
- 在
servlet-mapping
中,url-pattern
中设置为/
不会拦截jsp页面,若设置为/*
会拦截所有页面。 - 在服务器的总
web.xml
中有DefaultServlet
改Servlet是用来配置静态资源的。这样静态资源会被匹配到前端控制器,寻找RequestMapping中匹配的方法。
- 在
- 配置CharacterEncodingFilter,用来解决post请求的乱码问题。
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!--注册DispatcherServlet-->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--DispatcherServlet要绑定Spring的配置文件-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-web.xml</param-value>
</init-param>
<!--启动级别1,和服务器一起启动-->
<load-on-startup>1</load-on-startup>
</servlet>
<!--url-pattern
在/中只会匹配请求,不会匹配jsp页面
/* 都会匹配。
jsp是tomcat处理,但是会拦截html请求
1)服务器的大web.xml中有一个DefaultServlet是url-pattern=/
DefaultServlet是用来配置静态资源的;index.html;tomcat会在服务器下找到这个资源并返回
2)我们的配置中前端控制器url-pattern也是/,这样静态资源会被匹配到前端控制器,寻找RequestMapping中匹配的方法
3)没有覆盖jsp匹配的url-pattern,所以jsp不会被拦截。
4)/*会拦截所有请求,我们写/也会迎合后来的Rest风格
-->
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!--使用springMVC前端控制器直接写字符编码过滤器-->
<filter>
<filter-name>CharacterEncoding</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<!--解决POST请求乱码-->
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<!--解决相应乱码-->
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<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>
</web-app>
@RequestMapping注解
- 告诉SpringMVC,这个方法用来处理什么请求。
- RequestMapping可以标注在类上,会与方法上的注解进行组合。
@RequestMapping方法参数
- method:限定请求方式
- params:限定请求参数
- headers:可以规定请求头中的任意字段
- consumes:规定请求头中的Content-Type
- produces:告诉浏览器当前返回的内容是什么,给相应头中加上Content-Type:text/html;charset=utf-8
RequestMapping ant风格
URL地址可以写模糊的通配符
- ?能替代一个字符
- *能替代任意多个字符和一层路径
- **等替代多层路径
//ant风格url
@Controller
public class RequestMappingTest {
@RequestMapping("/antTest01")
public String hello(){
return "success";
}
//?匹配一个字符
//模糊和精确多个匹配下,精确优先
@RequestMapping("/antTest0?")
public String antTest02(){
return "success";
}
//*匹配任意多个字符或一层路径
//模糊和精确多个匹配下,精确优先
@RequestMapping("/antTest0*")
public String antTest03(){
return "success";
}
//**匹配任意多个字符或多层路径
//模糊和精确多个匹配下,精确优先
@RequestMapping("/antTest0**")
public String antTest04(){
return "success";
}
//路径上可以有占位符:占位符的语法就是可以在任意路径的地方写一个
//{变量名}
@RequestMapping("/user/{id}")
public String pathVariableTest(@PathVariable("id") String id){
System.out.println("路径上的占位符的值" + id);
return "hello";
}
}
配置一些bean
<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
https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
https://www.springframework.org/schema/mvc/spring-mvc.xsd">
<context:component-scan base-package="com.lym"/>
<mvc:default-servlet-handler/>
<mvc:annotation-driven/>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
</beans>
@PathVariable注解
为Restful风格提供支持
///book/{id}
@RequestMapping(path = "/book/{id}", method = RequestMethod.GET)
public String hello1(@PathVariable("id") String id){
System.out.println("查询到id为"+id+"的书籍");
return "success";
}
@RequestMapping(path = "/book/{id}", method = RequestMethod.POST)
public String hello2(@PathVariable("id") String id){
System.out.println("添加id为"+id+"的书籍");
return "success";
}
@RequestMapping(path = "/book/{id}", method = RequestMethod.PUT)
public String hello3(@PathVariable("id") String id){
System.out.println("修改到id为"+id+"的书籍");
return "success";
}
@RequestMapping(path = "/book/{id}", method = RequestMethod.DELETE)
public String hello4(@PathVariable("id") String id){
System.out.println("删除到id为"+id+"的书籍");
return "success";
}
@RequestParam @RequestHeader @CookieValue
@RequestParam 标注在方法的形参前,该参数会获得请求时携带的参数值,明确指定参数名的名称。具体参数功能如下
- value:指定获取的参数的key
- required:这个参数是否是必须的
- defaultValue:如果没带参数设置默认值
@RequestHeader 获得请求头信息
@CookieValue 获得请求头中的cookie中的值
这三个注解均有value,required,defaultValue三个属性值。
另外SpringMVC会自动为这个POJO赋值
将POJO中的每一个属性,从request参数中尝试出来,并封装即可
@RequestMapping("/book")
public String addBook(Book book){
System.out.println(book);
return "success";
}
package com.lym.controller.pojo;
public class Address {
private String Province;
private String city;
private String street;
public Address() {
}
public Address(String province, String city, String street) {
Province = province;
this.city = city;
this.street = street;
}
public String getProvince() {
return Province;
}
public void setProvince(String province) {
Province = province;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getStreet() {
return street;
}
public void setStreet(String street) {
this.street = street;
}
@Override
public String toString() {
return "Address{" +
"Province='" + Province + '\'' +
", city='" + city + '\'' +
", street='" + street + '\'' +
'}';
}
}
public class Book {
private String bookName;
private String author;
private Double price;
private Integer stock;
private Integer sales;
private Address address;
public Book(String bookName, String author, Double price, Integer stock, Integer sales, Address address) {
this.bookName = bookName;
this.author = author;
this.price = price;
this.stock = stock;
this.sales = sales;
this.address = address;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
public Book(){
}
public String getBookName() {
return bookName;
}
public void setBookName(String bookName) {
this.bookName = bookName;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public Double getPrice() {
return price;
}
public void setPrice(Double price) {
this.price = price;
}
public Integer getStock() {
return stock;
}
public void setStock(Integer stock) {
this.stock = stock;
}
public Integer getSales() {
return sales;
}
public void setSales(Integer sales) {
this.sales = sales;
}
@Override
public String toString() {
return "Book{" +
"bookName='" + bookName + '\'' +
", author='" + author + '\'' +
", price=" + price +
", stock=" + stock +
", sales=" + sales +
", address=" + address +
'}';
}
}
SpringMVC还可以传入原生API
直接在方法参数中提及
@RequestMapping("/handler03")
public String handler03(HttpSession session, HttpServletRequest request){
request.setAttribute("request","request中保存的值");
session.setAttribute("session","session中保存的值");
return "success";
}
SpringMVC数据输出的常用方法
方法参数为Map<String,Object>
方法参数为Model
方法参数为ModelMap
@Controller
@RequestMapping("/output")
@SessionAttributes("msg")
public class OutputController {
@RequestMapping("/handler01")
public String handler01(Map<String,Object> maps){
maps.put("msg","你好");
System.out.println();
return "success";
}
@RequestMapping("/handler02")
public String handler02(Model model){
model.addAttribute("msg","nihao");
return "success";
}
@RequestMapping("/handler03")
public String handler03(ModelMap modelMap){
modelMap.addAttribute("msg","nihao");
return "success";
}
@RequestMapping("/handler04")
public ModelAndView handler04(){
//之前的返回值我们就叫做视图名,视图名视图解析器会最终拼串得到页面的额真实地址
ModelAndView modelAndView = new ModelAndView("success");
modelAndView.addObject("msg","nihao");
return modelAndView;
}
}