Spring MVC --- RestFul 风格、页面跳转方式-原理区别(重定向、转发)、数据处理(接收请求参数、数据回显、乱码问题)

一. RestFul 风格

1.1 原理与功能

  • 概念
    Restful就是一个资源定位及资源操作的风格。不是标准也不是协议,只是一种风格。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。
  • 功能
    资源:互联网所有的事物都可以被抽象为资源 资源操作:使用POST、DELETE、PUT、GET,使用不同方法对资源进行操作。 分别对应 添加、 删除、修改、查询。

1.2 传统风格与 Restful 风格对比

  • 传统方式操作资源
    通过不同的参数来实现不同的效果!方法单一,post 和 get
http://127.0.0.1/item/queryItem.action?id=1 查询,GET
http://127.0.0.1/item/saveItem.action 新 增,POST
http://127.0.0.1/item/updateItem.action 更新,POST
http://127.0.0.1/item/deleteItem.action?id=1 删除,GET或POST
  • 使用RESTful操作资源
    可以通过不同的请求方式来实现不同的效果!如下:请求地址一样,但是功能可以不同!
http://127.0.0.1/item/1 查询,GET 
http://127.0.0.1/item 新增,POST 
http://127.0.0.1/item 更新,PUT 
http://127.0.0.1/item/1 删除,DELETE

1.3 代码测试

  • 在 Spring MVC 中可以使用 @PathVariable 注解,让方法参数的值对应绑定到一个 URI 模板变量上。
@Controller
public class RestFulController {
    
    

    // 原来的 localhost:8080/add?a=1&b=2
    // Restful localhost:8080/add/{a}/{b}

    // @RequestMapping(value = "/add/{a}/{b}", method = RequestMethod.GET)
    @GetMapping("/add/{a}/{b}")
    public String test1(@PathVariable int a,@PathVariable int b, Model model){
    
    
        int res = a+b;
        model.addAttribute("message","结果1为"+res);
        return "test";
    }

    @PostMapping("/add/{a}/{b}")
    public String test2(@PathVariable int a,@PathVariable int b, Model model){
    
    
        int res = a+b;
        model.addAttribute("message","结果2为"+res);
        return "test";
    }
}

启动 Tomcat 服务器,结果如下:

1.4 思考

使用路径变量的好处:

  • 使路径变得更加简洁;
  • 获得参数更加方便,框架会自动进行类型转换。
  • 通过路径变量的类型可以约束访问参数,如果类型不一样,则访问不到对应的请求方法,

1.5 小结

  • Spring MVC 的 @RequestMapping 注解能够处理 HTTP 请求的方法, 比如 GET, PUT, POST, DELETE 以 及 PATCH。
  • 所有的地址栏请求默认都会是 HTTP GET 类型的。
  • 方法级别的注解变体有如下几个: 组合注解
@GetMapping 
@PostMapping 
@PutMapping 
@DeleteMapping 
@PatchMapping

@GetMapping 是一个组合注解

它所扮演的是 @RequestMapping(method =RequestMethod.GET) 的一个快捷方式。

平时使用的会比较多!

二. 结果跳转方式

2.1 ModelAndView

  • 设置 ModelAndView 对象 , 根据 view 的名称 , 和视图解析器跳到指定的页面 .
  • 页面 : {视图解析器前缀} + viewName +{视图解析器后缀}
    <!-- 视图解析器 -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver "
          id="internalResourceViewResolver">
        <!-- 前缀 -->
        <property name="prefix" value="/WEB-INF/jsp/" />
        <!-- 后缀 -->
        <property name="suffix" value=".jsp" />
    </bean>

对应的 Controller 类:

@Controller
@RequestMapping("/HelloController")
public class HelloController {
    
    

    // 真实访问地址: localhost:8080/HelloController/hello
    @RequestMapping("/hello")
    public String sayHello(Model model){
    
    
        // 向模型中添加属性值message,可以与JSP页面中取出并渲染
        model.addAttribute("msg","Hello SpringMVC!!!");
        // WEB-INF/jsp/hello.jsp
        return "hello";
    }
}

2.2 ServletAPI

通过设置ServletAPI , 不需要视图解析器 .

  1. 通过 HttpServletResponse 进行输出
  2. 通过 HttpServletResponse 实现重定向
  3. 通过 HttpServletResponse 实现转发
@Controller
public class ResultGo {
    
    

    @RequestMapping("/result/t1") 
    public void test1(HttpServletRequest req, HttpServletResponse rsp) 
            throws IOException {
    
     
        rsp.getWriter().println("Hello,Spring BY servlet API"); 
    }
        
        @RequestMapping("/result/t2") 
        public void test2(HttpServletRequest req, HttpServletResponse rsp) 
                throws IOException {
    
     
        rsp.sendRedirect("/index.jsp"); 
    }
                
        @RequestMapping("/result/t3") 
        public void test3(HttpServletRequest req, HttpServletResponse rsp) 
                throws Exception {
    
     
       // 转发
        req.setAttribute("msg","/result/t3");
        req.getRequestDispatcher("/WEB-INF/jsp/test.jsp").forward(req,rsp); }
}

2.3 Spring MVC

  • 重定向 和 转发 的区别;
  1. 请求次数:重定向是浏览器向服务器发送一个请求并收到响应后再次向一个新地址发出请求,转发是服务器收到请求后为了完成响应跳转到一个新的地址;重定向至少请求两次,转发请求一次;

  2. 地址栏不同:重定向地址栏会发生变化,转发地址栏不会发生变化

  3. 是否共享数据:重定向两次请求不共享数据,转发一次请求共享数据(在request级别使用信息共享,使用重定向必然出错);

  4. 跳转限制:重定向可以跳转到任意URL,转发只能跳转本站点资源;

  5. 发生行为不同:重定向是客户端行为,转发是服务器端行为;

  • 代码学习
    @GetMapping("/add/{a}/{b}")
    public String test1(@PathVariable int a,@PathVariable int b, Model model){
    
    
        int res = a+b;
        model.addAttribute("message","结果1为"+res);
        // 转发
        return "test";
    }

    @PostMapping("/add/{a}/{b}")
    public String test2(@PathVariable int a,@PathVariable int b, Model model){
    
    
        int res = a+b;
        model.addAttribute("message","结果2为"+res);
        // 转发二
        return "test";
    }

    @DeleteMapping ("/add/{a}/{b}")
    public String test3(@PathVariable int a,@PathVariable int b, Model model){
    
    
        int res = a+b;
        model.addAttribute("message","结果3为"+res);
        // 重定向
        return "redirect:/test.jsp";
    }
  • 注意:
    通过 SpringMVC 来实现转发和重定向 - 有视图解析器;
    重定向 , 不需要视图解析器 , 本质就是重新请求一个新地方嘛 , 所以注意路径问题

三. 数据处理

3.1 处理提交数据

  • 提交的域名称和处理方法的参数名一致

提交数据 : http://localhost:8080/hello?name=kc

处理方法 :

@RequestMapping("/hello")
public String hello(String name){
    
    
    System.out.println(name);
    return "hello";
}

后台输出: kc

  • 提交的域名称和处理方法的参数名不一致 – @RequestParam(“xxoo”)

提交数据 : http://localhost:8080/hello?username=kc

处理方法 :

//@RequestParam("username") : username提交的域的名称 .
@RequestMapping("/hello")
public String hello(@RequestParam("username") String name){
    
    
    System.out.println(name);
    return "hello";
}

  • 提交的是一个对象

要求提交的表单域和对象的属性名一致 , 参数使用对象即可

  1. 实体类
@Date
@AllArgsConstructor
@NoArgsConstructor
public class User {
    
    
    private int id;
    private String name;
    private int age;
}
  1. 提交数据 : http://localhost:8080/user?name=kc&id=8&age=24

3.处理方法:

@RequestMapping("/user")
public String user(User user){
    
    
    System.out.println(user);
    return "hello";
}

后台输出 : User { id=8, name=‘kc’, age=24 }

说明:如果使用对象的话,前端传递的参数名和对象名必须一致,否则就是null。

3.2 数据显示到前端

  • ModelAndView
public class ControllerTest1 implements Controller {
    
    
 	
 	@RequestMapping("/t1")
    public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
    
    
        //返回一个模型视图对象
        ModelAndView mv = new ModelAndView();
        mv.addObject("msg","ControllerTest1");
        mv.setViewName("test");
        return mv;
    }
}

  • ModelMap
@RequestMapping("/t2")
public String hello(@RequestParam("username") String name, ModelMap model){
    
    
    //封装要显示到视图中的数据
    //相当于req.setAttribute("name",name);
    model.addAttribute("name",name);
    System.out.println(name);
    return "hello";
}

  • Model
@RequestMapping("/t3")
public String hello(@RequestParam("username") String name, Model model){
    
    
    //封装要显示到视图中的数据
    //相当于req.setAttribute("name",name);
    model.addAttribute("msg",name);
    System.out.println(name);
    return "test";
}

3.3 对比

  • Model 只有寥寥几个方法只适合用于储存数据,简化了新手对于 Model 对象的操作和理解;

  • ModelMap 继承了 LinkedMap ,除了实现了自身的一些方法,同样的继承 LinkedMap 的方法和特性;

  • ModelAndView 可以在储存数据的同时,可以进行设置返回的逻辑视图,进行控制展示层的跳转。

3.4 乱码问题

测试步骤:

  1. 我们可以在首页编写一个提交的表单
<form action="/e/t" method="post">
  <input type="text" name="name">
  <input type="submit">
</form>
  1. 后台编写对应的处理类
@Controller
public class Encoding {
    
    
    @RequestMapping("/e/t")
    public String test(Model model,String name){
    
    
        model.addAttribute("msg",name); //获取表单提交的值
        return "test"; //跳转到test页面显示输入的值
    }
}

  1. 输入中文测试,发现乱码

  2. 修改了 xml 文件,添加过滤器
    以前乱码问题通过过滤器解决 , 而 SpringMVC 给我们提供了一个过滤器 , 可以在web.xml中配置

<!--2.配置SpringMVC的乱码过滤-->
<filter>
    <filter-name>encoding</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>encoding</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

乱码问题解决!

猜你喜欢

转载自blog.csdn.net/Kc635908933/article/details/114834063