SpringMVC基础(二)

SpringMVC基础(二)

使用注解开发SpringMVC

@Controller

@RequestMapping

  1. 配置web.xml(与使用配置文件开发中一直)

  2. 配置springmvc-servlet.xml(这与原来不同)

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans.xsd">
        
        <!-- 自动扫描包,使得包中的注解生效 -->
        <context:component-scan base-package="com.qiu.controller"/>
        <!-- 使SpringMVC不处理静态资源,例如:.css .js .html .mp3。过滤这些资源,也就是使用url访问这些资源的时候不会被DispatcherServlet捕获 -->
        <mvc:default-servlet-handler/>
        
        <!-- 原来需要配置处理映射器、适配器,现在只需要一个注解驱动即可;写上这个spring就会自动帮我们开启两个器,并且自动注入到spring容器中 -->
    	<mvc:annotation-driven/>
    
        <!--视图解析器:DispatcherServlet给他的ModelAndView-->
        <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="InternalResourceViewResolver">
            <!--前缀-->
            <property name="prefix" value="/WEB-INF/"/>
            <!--后缀-->
            <property name="suffix" value=".jsp"/>
        </bean>
    
        <!-- 不需要写请求控制器连接的handler了,在注解中写 -->
    </beans>
    

    扫描到包后,包中的注解会生效。遇到@Controller注解时,会自动将控制器注册到spring容器中。@RequestMapping("/hello")就是那个映射请求与Controller的bean,自动注入进入!

  3. 写Controller

    // 声明HelloSpringMvc是一个Controller,而不用implements了
    @Controller
    public class HelloSpringMvc {
          
          
        
        // 请求与Controller映射,相当于原来那个请求控制器连接bean;这也是将这个方法作为请求控制器连接bean注册到spring容器中
        // 每一个@RequestMapping就对应一个handlerBean
        @RequestMapping("/hello")
        public String hello(Model model){
          
          
            // 封装数据使用model进行封装,在跳转的时候model跟着一起转发
            model.addAttribute("msg", "HelloSpringMVC");
    
            // 这个return会被视图解析器处理,自动跳转到视图;与原来使用mv是相同的。
            return "hello";
        }
        
        @RequestMapping("/hello2")
        public String hello(Model model){
          
          
            model.addAttribute("msg", "HelloSpringMVC");
            return "hello2";
        }
        
        @RequestMapping("/hello3")
        public String hello(Model model){
          
          
            model.addAttribute("msg", "HelloSpringMVC");
            return "hello";
        }
        
    }
    

    原来一个业务需要多种情况的时候,需要每个情况对应一个页面一个Controller(每个Controller中只有一个handler)。但是使用这种方法可以将同种业务的handler放在一起,一个Controller中。

增加层级访问路径

@RequestMapping

// 声明HelloSpringMvc是一个Controller,而不用implements了
@Controller
@RequestMapping("/hello")
public class HelloSpringMvc {
    
     
    
    @RequestMapping("/h1")
    public String hello(Model model){
    
    
        model.addAttribute("msg", "HelloSpringMVC");
        return "hello";
    }
   
}

@RequestMapping可以在方法上写,也可以在类上写。类上写就表明这是一个父路径,在方法上写就表明这是一个子路径

也就是说,现在访问hello方法(handler),需要url写成:xxx/hello/h1。才能访问到这个handler

从servlet容器中先找到Controller(/hello),在从Controller中找到对应的handler(/h1)。原来因为一个Controller中只有一个handler所以不需要写第二路径,直接访问Controller就可以使用handler,现在多了一个需要先到父路径在到handler。

定义访问方式权限,确保安全性

@RequestMapping可以修改访问handler的方式(POST、DELETE、PUT、GET)。

如果说不想让用户访问登录的handler(登录的handler需要用户名密码参数)

@Controller
@RequestMapping("/hello")
public class HelloSpringMvc {
    
     
    
    @RequestMapping("/h1", method=RequestMethod.POST)
    public String hello(String id, String password, Model model){
    
    
        model.addAttribute("msg", "HelloSpringMVC"+c);
        return "hello";
    }
   
}
这样使用这种uri就不能访问了:
http://localhost:8080/hello/h1?id=123&password=123456

因为这样的uri是GET方式的,而我们限制的handler需要是POST方式才可以访问!

注意:POST方式可以带参数,但是POST方式uri中不能携带参数,只能通过表单发送。因为POST方式的参数是隐藏的。

RestFul风格

以前在url中携带参数使用?参数=xxx寻找资源,使用RestFul风格后使用 /资源 即可找到资源。

RestFul就是一个资源定位以及资源操作的风格,不是一种协议、标准,仅仅只是一种风格!

作用:RestFul的最大的作用是安全,因为你不能知道那个参数的含义是什么!

功能:

  • 资源:互联网所有的事务都可以被抽象为资源

  • 资源操作:使用POST、DELETE、PUT、GET,使用不同的方法对资源进行操作。

    分别对应: 添加、删除、修改、查询

@PathVariable

在SpringMVC中使用 @PathVariable 注解,让方法参数的值对应绑定到URI模板变量上。

例如:

@Controller
@RequestMapping("/hello")
public class HelloSpringMvc {
    
     
    
    // 在请求上改动,使得uri可以是这种风格的
    @RequestMapping("/h2/{a}/{b}")
    public String sayHello(@PathVariable int a,@PathVariable int b, Model model){
    
    
        int c = a + b;
        model.addAttribute("msg", "HelloSpringMVC"+c);

        return "hello2";
    }
   
}

这样可以这样使用:

uri = http://localhost:8080/hello/h2/1/2
结果为:HelloSpringMVC3

传统的uri = http://localhost:8080/hello/h2?a=1&b=2

这样使用就可以切换风格了。原来是链接式风格、现在是请求式风格。

注意!使用这种风格需要两点:

  • 修改请求映射
  • 添加注解 @PathVariable

接受请求 与 请求转发与重定向

接收请求

DispatcherServlet中有一个方法是doService,请求到DispatcherServlet中先去找doService,在从doService中判断寻找请求要找的handler!

所以我们写的handler可以有HttpServletRequest、HttpServletResponse!(你只要写上这个参数这是可以接收的)

@Controller
@RequestMapping("/hello")
public class HelloSpringMvc {
    
    
    @RequestMapping("/h3")
    public void test(HttpServletRequest req, HttpServletResponse rsp){
    
    
        String name = req.getParameter("name");
        int age = (Integer) req.getAttribute("age");

        try {
    
    
            req.getRequestDispatcher("/index.jsp").forward(req, rsp);
        } catch (ServletException e) {
    
    
            e.printStackTrace();
        } catch (IOException e) {
    
    
            e.printStackTrace();
        }
    }
}

注意一点,这种请求转发并不太好,你可以使用之前跳转视图的方法return进行转发(在Model中携带数据)。

请求转发与重定向

请求转发(可访问WEB-INF)

@Controller
@RequestMapping("/hello")
public class HelloSpringMvc {
    
    
    @RequestMapping("/h3")
    public String test(HttpServletRequest req, HttpServletResponse rsp){
    
    
        return "hello";
    }
}

这种直接文件名的方式是请求转发的方式,注意要String!

重定向(不可访问WEB-INF)

@Controller
@RequestMapping("/hello")
public class HelloSpringMvc {
    
    
    @RequestMapping("/h3")
    public String test(HttpServletRequest req, HttpServletResponse rsp){
    
    
        return "redirect:/index.jsp";
    }
}

注意!这里是要加jsp后缀的,并且重定向不能访问WEB-INF下的文件!

因为WEB-INF下的文件只能由服务端级别才能访问,客户端级别访问不了!,而重定向发生了两次请求第二次请求是真正请求的(由客户端发出请求)所以重定向访问不了WEB-INF下的文件!

Handler接收Param参数

如果你喜欢用 RestFull风格、或者使用request 接收参数的话就不用看下面的了,这里的接收参数是对于url栏中参数而言的

最好还是用request接收一下呗,又不费劲

直接接收参数Param

@Controller
@RequestMapping("/hello")
public class HelloSpringMvc {
    
    
    @RequestMapping("/h1")
    public String test(String name){
    
    
        System.out.println(name);
        return "redirect:/index.jsp";
    }
}

这样直接使用url:http://localhost:8080/hello/h1?name=xxx 就可以访问

URL栏参数名与handler中参数名不一致

如果url中的域名的携带参数与handler中的参数不一致,可以使用名称映射注解。

@Controller
@RequestMapping("/hello")
public class HelloSpringMvc {
    
    
    @RequestMapping("/h1")
    public String test(@RequestParam("username") String name){
    
    
        System.out.println(name);
        return "redirect:/index.jsp";
    }
}

这样url可以这样写:http://localhost:8080/hello/h1?username=xxx

接收一个对象

直接将参数封装成一个对象,使用对象作为参数即可

class User{
    
    
    private int age;
    private String name;
}

@Controller
@RequestMapping("/hello")
public class HelloSpringMvc {
    
    
    @RequestMapping("/h1")
    public String test(User user){
    
    
        System.out.println(user.toString());
        return "redirect:/index.jsp";
    }
}

这样url可以这样写:http://localhost:8080/hello/h1?id=1&name=xxx

传递参数给前端

  • 就直接使用model传递参数给前端!
  • 就直接使用ModelAndView传递参数给前端!
  • 使用注解@ResponseBody屏蔽视图解析器,并将return值放在response中返回给前端
  • 使用ModelMap传递参数给前端

ModelMap是Model的一个父类,它继承自LinkedHashMap(拥有LinkedHashMap的全部方法)。Model是ModelMap的精简版本,大部分情况用Model就够了!

前两种一样的用法,return都是经过视图解析器的

屏蔽handler的视图解析器return数据给前端(@ResponseBody)

用法:在handler上用==@ResponseBody==屏蔽该handler的视图解析器作用。

那么return的值就不会经过视图解析器解析,而是将return值放在response中return给前端。

@Controller
@RequestMapping("book")
public class BookController {
    
    
    @Autowired
    @Qualifier("bookServiceImpl") 
    private BookService bookService;

    @RequestMapping("/allBook")
    public String queryList(Model model){
    
    
        List<Books> list = bookService.queryAllBook();
        model.addAttribute("allBooks", list);
        return "allBook";
    }

    @ResponseBody
    @RequestMapping("/test")
    public String test(){
    
    
        return "allBook";
    }
}

这样访问 /book/test 就是向response域中添加字符串 allBook 而不是转发到 allBook.jsp

但是访问 book/allBook 仍会经过视图解析器然后转发!

注意 @ResponseBody 屏蔽掉的是一个handler的视图解析器,而不是整个Controller的视图解析器,所以没写注解的handler仍可以经过视图解析器!

屏蔽整个Controller的视图解析器return数据给前端(@RestController)

使用 @RestController = @Controller + @ResponseBody

@RestController
@RequestMapping("book")
public class BookController {
    
    
    @Autowired
    @Qualifier("bookServiceImpl") 
    private BookService bookService;

    @RequestMapping("/allBook")
    public String queryList(Model model){
    
    
        List<Books> list = bookService.queryAllBook();
        model.addAttribute("allBooks", list);
        return "allBook";
    }

    @RequestMapping("/test")
    public String test(){
    
    
        return "allBook";
    }
}

或者使用 @ResponseBody + @Controller

@Controller
@ResponseBody
@RequestMapping("book")
public class BookController {
    
    
    @Autowired
    @Qualifier("bookServiceImpl") 
    private BookService bookService;

    @RequestMapping("/allBook")
    public String queryList(Model model){
    
    
        List<Books> list = bookService.queryAllBook();
        model.addAttribute("allBooks", list);
        return "allBook";
    }

    @RequestMapping("/test")
    public String test(){
    
    
        return "allBook";
    }
}

解决乱码问题

原始方法

在原来纯servlet中乱码可以使用request的setCharacterEncoding解决。但是在Spring中已经不知道封装了多少次了,在封装中就已经乱码了。所以我们在handler中使用request来解决乱码是不可以的!

这样我们只能必须配置一个过滤器来解决乱码了!!!

public class Filter implements javax.servlet.Filter {
    
    
    public void init(FilterConfig filterConfig) throws ServletException {
    
    

    }

    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
    
    
        servletRequest.setCharacterEncoding("utf-8");
        servletResponse.setCharacterEncoding("utf-8");
        
        filterChain.doFilter(servletRequest, servletResponse);
    }

    public void destroy() {
    
    

    }
}

在web.xml中配置一下过滤器

<filter>
    <filter-name>filter</filter-name>
    <filter-class>com.qiu.filter.Filter</filter-class>
</filter>

<filter-mapping>
    <filter-name>filter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

*注意这里必须要是“/*”,只有“/ ”才能拦截jsp。

SpringMVCfangfa

SpringMVC为我们提供了过滤器,直接在web.xml中使用就行了!

<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>

不需要我们手动写Filter了。

猜你喜欢

转载自blog.csdn.net/qq_43477218/article/details/114263368