SpringMVC讲解

97 阅读9分钟

数据结构与算法之美 下栽: www.sanzhishu.top/655.html


SpringMVC

Spring集成web环境

集成步骤

  1. 导入相关的坐标,spring的和web的

      org.springframework
      spring-context
      5.3.6

      mysql
      mysql-connector-java
      5.1.32

      c3p0
      c3p0
      0.9.1.2

      cn.6tail
      nlf-mini-plugin-druid
      1.0.0

      junit
      junit
      4.12
      test

      org.springframework
      spring-test
      5.3.6

      org.junit.jupiter
      junit-jupiter
      RELEASE
      compile

      junit
      junit
      RELEASE
      compile

      javax.servlet
      javax.servlet-api
      4.0.1

      javax.servlet.jsp
      javax.servlet.jsp-api
      2.3.3

  1. spring相关配置
  2. 添加一个web包,用来写javaweb
  3. 在web.xml配置相关类
  4. 配置tomcat,部署项目运行

ApplicationContext应用上下文的获取方式

之前每次我们都是通过new的方式创建的应用上下文,这样的弊端是在大项目中配置文件会加载多次,应用上下文被创建多次,繁琐且不节省资源

所以我们运用监听器来只创建一次,所有的用这一个容器,所以:

创建一个实现ServletContext监听器的类:

public class ContextLoader implements ServletContextListener {
    @Override
    public void contextInitialized(ServletContextEvent sce) {
        ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
        //将这个应用上下文对象存储在servletContext域中
        ServletContext servletContext = sce.getServletContext();
        servletContext.setAttribute("app",app);
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
    }
}

web层中:

    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext servletContext = req.getServletContext();
        ApplicationContext app = (ApplicationContext) servletContext.getAttribute("app");
        UserService userService= app.getBean(UserService.class);
        userService.save();
    }

web.xml:


  com.myspring.listener.ContextLoader

    contextConfigLocation
    classpath:applicationContext.xml

Spring提供的获得应用上下文的工具

没错,上面又白写了。。。

上面的不用手动实现。Spring提供了一个监听器ContextLoaderListener就是对该功能的封装

我们只需要做两件事:

  1. 在web.xml中配置ContextLoaderListener监听器(需要先导入spring-web坐标) pom.xml:

      org.springframework
      spring-web
      5.3.6

web.xml:


  org.springframework.web.context.ContextLoaderListener

  1. 通过WebApplicationCintextUtils(一个客户端工具)获得应用上下文对象ApplicationContext web层中:
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

    ServletContext servletContext = req.getServletContext();
//关键
    WebApplicationContext app = WebApplicationContextUtils.getWebApplicationContext(servletContext);
    UserService userService= app.getBean(UserService.class);
    userService.save();
}

SpringMVC简介

  • SpringMVC 是一种基于 Java 的实现 MVC 设计模型的请求驱动类型的轻量级 Web 框架,属于SpringFrameWork的后续产品,已经融合在 Spring Web Flow 中。 SpringMVC已经成为目前最主流的MVC框架之一。
  • SpringMVC的作用:作为前端控制器,控制请求的共有行为,在传统的JavaEE技术中,只使用Servlet作为控制器,当每个功能都需要一个servlet程序相似功能也无法分开封装,另外,传统的开发模式也存在其它使用不便利的做法。 SpringMVC解决了V-C交互的问题,即V(View:视图)和C(Controller:控制器)之间的交互问题,具体表现在:用户可以通过视图将请求数据提交给服务器端的控制器,而控制器可以接收到相关数据后进行处理,最终,给予客户端某个视图,使得客户端得到响应结果。当然springMVC作为控制器还是需要servlet

SpringMVC开发步骤

  1. 导入SpringMVC

      org.springframework
      spring-webmvc
      5.3.6

  1. 配置servlet在web.xml

    DispatcherServlet
    org.springframework.web.servlet.DispatcherServlet

      contextConfigLocation
      classpath:spring-mvc.xml

    DispatcherServlet

    /

  1. 编写pojo(controller)
  2. 将controller使用注解(@Controller)配置到Spring容器中
//表明是一个控制类bean实例
@Controller
public class UserController {
    //地址映射,当跳转/quick,访问此方法
    @RequestMapping("/quick")
    public  String save(){
        System.out.println("Controller save running");
//        要跳转的视图
        return "success.jsp";
    }
}
  1. 配置组件扫描(配置到Spring-mvc.xml:springmvc的配置文件,需要自己在resources创建)
  1. 发送请求测试

流程:

SpringMVC的组件解析

SpringMVC内部执行流程

SpringMVC注解解析

@RequestMapping(""):地址映射

常用参数:value:就是路径

​ method:可以指定请求方式。值为枚举方式在RequestMethod

​ params:指定请求参数条件,例如:

@Controller
@RequestMapping("/user")
public class UserController {
    //当地址为localhost:8080/user/quick时访问该方法
    @RequestMapping("/quick")
    public  String save(){
        System.out.println("Controller save running");
### SpringMVC配置解析

在上面的代码中,最后我们renturn了jsp页面

```java
return "success.jsp";
//实际上本句为
return "forword:success.jsp";
//forword在本处意思为转发(不改变url地址访问资源),默认为forword
return "redirect:/success.jsp"
//redirect:代表重定向

我们还可以在springmvc中配置视图解析器,来避免写前缀后缀


这样一来我们可以这样写:
return "/success"
代表:/jsp/success.jsp

总结:

SpringMVC的数据响应

SpringMVC的数据响应方式:

  1. 页面跳转
  • 直接返回字符串
  • 通过ModelAndView对象返回
  1. 回写数据
  • 直接返回字符串
  • 返回对象或集合

页面跳转

  1. 直接返回字符串:此种方式会将返回的字符串与视图解析器的前后缀拼接后跳转:不多说,上面例子就是用的这种
  2. 通过ModelAndView对象返回
    @RequestMapping("/quick2")
    public ModelAndView save2(){
        ModelAndView modelAndView = new ModelAndView();
//        设置模型数据:可以在jsp中通过el表达式获得
      modelAndView.addObject("username","lihua");
//        设置视图名称
        modelAndView.setViewName("index.jsp");
        return modelAndView;
    }

//这种也可以,和上面一样只不过是springmvc为你注入了一个bean实例
    @RequestMapping("/quick2")
    public ModelAndView save2(ModelAndView modelAndView){
//        设置模型数据
        modelAndView.addObject("username","lihua");
//        设置视图名称
        modelAndView.setViewName("index");
        return modelAndView;
    }

​ 返回字符串的形式也可以传递参数:

    @RequestMapping("/quick")
    public  String save(Model model){
        model.addAttribute("username","lihua");
//        要跳转的视图
        return "success";
    }

//另外代替Model,还可以传HttpServletRequest等作为参数

​ 在index.jsp中


这个isELIgnored="false"表示el表达式可用

Hello World!${username}

回写数据

  1. 直接返回字符串 在web阶段我们需要回写字符串直接response.getWriter().print("hello world"),在Controller直接通过参数注入response对象,但是还有更加简单的方法:返回字符串
@RequestMapping("/quick")
//告知springmvc返回的用于回写数据的字符串,不要进行页面跳转
@ResponseBody
public  String save(HttpServletResponse response){
    return "helloworld";
}
  1. 返回对象或集合 当我们需要传递一个对象或者集合时,可以先转成json格式字符串再return
    @RequestMapping("/quick")
//    还是要写这个注解,因为还是返回的字符串数据
    @ResponseBody
    public  String save(HttpServletResponse response) throws IOException {
        UserServiceImpl userService = new UserServiceImpl();
        userService.setAge(10);
        userService.setName("lihua");
//        使用json转换工具将对象转换为json格式字符串再返回
        ObjectMapper objectMapper = new ObjectMapper();
        String string = objectMapper.writeValueAsString(userService);
        return string;

需要导入的json转换工具坐标:


      com.fasterxml.jackson.core
      jackson-core
      2.11.4

      com.fasterxml.jackson.core
      jackson-databind
      2.11.4

      com.fasterxml.jackson.core
      jackson-annotations
      2.11.4

​ springmvc不需要我们自己来转json字符串,有更加简便的方式:

​ 返回对象和集合。

​ 首先需要我们在spring配置文件中进行一些配置(配置处理器映射器):

​ 控制类中:

    @RequestMapping("/quick")
//    还是要写这个注解,因为还是返回的字符串数据
    @ResponseBody
    public UserServiceImpl save(HttpServletResponse response) throws IOException {
        UserServiceImpl userService = new UserServiceImpl();
        userService.setAge(10);
        userService.setName("lihua");
        return userService;
    }

配置太麻烦了,可以通过mvc的注解驱动代替上述配置,没错,又又又有更加简便的操作:

在springmvc的配置文件中:

<!--        mvc注解驱动-->
        <mvc:annotation-driven>

注意:注解驱动对应的命名空间必须是
xmlns:mvc="http://www.springframework.org/schema/mvc"
其他两个不行
</mvc:annotation-driven>

SpringMVC获取请求数据

获取请求参数

  1. 获取基本类型参数:直接通过参数获得:
@RequestMapping("/quick")
@ResponseBody
public void save(String username,int age) throws IOException {
    System.out.println(username);
    System.out.println(age);
}

url: 结果: 2. 获得pojo类型参数:pojo参数的属性名和请求参数的name一致,参数值会自动映射匹配

@Controller
public class UserController {
    private int age;
    private String name;
//    还需要getter和setter

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @RequestMapping("/quick")
    @ResponseBody
    public void save(UserController userController) throws IOException {
        System.out.println(userController.getAge());
        System.out.println(userController.getName());
    }

}

输入与结果:

  1. 获得数组类型参数:和基本数据类型完全一致,函数参数和请求的参数一致就可以

  1. 获得集合类型参数:需要被包装到一个pojo类中才可以
public class VO {
    public List getStringList() {
        return stringList;
    }

    public void setStringList(List stringList) {
        this.stringList = stringList;
    }

    private List stringList;
}
@RequestMapping("/quick")
@ResponseBody
public void save(VO vo) throws IOException {
    System.out.println(vo.getStringList());
}

当请求为Ajax可以通过指定contenttype为json格式,通过注解直接获取集合数据:

ajax:

@RequestMapping("/quick")
@ResponseBody
public void save(@RequestBody List userList) throws IOException {
    System.out.println(userList);
}

开放静态资源;

无法访问的js文件等静态资源是配置

这样也可以:在springmvc找不到资源是交给tomcat处理

解决低版本tomcat请求数据为中文乱码问题

如果tomcat版本较低,当配置post请求时,数据为中文会出现乱码,所以我们通过配置过滤器来解决


  CharacterEncodingFilter
  org.springframework.web.filter.CharacterEncodingFilter

    encoding
    UTF-8

  CharacterEncodingFilter
  /*

参数绑定注解@requestParam

当请求的参数名称和controller方法参数不一致时,就需要通过@requestParam注解显示

@RequestMapping("/quick")
@ResponseBody
//当我在url中输入的是name
public void save(@RequestParam("name") String username) throws IOException {
    System.out.println(username);
}

@requestParam注解的参数:

获得Restful风格的参数

Restful是一种软件架构风格、设计风格,而不是标准,只是提供一组设计原则和约束条件。主要用于客户端和服务器交互类的软件,基于这个风格设计的软件可以更加简洁,更有层次等

HTTP协议中四个表示操作方式的动词:

具体实例:

自定义类型转换器

SpringMVC实际上已经具备了一些常用的类型转换器,例如客户端提交的字符串被转换成int型进行参数设置

但是可能并不完全满足我们的需求,所以我可以自定义类型转换器: 开发步骤:

  1. 定义转换器实现Converter接口
public class DataConverter implements Converter {
    public Date convert(String dateStr) {
        //将日期字符串转换为日期对象
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        Date date = null;
        try {
            date = format.parse(dateStr);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return date;
    }
}
  1. 在配置文件中声明转换器
  1. 在中引用转换器

结果:

获得Servlet的相关API

前面说过,直接在相关方法参数位置注入,就不在赘述

获取请求头

  1. 使用@RequestHeader
    @RequestMapping("/quick")
    @ResponseBody
//    将请求头的user-agent一行赋值给参数
    public void save(@RequestHeader(value = "User-Agent") String userAgent) throws IOException {
        System.out.println(userAgent);
    }
  1. @CookieValue获得Cookie的值:
    @RequestMapping("/quick")
    @ResponseBody
//    通过cookie的id获得cookie的值
    public void save(@CookieValue(value = "JSESSIONID") String cookie) throws IOException {
        System.out.println(cookie);
    }

文件上传

文件上传客户端要求:

单文件上传步骤:

  1. 导入fileupload和io坐标

      commons-fileupload
      commons-fileupload
      1.3.1

      commons-io
      commons-io
      2.5

  1. 配置文件上传解析器
  1. 编写文件上传代码
    @RequestMapping("/quick")
    @ResponseBody
    //参数名必须与上传文件表单的各项name相同
    public void save(String username, MultipartFile uploadFile) throws IOException {
//        获得文件名称
        String originalFilename = uploadFile.getOriginalFilename();
//        保存文件到
        uploadFile.transferTo(new File("D:\\"+originalFilename));

多文件上传同理:

    @RequestMapping("/quick")
    @ResponseBody
    //参数名必须与上传文件表单的各项name相同
    public void save(String username, MultipartFile uploadFile1,MultipartFile uploadFile2) throws IOException {
//        获得文件名称
        String originalFilename = uploadFile1.getOriginalFilename();

        String originalFilename2 = uploadFile2.getOriginalFilename();
//        保存文件到
        uploadFile2.transferTo(new File("D:\\"+originalFilename));
        uploadFile1.transferTo(new File("D:\\"+originalFilename));
    }

当然也可以把参数换成一个数组

关注夏壹分享发送:资源 获取深入讲解JVM虚拟机课程