SpringMVC - 请求

1. @Controller

@Controller 用于标记在一个类上,使用它标记的类就是一个SpringMVC Controller 对象。分发处理器将会扫描使用了该注解的类的方法,并检测该方法是否使用了@RequestMapping 注解。@Controller 只是定义了一个控制器类,而使用@RequestMapping 注解的方法才是真正处理请求的处理器。

单单使用@Controller 标记在一个类上还不能真正意义上的说它就是SpringMVC 的一个控制器类,因为这个时候Spring 还不认识它。那么要如何做Spring 才能认识它呢?这个时候就需要我们把这个控制器类交给Spring 来管理。有两种方式:
① 在SpringMVC 的配置文件中定义MyController 的bean 对象

<!--方式一-->
<bean class="com.host.app.web.controller.MyController"/>

② SpringMVC 的配置文件中告诉Spring 该到哪里去找标记为@Controller 的Controller 控制器

<!--方式二-->
< context:component-scan base-package = "com.host.app.web" />//路径写到controller的上一层

2. @RequestMapping

RequestMapping是一个用来处理请求地址映射的注解,可用于类或方法上。用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径

2.1 属性

**value:**指定请求的实际地址

@RestController  
@RequestMapping("/home")  
public class IndexController {  
    @RequestMapping(value="/")  
    String get() {  
        //mapped to hostname:port/home/  
        return "Hello from get";  
    }  
    @RequestMapping("/index")  
    String index() {  
        //mapped to hostname:port/home/index/  
        return "Hello from index";  
    }  
}

还支持ant风格的通配符

@RequestMapping("/index/*/a")  
    String index() {  
        //mapped to hostname:port/home/index/  
        return "Hello from index";  
    }  

**method:**指定请求的method类型, GET, PUT, POST, DELETE 以及 PATCH

@RestController  
@RequestMapping("/home")  
public class IndexController {  
    @RequestMapping(method = RequestMethod.GET)  
    String get() {  
        return "Hello from get";  
    }  
    @RequestMapping(method = RequestMethod.DELETE)  
    String delete() {  
        return "Hello from delete";  
    }  
    @RequestMapping(method = RequestMethod.POST)  
    String post() {  
        return "Hello from post";  
    }  
    @RequestMapping(method = RequestMethod.PUT)  
    String put() {  
        return "Hello from put";  
    }  
    @RequestMapping(method = RequestMethod.PATCH)  
    String patch() {  
        return "Hello from patch";  
    }  
}

**params:**指定request中必须包含某些参数值,如果写的

@RestController  
@RequestMapping("/home")  
public class IndexController {  
	//传递的参数必须有personId属性
    @RequestMapping(value = "/fetch", params = {  
        "personId"  
    })  
    String getParams(@RequestParam("personId") String id) {  
        return "Fetched parameter using params attribute = " + id;  
    }  

	//传递的参数必须有personId参数而且值要等于20
    @RequestMapping(value = "/fetch", params = {  
        "personId=20"  
    })  
    String getParamsDifferent(@RequestParam("personId") String id) {  
        return "Fetched parameter using params attribute = " + id;  
    }  
}

	//传递的参数必须有personId参数而且值要不等于20
    @RequestMapping(value = "/fetch", params = {  
        "personId!=20"  
    })  
    String getParamsDifferent2(@RequestParam("personId") String id) {  
        return "Fetched parameter using params attribute = " + id;  
    }  
}

consumes: 指定处理请求的提交内容类型(Content-Type),例如application/json, text/html

@Controller
@RequestMapping(value = "/pets", method = RequestMethod.POST, 	consumes="application/json")
public void addPet(@RequestBody Pet pet, Model model) {    
    // implementation omitted
}

headers: 指定request中必须包含某些指定的请求头,才能让该方法处理请求

@Controller
@RequestMapping("/owners/{ownerId}")
public class RelativePathUriTemplateController {
 
	@RequestMapping(value = "/pets", method = RequestMethod.GET, 		
	headers="Referer=http://www.ifeng.com/")
  	public void findPet(@PathVariable String ownerId, @PathVariable String petId, Model model) {    
    	// implementation omitted
  	}
}

3. 请求参数的绑定

3.1 基本类型参数

包括基本类型和 String 类型
使用要求:参数名称必须和控制器中方法的形参名称保持一致。 (严格区分大小写)
index.jsp

扫描二维码关注公众号,回复: 9974357 查看本文章
<form action="${pageContext.request.contextPath}/user/testParam" method="post">
	用户名: <input type="text" name="username"> <br>
	年龄: <input type="text" name="age"> <br>
	性别: <input type="text" name="sex"> <br>
    <input type="submit" value="提交">
</form>

UserController.java

@Controller
@RequestMapping("/user")
public class UserController2 {

    @RequestMapping(value = "/testParam",method = RequestMethod.POST)
    public String testParam(String username,Integer age,Character sex){
        System.out.println(username + "--" + age + "--" + sex);
        return "show";
    }
}

3.2 POJO类型参数

  • 要求集合类型的请求参数必须在 POJO 中。在表单中请求参数名称要和 POJO 中集合属性名称相同。

index.jsp

<form action="${pageContext.request.contextPath}/user/saveUser" method="post">
	用户名: <input type="text" name="username"> <br>
    年龄: <input type="text" name="age"> <br>
    性别: <input type="text" name="sex"> <br>
    一个角色对象:<!--role为 POJO类型参数-->
    id:<input type="text" name="role.id">
    roleName:<input type="text" name="role.roleName"><br>
    <input type="submit" value="提交">
</form>

Role.java

public class Role {
    private Integer id;
    private String roleName;
    //此处省略 getter and setter toString
}

User.java

public class User {
    private Integer id;
    private String username;
    private Character sex;
    private Integer age;

    private  Role role; //POJO 类型参数
    //此处省略 getter and setter toString
 }

UserController.java

@RequestMapping(value = "/saveUser",method = RequestMethod.POST)
public String saveUser(User user){
	System.out.println(user);
    return "show";
}

3.3 集杂数据类型

3.3.1 数组

表单中name属性相同,value不同;形参是数组,且名称相同

3.3.2 集合
  • 要求集合类型的请求参数必须在 POJO 中。在表单中请求参数名称要和 POJO 中集合属性名称相同

  • 给 List 集合中的元素赋值,使用下标

  • 给 Map 集合中的元素赋值,使用键值对

index.jsp

   <form action="${pageContext.request.contextPath}/user/saveUser" method="post">
       用户名: <input type="text" name="username"> <br>
       年龄: <input type="text" name="ag"> <br>
        性别: <input type="text" name="sex"> <br>
        list集合参数: <input type="text" name="list[0]">
                       <input type="text" name="list[1]"><br>
        一个角色对象:<input type="text" name="role.id">
                    <input type="text" name="role.roleName"><br>
        多个角色对象:<input type="text" name="roleList[0].id">
                    <input type="text" name="roleList[0].roleName"><br>
                    <input type="text" name="roleList[1].id">
                    <input type="text" name="roleList[1].roleName"><br>
        map集合:<input type="text" name="map[one]"><br>
                <input type="text" name="map[two]"><br>
                <input type="text" name="map[three]"><br>

        <input type="submit" value="提交">
    </form>

Role.java

public class Role {

    private Integer id;
    private String roleName;
    //此处省略 getter and setter toString
}

User.java

public class User {
    private Integer id;
    private String username;
    private Character sex;
    private Integer age;
    
    private List<String> list;
    private  Role role;
    private List<Role> roleList;
    private Map<String ,Object> map;
    //此处省略 getter and setter toString
 }

UserController.java

    @RequestMapping(value = "/saveUser",method = RequestMethod.POST)
    public String saveUser(User user){
        System.out.println(user);
        return "show";
    }

后台结果

User {
	id = null,
	username = 'zhangsan',
	sex =,
	age = 30,
	list = [hello, world],
	role = Role {
		id = 21,
		roleName = 'cook'
	},
	roleList = [Role {
			id = 23,
			roleName = 'teacher'
		}, Role {
			id = 25,
			roleName = 'student'
		}
	],
	map = {
		one = little,
		three = huge,
		two = big
	}
}


4. 请求参数中文乱码的解决

在web.xml中配置Spring提供的过滤器类

<!-- 配置过滤器,解决中文乱码的问题 -->
    <filter>
        <filter-name>characterEncodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <!-- 指定字符集 -->
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
    </filter>
    <!-- 过滤所有请求 --> 
    <filter-mapping>
        <filter-name>characterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

5. 类型转换器

  • 表单提交的任何数据类型全部都是字符串类型,但是后台定义Integer类型,数据也可以封装上,说明Spring框架内部会默认进行数据类型转换。

  • 如果想自定义数据类型转换,可以实现Converter的接口

  • 注册自定义类型转换器,在springmvc.xml配置文件中编写配置

  • 还是可以使用Formatter进行类型转换

当我们在后端对日期类型的参数进行准换,默认只转换2000/1/1类型的日期,如果输入的是2000-1-1转换就会出错

<form action="${pageContext.request.contextPath}/user/testDate">
    <input type="date" name="birthday">
    <input type="submit" value="提交">
</form>

    @RequestMapping("/testDate")
    public String testDate(String birthday){
        System.out.println(birthday);
        return "show";
    }

自定义String–>Date类型转换器

public class StringToDateConverter implements Converter<String ,Date>{
    //把 String 类型转成日期类型
    
    @Override
    public Date convert(String source) {
        //日期类型的转换对象
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Date date = null;
        try {
            date = sdf.parse(source);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return date;
    }
}

在 spring 配置文件中配置类型转换器

    <!-- 配置类型转换器工厂 -->
    <bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
    <!-- 给工厂注入一个新的类型转换器 -->
        <property name="converters">
            <set>
           		 <!-- 配置自定义类型转换器 -->
                <bean class="com.testfan.converter.StringToDateConverter"></bean>
            </set>
        </property>
    </bean>

在 annotation-driven 标签中引用配置的类型转换服务

<!-- 引用自定义类型转换器 -->
<!--注解驱动: 关联类型转换工厂-->
<mvc:annotation-driven conversion-service="conversionService"></mvc:annotation-driven>

6. 获取Servlet原生API

在参数写上就行

@RequestMapping(path="/servletAPI")
public String servletAPI(HttpServletRequest request , HttpServletResponse response){
 
	HttpSession session = request.getSession();
	System.out.println(session);
 
	ServletContext servletContext = session.getServletContext();
	System.out.println(servletContext);
 
    System.out.println(request);
    System.out.println(response);
 
	return "success";
}

7. @RequestParam

前面看的接收参数,方法的参数名必须和传递的参数名一致,为了解决不一致问题,可以使用这个注解完成一个映射

index.jsp

<form action="${pageContext.request.contextPath}/user/testParam" method="post">
	用户名: <input type="text" name="username"> <br>
</form>

UserController.java

@Controller
@RequestMapping("/user")
public class UserController2 {

    @RequestMapping(value = "/testParam")
    public String testParam(@RequestParam("username") String name){
        System.out.println(username);
        return "show";
    }
}

8. @RequestBody

用来获取请求体

9. @PathVariable

当使用@RequestMapping URI template 样式映射时, 即 someUrl/{paramId}, 这时的paramId可通过 @Pathvariable注解绑定它传过来的值到方法的参数上

支持Restful风格的URL

@Controller
@RequestMapping("/owners/{ownerId}")
public class RelativePathUriTemplateController {
 
  @RequestMapping("/pets/{petId}")
  public void findPet(@PathVariable String ownerId, @PathVariable String petId, Model model) {    
    // implementation omitted
  }
}

10. @RequestHeader

@RequestHeader 注解,可以把Request请求header部分的值绑定到方法的参数上

Host                    localhost:8080
Accept                  text/html,application/xhtml+xml,application/xml;q=0.9
Accept-Language         fr,en-gb;q=0.7,en;q=0.3
Accept-Encoding         gzip,deflate
Accept-Charset          ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive              300
@RequestMapping("/displayHeaderInfo.do")
public void displayHeaderInfo(@RequestHeader("Accept-Encoding") String encoding,
                              @RequestHeader("Keep-Alive") long keepAlive)  {
 
  //...
 
}

10. @CookieValue

可以把Request header中关于cookie的值绑定到方法的参数上

//JSESSIONID=415A4AC178C59DACE0B2C9CA727CDD84
@RequestMapping("/displayHeaderInfo.do")
public void displayHeaderInfo(@CookieValue("JSESSIONID") String cookie)  {
 
  //...
 
}

11. @ModelAttribute

该注解有两个用法,一个是用于方法上,一个是用于参数上;

用于方法上时: 被@ModelAttribute注释的方法会在此controller每个方法执行前被执行,因此对于一个controller映射多个URL的用法来说,要谨慎使用,通常用来在处理@RequestMapping之前,为请求绑定需要从后台查询的model;

// Add one attribute
// The return value of the method is added to the model under the name "account"
// You can customize the name via @ModelAttribute("myAccount")
 
@ModelAttribute
public Account addAccount(@RequestParam String number) {
    return accountManager.findAccount(number);
}

用于参数上时: 用来通过名称对应,把相应名称的值绑定到注解的参数bean上

12. @SessionAttributes

默认情况下Spring MVC将模型中的数据存储到request域中。当一个请求结束后,数据就失效了。如果要跨页面使用。那么需要使用到session。而@SessionAttributes注解就可以使得模型中的数据存储一份到session域中

@SessionAttributes(types=User.class)会将model中所有类型为 User的属性添加到会话中

@SessionAttributes(value={"user1", "user2"}) 会将model中属性名为user1和user2的属性添加到会话中。

@SessionAttributes(types={User.class, Dept.class}) 会将model中所有类型为 User和Dept的属性添加到会话中

@SessionAttributes(value={"user1","user2"},types={Dept.class})会将model中属性名为user1和user2以及类型为Dept的属性添加到会话中。value和type之间是并集关系

@SessionAttributes(value={"user"})
@Controller
public class UserController {

    @RequestMapping("/testSessionAttributes")
    public String testSessionAttributes(Model model){
        User user = new User("jack","123456");
        model.addAttribute("user", user);
        return "success";
    }
}
发布了167 篇原创文章 · 获赞 3 · 访问量 5414

猜你喜欢

转载自blog.csdn.net/weixin_43907800/article/details/104838116