您当前的位置: 首页 >  Java

彭世瑜

暂无认证

  • 2浏览

    0关注

    2791博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

Java学习路线-64:SpringMVC

彭世瑜 发布时间:2020-06-22 21:04:40 ,浏览量:2

1、MVC 框架作用:

  1. 将 url 映射到 java 类或 java 类的方法
  2. 封装用户提交的数据
  3. 处理请求-调用相关的业务处理-封装响应数据
  4. 将响应的数据进行渲染 jsp,html,freemaker 等

2、Spring MVC 是一个轻量级的基于响应的 MVC 框架

3、Spring MVC 优势

  1. 性能比 Struts2 好
  2. 简单,便捷,易学
  3. 和 Spring 无缝集成(使用 spring ioc, aop)
  4. 使用约定优先于配置
  5. 能够进行简单 junit 测试
  6. 支持 Restful 风格
  7. 异常处理
  8. 本地化,国际化
  9. 数据验证,类型转换
  10. 拦截器
  11. 使用的公司多

4、结构

在这里插入图片描述

spring-beans spring-context spring-core spring-web spring-webmvc commons-logging

项目目录

.
├── pom.xml
└── src
    ├── main
    │   ├── java
    │   │   └── com
    │   │       └── pengshiyu
    │   │           └── controller
    │   │               └── HelloController.java
    │   ├── resources
    │   │   └── springmvc-servlet.xml
    │   └── webapp
    │       ├── WEB-INF
    │       │   ├── jsp
    │       │   │   └── hello.jsp
    │       │   └── web.xml
    │       └── index.html
    └── test
        └── java
配置文件

pom.xml



    4.0.0

    org.example
    spring-mvc-demo
    1.0-SNAPSHOT

    

        
            
            
                org.apache.tomcat.maven
                tomcat7-maven-plugin
                2.2
                
                    8080
                    /
                    UTF-8
                    
                    true
                    src/main/webapp/WEB-INF/web.xml
                    true
                
            

        
    

    
        
        
            org.springframework
            spring-core
            5.2.6.RELEASE
        
        
        
            org.springframework
            spring-beans
            5.2.6.RELEASE
        
        
        
            org.springframework
            spring-context
            5.2.6.RELEASE
        
        
        
            org.springframework
            spring-web
            5.2.6.RELEASE
        
        
        
            org.springframework
            spring-webmvc
            5.2.6.RELEASE
        

        
        
            org.springframework
            spring-aop
            5.2.6.RELEASE
        

        
        
            org.springframework
            spring-expression
            5.2.6.RELEASE
        


        
        
            commons-logging
            commons-logging
            1.2
        

        
            javax.servlet
            javax.servlet-api
            4.0.1
            provided
        

        
            jstl
            jstl
            1.2
        
    

src/main/webapp/WEB-INF/web.xml





    
    
        springmvc
        org.springframework.web.servlet.DispatcherServlet

        
        
            contextConfigLocation
            classpath:springmvc-servlet.xml
        

        
        1
    

    
        springmvc
        
        /
    


src/main/resources/springmvc-servlet.xml





    
    
        
        
        
        
        
    

    
    



控制器

src/main/java/com/pengshiyu/controller/HelloController.java

package com.pengshiyu.controller;

import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class HelloController implements Controller {
    public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
        // 封装要显示的数据
        ModelAndView modelAndView = new ModelAndView();

        modelAndView.addObject("name", "Tom");
        modelAndView.addObject("age", 25);

        // 视图名
        modelAndView.setViewName("hello");
        return modelAndView;
    }
}

视图文件

src/main/webapp/WEB-INF/jsp/hello.jsp



${name}
${age}
访问测试
GET http://localhost:8080/hello

Tom 25
Spring-MVC 注解开发

修改配置文件

src/main/resources/springmvc-servlet.xml





    
    
        
        
        
        
        
    

    


    
    



修改 Controller

package com.pengshiyu.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Controller
public class HelloController  {
    @RequestMapping("/hello")
    public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
        // 封装要显示的数据
        ModelAndView modelAndView = new ModelAndView();

        modelAndView.addObject("name", "Tom");
        modelAndView.addObject("age", 24);

        // 视图名
        modelAndView.setViewName("hello");
        return modelAndView;
    }
}

配置总结

1、通过 url 对应 bean

适用于小型的应用系统





2、为 url 分配 bean


    
        
            
            helloController
        
    



3、注解



Controller 配置对应的注解

结果跳转方式

1、返回 ModelAndView 对象

根据 view 的名称和视图解析器,会跳转到指定的页面

页面:视图解析器的前缀+ view name + 视图解析器的后缀

springmvc-servlet.xml





    
    
        
        
        
        
        
    

    




package com.pengshiyu.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Controller
public class HelloController {
    @RequestMapping("/hello")
    public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response)
            throws Exception {
        // 封装要显示的数据
        ModelAndView modelAndView = new ModelAndView();

        modelAndView.addObject("name", "Tom");
        // 相当于:
        // request.setAttribute("name", "Tom");

        modelAndView.setViewName("hello");
        // WEB-INF/jsp/hello.jsp

        // 类似转发
        return modelAndView;
    }
}

2、返回字符串

不需要视图解析器

springmvc-servlet.xml





    




package com.pengshiyu.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Controller
public class HelloController {
    @RequestMapping("/hello")
    public void handleRequest(HttpServletRequest request, HttpServletResponse response)
            throws Exception {
        response.getWriter().println("hello");
    }
}

3、重定向(地址改变)

package com.pengshiyu.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Controller
public class HelloController {
    @RequestMapping("/hello")
    public void handleRequest(HttpServletRequest request, HttpServletResponse response)
            throws Exception {
        response.sendRedirect("index.jsp");
    }
}

或者

package com.pengshiyu.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Controller
public class HelloController {
    @RequestMapping("/hello")
    public String handleRequest(HttpServletRequest request, HttpServletResponse response)
            throws Exception {
        // 不需要视图解析
        return "redirect:index.jsp";
    }
}

4、转发(地址不变)

package com.pengshiyu.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Controller
public class HelloController {
    @RequestMapping("/hello")
    public void handleRequest(HttpServletRequest request, HttpServletResponse response)
            throws Exception {

        request.setAttribute("name", "Tom");
        request.getRequestDispatcher("index.jsp").forward(request, response);
    }
}

或者

package com.pengshiyu.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Controller
public class HelloController {
    @RequestMapping("/hello")
    public String handleRequest(HttpServletRequest request, HttpServletResponse response)
            throws Exception {
        return "hello";
    }
}

或者

package com.pengshiyu.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Controller
public class HelloController {
    @RequestMapping("/hello")
    public String handleRequest(HttpServletRequest request, HttpServletResponse response)
            throws Exception {
        return "forward:index.jsp";
    }
}

数据处理

1、提交数据

package com.pengshiyu.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class HelloController {
    @RequestMapping("/hello")
    public String handleRequest(String name){
        System.out.println(name);
        return "index.jsp";
    }
}

GET http://localhost:8080/hello
null

GET http://localhost:8080/hello?name=Tom
Tom

2、指定参数名

package com.pengshiyu.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

@Controller
public class HelloController {
    @RequestMapping("/hello")
    public String handleRequest(@RequestParam("uname") String name){
        System.out.println(name);
        return "index.jsp";
    }
}

GET http://localhost:8080/hello?uname=Tom
Tom

3、提交对象

实体类

package com.pengshiyu.bean;

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

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

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

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

package com.pengshiyu.controller;

import com.pengshiyu.bean.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class HelloController {
    @RequestMapping("/user")
    public String user(User user){
        System.out.println(user);
        return "index.jsp";
    }
}

GET http://localhost:8080/user?name=Tom&age=23
User{name='Tom', age=23}
将数据显示到 UI 层

1、通过 ModelAndView 需要视图解析器

package com.pengshiyu.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Controller
public class HelloController {
    @RequestMapping("/hello")
    public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response)
            throws Exception {
        // 封装要显示的数据
        ModelAndView modelAndView = new ModelAndView();

        modelAndView.addObject("name", "Tom");
        // 相当于:
        // request.setAttribute("name", "Tom");

        modelAndView.setViewName("hello");
        // WEB-INF/jsp/hello.jsp

        // 类似转发
        return modelAndView;
    }
}

2、通过 ModelMap 不需要视图解析器

package com.pengshiyu.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class HelloController {
    @RequestMapping("/user")
    public String user(String name, ModelMap modelMap){
        System.out.println(name);
        modelMap.addAttribute("name", name);
        return "index.jsp";
    }
}

区别:ModelAndView ModelMap

相同点:

  1. 都可以将数据封装显示到表示层页面

不同点:

  1. ModelAndView 可以指定跳转的视图,而 ModelMap 不能
  2. ModelAndView 需要视图解析器,而 ModelMap 不需要配置
乱码和 Restful

通过过滤器解决 web.xml



    CharacterEncodingFilter
    org.springframework.web.filter.CharacterEncodingFilter
    
        encoding
        utf-8
    



    CharacterEncodingFilter
    /*

2、Restful

package com.pengshiyu.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class HelloController {
    @RequestMapping("/user/{id}")
    public String user(@PathVariable int id, ModelMap modelMap){
        System.out.println(id);
        modelMap.addAttribute("name", id);
        return "/index.jsp";
    }
}

GET http://localhost:8080/user/123

123

3、通过参数访问处理方法

package com.pengshiyu.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
@RequestMapping("/user")
public class HelloController {
     // /user?method=add
    @RequestMapping(params = {"method=add"}, method = RequestMethod.GET)
    public String add(ModelMap modelMap){
        modelMap.addAttribute("name", "add");
        return "/index.jsp";
    }

    // /user?method=delete
    @RequestMapping(params = {"method=delete"}, method = RequestMethod.GET)
    public String delete(ModelMap modelMap){
        modelMap.addAttribute("name", "delete");
        return "/index.jsp";
    }
}

文件上传

依赖 commons-io commons-fileupload

pom.xml



    commons-io
    commons-io
    2.7




    commons-fileupload
    commons-fileupload
    1.4

配置文件

src/main/resources/springmvc-servlet.xml


        
        
        
    

src/main/java/com/pengshiyu/controller/HelloController.java

package com.pengshiyu.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.commons.CommonsMultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.*;

@Controller
public class HelloController {

    @RequestMapping(value = "/upload", method = RequestMethod.GET)
    public String upload(){
        return "/template/upload.jsp";
    }

    @RequestMapping(value = "/upload", method = RequestMethod.POST)
    public String upload(@RequestParam("file")  CommonsMultipartFile file, HttpServletRequest request) throws IOException {
        String path = request.getRealPath("/uploads");
        InputStream is = file.getInputStream();

        System.out.println(file.getOriginalFilename());

        OutputStream os = new FileOutputStream(new File(path, file.getOriginalFilename()));

        int len = 0;
        byte[] buffer = new byte[400];

        while ((len = is.read(buffer)) != -1){
            os.write(buffer, 0, len);
        }

        is.close();;
        os.close();

        return "/index.jsp";
    }

}

src/main/webapp/template/upload.jsp


  
  

Ajax 和 JSON

1、Ajax

为了直接获取 html 文件,将配置文件匹配规则修改如下


    springmvc
    
    *.do

package com.pengshiyu.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Controller
public class HelloController {

    @RequestMapping(value = "/ajax")
    public void ajax(String name, HttpServletResponse response) throws IOException {
        System.out.println(name);
        response.getWriter().println("ok");
    }
}






  $(function () {
    $("#name").blur(function () {
      $.post(
        "/ajax.do",
        {
          name: $("#name").val(),
        },
        function (res) {
          alert(res);
        }
      );
    });
  });

2、JSON jackson-annotations jackson-core jackson-databind




    com.fasterxml.jackson.core
    jackson-annotations
    2.11.0



    com.fasterxml.jackson.core
    jackson-databind
    2.11.0



    com.fasterxml.jackson.core
    jackson-core
    2.11.0


配置 JSON 转换器





    
    
        
            
                text/plain;charset=UTF-8
            
        
    

    

    
    
        
            
                
                
            
        
    

    




package com.pengshiyu.controller;

import com.pengshiyu.bean.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

@Controller
public class HelloController {

    @RequestMapping("/json")
    @ResponseBody
    public List ajax() throws IOException {
        List users = new ArrayList();
        users.add(new User("Tom", 23));
        users.add(new User("Jack", 24));
        return users;
    }
}

拦截器

interceptor 1、实现 HandlerInterceptor 接口 DispatcherServlet

package com.pengshiyu.interceptor;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class MyInterceptor implements HandlerInterceptor {
    // 在请求处理的方法执行之前执行,
    // 返回true执行下一个拦截器,
    // 返回false不执行下一个拦截器
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("preHandle");
        return true;
    }

    // 在处理方法执行之后执行
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("postHandle");
    }

    // 在DispatcherServlet 之后执行 清理工作
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("afterCompletion");
    }
}

2、配置拦截器





    

    
    
        
            
            
            
        
    

3、执行顺序

package com.pengshiyu.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Controller
public class HelloController {

    @RequestMapping("/echo")
    public void echo(HttpServletResponse response) throws IOException {
        System.out.println("echo");
        response.getWriter().println("echo");
    }
}

preHandle
echo
postHandle
afterCompletion
登录拦截器实现

配置



    
        
        
        
            
                
                    login.do
                
            
        
    

拦截器

package com.pengshiyu.interceptor;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;

public class MyInterceptor implements HandlerInterceptor {


    private List allowedUrls;

    // 在请求处理的方法执行之前执行,
    // 返回true执行下一个拦截器,
    // 返回false不执行下一个拦截器
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("preHandle");
        // 解决中文打印乱码输出
        response.setContentType("text/html;charset=utf-8");

        // 判断session
        Object user = request.getSession().getAttribute("user");
        if(user != null){
            return true;
        }

        // 判断放行路径
        String url = request.getRequestURL().toString();
        System.out.println(url);

        for(String temp: allowedUrls){
            if(url.endsWith(temp)){
                return true;
            }
        }

        // 如果没有登录就重定向到登录页面
        response.sendRedirect("/login.do");

        return false;
    }

    // 在处理方法执行之后执行
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("postHandle");
    }

    // 在DispatcherServlet 之后执行 清理工作
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("afterCompletion");
    }

    public List getAllowedUrls() {
        return allowedUrls;
    }

    public void setAllowedUrls(List allowedUrls) {
        this.allowedUrls = allowedUrls;
    }
}

User 类

package com.pengshiyu.bean;

public class User {
    private String name;
    private String password;


    public User() {
    }

    public User(String name, String password) {
        this.name = name;
        this.password = password;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getName() {
        return name;
    }

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

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", password='" + password + '\'' +
                '}';
    }
}

Controller

package com.pengshiyu.controller;

import com.pengshiyu.bean.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

@Controller
public class UserController {
    @RequestMapping("/userInfo")
    public void userInfo(HttpSession session, HttpServletResponse response) throws IOException {
        User user = (User) session.getAttribute("user");
        response.getWriter().println(user);
    }

    @RequestMapping(value = "/login", method = RequestMethod.GET)
    public String login() throws IOException {
        return "/template/login.jsp";
    }

    @RequestMapping(value = "/login", method = RequestMethod.POST)
    public void login(User user, HttpSession session, HttpServletResponse response) throws IOException {
        String message = "";

        if ("root".equals(user.getName()) && "123".equals(user.getPassword())) {
            message = "登录成功";
            session.setAttribute("user", user);
        } else {
            message = "用户名或密码错误";
        }

        response.getWriter().println(message);
    }
}

登录页



登录



    
    

    

关注
打赏
1665367115
查看更多评论
立即登录/注册

微信扫码登录

0.2143s