SpringMVC学习笔记二

一、类型转换器

虽然我们前面在获取参数时看起来非常轻松,但是在这个过程中是有可能出现一些问题的。
例如,请求参数为success=1 我们期望把这个请求参数获取出来赋值给一个Boolean类型的变量。
这里就会涉及到 Stirng-——>Boolean的类型转换了。实际上SpringMVC中内置了很多类型转换器来进行类型转换。也有专门进行Stirng-——>Boolean类型转换的转换器StringToBooleanConverter。
如果是符合SpringMVC内置转换器的转换规则就可以很轻松的实现转换。但是如果不符合转换器的规则呢?

例如,请求参数为birthday=2004-12-12 我们期望把这个请求参数获取出来赋值给一个Date类型的变量。就不符合内置的规则了。内置的可以把 2004/12/12 这种格式进行转换。这种情况下我们就可以选择自定义类型转换。

1.1 自定义类型转换器

①创建类实现Converter接口

public class StringToDateConverter implements Converter<String, Date> {
    
    
    public Date convert(String source) {
    
    
        return null;
    }
}

②实现convert方法

public class StringToDateConverter implements Converter<String, Date> {
    
    
    public Date convert(String source) {
    
    
        //String->Date   2005-12-12 
        Date date = null;
        try {
    
    
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
            date = simpleDateFormat.parse(source);
        } catch (ParseException e) {
    
    
            e.printStackTrace();
        }
        return date;
    }
}

③配置让SpringMVC使用自定义转换器

    <!--解决响应乱码-->
    <mvc:annotation-driven conversion-service="myConversionService">
        <mvc:message-converters>
            <bean class="org.springframework.http.converter.StringHttpMessageConverter">
                <constructor-arg value="utf-8"/>
            </bean>
        </mvc:message-converters>
    </mvc:annotation-driven>

    <bean class="org.springframework.context.support.ConversionServiceFactoryBean" id="myConversionService">
        <property name="converters">
            <set>
                <bean class="com.lx.converter.StringToDateConverter"></bean>
            </set>
        </property>
    </bean>

1.2 日期转换简便解决方案

如果是String到Date的转换我们也可以使用另外一种更方便的方式。使用@DateTimeFormat来指定字符串的格式。

    @RequestMapping("/testDateConverter")
    public String testDateConverter(@DateTimeFormat(pattern = "yyyy-MM-dd") Date birthday){
    
    
        System.out.println("testDateConverter");
        System.out.println(birthday);
        return "success";
    }

二、响应体响应数据

无论是RestFul风格还是我们之前web阶段接触过的异步请求,都需要把数据转换成Json放入响应体中。

2.1 数据放到响应体

我们的SpringMVC为我们提供了@ResponseBody来非常方便的把Json放到响应体中。

@ResponseBody可以加在哪些东西上面?类上和方法上

具体代码请参考范例。

2.2 数据转换成Json

SpringMVC可以帮我们进行Json的转换,不过需要进行相应配置.
①导入jackson依赖

		<!-- jackson,帮助进行json转换-->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.9.0</version>
        </dependency>

②开启mvc的注解驱动

 <mvc:annotation-driven></mvc:annotation-driven>

2.3 使用示例

示例一:
要求定义个RestFul风格的接口,该接口可以用来根据id查询用户。请求路径要求为 /response/user ,请求方式要求为GET。
而请求参数id要写在请求路径上,例如 /response/user/1 这里的1就是id。
要求获取参数id,去查询对应id的用户信息(模拟查询即可,可以选择直接new一个User对象),并且转换成json响应到响应体中。

@Controller
@RequestMapping("/response")
public class ResponseController {
    
    
    @GetMapping("/user/{id}")
    @ResponseBody //这方法的返回值放入响应体中
    public User testResponse(@PathVariable Integer id){
    
    
        User user = new User(id,null,null,null);
        return user;//因为以及做过配置,所以会把返回值转换成json
    }
}

示例二:
要求定义个RestFul风格的接口,该接口可以查询所有用户。请求路径要求为 /response/user ,请求方式要求为GET。
去查询所有的用户信息(模拟查询即可,可以选择直接创建集合,添加几个User对象),并且转换成json响应到响应体中。

@Controller
@RequestMapping("/response")
@ResponseBody  //这类中所有方法的返回值都会放到响应体中
public class ResponseController {
    
    

    @GetMapping("/user/{id}")
    public User testResponse(@PathVariable Integer id){
    
    
        User user = new User(id,null,null,null);
        return user;
    }

    @GetMapping("/user")
    public List<User> testResponse2(){
    
    
        List<User> list = new ArrayList<User>();
        list.add(new User(1,"张三",15,null));
        list.add(new User(2,"李四",16,null));
        list.add(new User(3,"王五",17,null));
        return list;
    }
}

如果一个Controller中的所有方法返回值都要放入响应体,那么我们可以直接在Controller类上加@ResponseBody。
我们可以使用@RestController 注解替换@Controller和@ResponseBody两个注解

@RequestMapping("/response")
@RestController //相当于  @Controller+@ResponseBody
public class ResponseController {
    
    

    @GetMapping("/user/{id}")
    public User testResponse(@PathVariable Integer id){
    
    
        User user = new User(id,null,null,null);
        return user;
    }

  	@GetMapping("/user")
    public List<User> testResponse2(){
    
    
        List<User> list = new ArrayList<User>();
        list.add(new User(1,"张三",15,null));
        list.add(new User(2,"李四",16,null));
        list.add(new User(3,"王五",17,null));
        return list;
    }
}

三、页面跳转

默认的跳转其实是转发的方式跳转的。我们也可以选择加上标识,在要跳转的路径前加上forward: 。这样SpringMVC也会帮我们进行请求转发。
例如:

@Controller
public class PageJumpController {
    
    
    @RequestMapping("/testJump")
    public String testJump(){
    
    
        return "forward:/success";
    }
}

如果想实现重定向跳转则可以在跳转路径前加上 redirect: 进行标识。这样SpringMVC就会帮我们进行重定向跳转。
例如:

@Controller
public class PageJumpController {
    
    
    @RequestMapping("/testJump")
    public String testJump(){
    
    
        return "redirect:/success";
    }
}

四、视图解析器

如果我们经常需要跳转页面,并且页面所在的路径比较长,我们每次写完整路径会显的有点麻烦。我们可以配置视图解析器,设置跳转路径的前缀和后缀。这样可以简化我们的书写。

4.1 使用步骤

①配置视图解析器
我们需要往SpringMVC容器中注入ThymeleafViewResolver对象。

  • ThymeleafViewResolver
  • InternalResourceViewResolver
<!--配置Thymeleaf视图解析器-->
    <bean id="viewResolver" class="org.thymeleaf.spring5.view.ThymeleafViewResolver">
        <property name="order" value="1"/>
        <property name="characterEncoding" value="UTF-8"/>
        <property name="templateEngine">
            <bean class="org.thymeleaf.spring5.SpringTemplateEngine">
                <property name="templateResolver">
                    <bean class="org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver">
                        <!-- 视图前缀-->
                        <property name="prefix" value="/WEB-INF/templates/"/>
                        <!--视图后缀-->
                        <property name="suffix" value=".html"/>
                        <property name="templateMode" value="HTML5"/>
                        <property name="characterEncoding" value="UTF-8" />
                    </bean>
                </property>
            </bean>
        </property>
    </bean>

②页面跳转
视图解析器会在逻辑视图的基础上拼接得到物理视图。

    @RequestMapping("/testJumpToJsp")
    public String testJumpToJsp(){
    
    
//        return "/WEB-INF/page/test.html";
        return "test";
    }

4.2 不进行前后缀拼接

如果在配置了视图解析器的情况下,某些方法中并不想拼接前后缀去跳转。这种情况下我们可以在跳转路径前加forward: 或者redirect:进行标识。这样就不会进行前后缀的拼接了。

    @RequestMapping("/testJumpHtml")
    public String testJumpHtml(){
    
    
        //如果加了forward:  或者redirect: 就不会进行前后缀的拼接
        return "forward:/hello1.html";
    }

五、获取原生对象

我们之前在web阶段我们经常要使用到request对象,response,session对象等。我们也可以通过SpringMVC获取到这些对象。(不过在MVC中我们很少获取这些对象,因为有更简便的方式,避免了我们使用这些原生对象相对繁琐的API。)

我们只需要在方法上添加对应类型的参数即可,但是注意数据类型不要写错了,SpringMVC会把我们需要的对象传给我们的形参。

@Controller
public class TestParamController {
    
    
    @RequestMapping("/param/ServletAPI")
    public String testParam(HttpServletRequest request, HttpServletResponse response){
    
    
        String host = request.getRemoteHost();
        HttpSession session = request.getSession();
        session.setAttribute("userName","rootAdmin");
        String username = request.getParameter("username");
        String password= request.getParameter("password");
        System.out.println(String.format("username:%s,password:%s",username,password));
        return "success";
    }
}

六、获取请求头和Cookie

6.1获取请求头

在方法中定义一个参数,参数前加上@RequestHeader注解,知道要获取的请求头名即可获取对应请求头的值。
例如获取header中的User-Agent信息

@Controller
public class RequestResponseController {
    
    
    @RequestMapping("/param")
    public String getParam(
            @RequestHeader(value = "User-Agent",required = true) String agent,
    )
    {
    
    
        System.out.println("User-Agent:"+agent);
        System.out.println(jsessionid);
        return "success";
    }
}

6.2 获取Cookie

在方法中定义一个参数,参数前加上@CookieValue 注解,知道要获取的cookie名即可获取对应cookie的值。
例如:想要获取 JSESSIONID 的cookie值。则可以按照如下方式定义方法。

@Controller
public class RequestResponseController {
    
    
    @RequestMapping("/getCookie")
    public String getCookie(@CookieValue("JSESSIONID") String sessionId){
    
    
        System.out.println(sessionId);
        return "test";
    }
}

七、向域中存取数据

向域对象共享数据:

  1. 通过ModelAndView向请求域共享数据
    使用ModelAndView时,可以使用其Model 功能向请求域共享数据
    使用view功能设置逻辑视图,但是控制器方法一定要将ModeLAndview作为方法的返回值
  2. 使用Model 向请求域共享数据
  3. 使用ModelMap 向请求域共享数据
  4. 使用map向请求域共享数掮
  5. Model,ModelMap和map的关系

其实在底层中,这些类型的形参最终都是通过BindingAwareModelMap创建

7.1 使用ModelAndView

@Controller
public class TestScopeController {
    
    
    @RequestMapping("/test/mav")
    public ModelAndView testMAV(){
    
    
        /*
        * * ModeLAndView包含Model和View的功能
        Model:向请求域中共享数据
        View:设置逻辑视图实现页面跳转
        * */
        ModelAndView mav = new ModelAndView();
        //向请求域中共享数据
        mav.addObject("testRequestScope","hello,modelAndview");
        //设置逻辑视图
        mav.setViewName("success");
        return mav;
    }
}

前端使用thymeleaf语法获取数据

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>成功页面</title>
</head>
<body>
<h1>访问成功!</h1>
<p th:text="${testRequestScope}"></p>
</body>
</html>

7.2 使用Model

@Controller
public class JspController {
    
    
    @RequestMapping("/test/model")
    public String testModel(Model model){
    
    
        model.addAttribute("testRequestScope","hello,model");
        return "success";
    }
}

7.3 使用ModelMap

@Controller
public class JspController {
    
    
       @RequestMapping("/test/modelMap")
    public String testModelMap(ModelMap modelMap){
    
    
        modelMap.addAttribute("testRequestScope","hello,modelMap");
        return "success";
    }
}

7.4 使用Map

@Controller
public class JspController {
    
    
    @RequestMapping("/test/map")
    public String testModelMap(Map<String,String> map){
    
    
        map.put("testRequestScope","hello,map");
        return "success";
    }
}

7.5 往Session域中存取数据

@Controller
public class JspController {
    
    
    @RequestMapping("/test/session")
    public String testSession(HttpSession session){
    
    
        session.setAttribute("testSessionScope","hello,session");
        return "success";
    }
}

7.6 获取Session域中数据

我们可以使用@SessionAttribute把他加在方法参数上,可以让SpringMVC帮我们从Session域中获取相关数据。

@Controller
@SessionAttributes({
    
    "name"})
public class JspController {
    
    
    @RequestMapping("/testGetSessionAttr")
    public String testGetSessionAttr(@SessionAttribute("testSessionScope") String testSessionScope){
    
    
        System.out.println(testSessionScope);
        return "testScope";
    }

}

猜你喜欢

转载自blog.csdn.net/lx00000025/article/details/131964579