2021-08-02 SpringMVC实战技术

一、MVC软件框架与SpringMVC介绍

1.1 MVC模式

MVC模式是一种开发方式,它的主要用途是对组件之间进行隔离分层。

1.1.1 MVC三层架构

  1. M(odel)模型,包含被传递的数据。在软件项目中,M常常被定义为业务模型,也就是业务/服务层。
  2. V(ison)视图层,即用什么组件显示数据,常用的有HTML与JSP这些文件。
  3. C(ontroller)控制层,表示软件大方向的执行流程以及哪个视图对象将数据展示给用户。

1.1.2 MVC的优点

MVC开发方式将不用功能的组件进行隔离,进行分层,有利于代码的后期维护。

1.2 软件框架

软件框架就是软件功能的半成品。框架提供了针对某一个领域所写代码的基本模型,对大多数通用性的功能进行封装。

Spring5MVC框架是现在主流的JavaWeb服务端MVC分层框架,它在功能及代码执行效率上进行了优化和增强。

二、搭建MavenSpring项目

2.1 项目基本环境的搭建与运行

2.1.1 项目基本环境搭建步骤

  1. 创建maven-webapp项目。
  2. 在pom.xml中 新增依赖(如下)。

与name、url等同级:

  <parent>
    <artifactId>spring-boot-starter-parent</artifactId>
    <groupId>org.springframework.boot</groupId>
    <version>2.5.3</version>
  </parent>

dependencies中新增节点:

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-web</artifactId>
  <version>2.3.4.RELEASE</version>
</dependency>
  1. 右键main,new->directory,选择java与resources,新建两个目录。

  2. 创建controller层的TestController与Spring启动类Application,项目结构如图所示。
    在这里插入图片描述

  3. TestController代码:

package com.wqq.www.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class TestController {
    
    
    @RequestMapping("test1")
    @ResponseBody
    public String test1(){
    
    
        System.out.println("public String test1()");
        return "test1返回值";
    }
}

注意:

  • @Controller注解注明该类作用于Controller层。
  • @RequestMapping(“test1”),注明匹配方式,即通过根路径+test1进行访问此controller。
  • ResponseBody注明返回体。(此案例可以不使用它)
  1. Application代码:
package com.wqq.www;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Application {
    
    
    public static void main(String[] args) {
    
    
        SpringApplication.run(Application.class, args);
    }
}

2.1.2 项目运行

1、通过idea编译器Application启动类运行

点击如下所示的按钮,等待加载完成便可运行。
在这里插入图片描述输入网址http:/localhost:8080/test1即可出现如下网页,运行成功。
在这里插入图片描述

2.1.3 打包运行

1、介绍

将SpringBoot Web项目打包成可自动运行的war/jar,直接运行war/jar就可以启动Web项目。war/jar以及内嵌了tomcat,实际项目发布时,只需要这种war/jar包便可以完成项目的发布

2、新增plugins节点

将以下代码放到build标签中(注:不是pluginManagement里面,而是与它同级。)

<plugins>
      <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
      </plugin>
</plugins>

3、运行cmd命令

  1. 打开cmd并进入项目根目录。
  2. 输入命令mvn package
  3. 控制台显示BUILD SUCCESS字样,然后刷新项目目录,便可见到war包文件。
  4. 若想生成jar包文件只需将pom.xml中的配置更改即可(与groupId、artifactId等节点同级)。其他打包步骤均相同。
<packaging>jar</packaging>
  1. 输入以下命令启动服务器
    java -jar war包的名字.war(没写错)或java -jar jar包的名字.jar

2.2 创建css-JavaScript-HTML-JSP资源

2.2.1 项目结构

在这里插入图片描述

2.2.2 代码

mycss.css:

.myStyle{
    
    
    color: red;
    font-size: large;
}

myjs.js:

setTimeout(function (){
    
    
    alert("auto run!");
},3000)

test1.html

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <script src="js/myjs.js"></script>
        <link rel="stylesheet" type="text/css" href="css/mycss.css">

    </head>
    <body>
        <p>这是html</p><br>
        <h1 class="myStyle">引入css样式</h1>
    </body>
</html>

test2.jsp

<%@ page contentType="text/html; UTF-8" language="java" pageEncoding="UTF-8" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<html>
    <head>
        <link rel="stylesheet" type="text/css" href="css/mycss.css">
    </head>
<body>
<h2>Hello jsp文件</h2>
    <br/>
    <h1 class="myStyle">引入样式表</h1>
    <c:forEach var="item" items="${mylist}">
        ${item}<br/>
    </c:forEach>
</body>
</html>

TestController(jsp页面通过转发获得myList):

package com.wqq.www.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;

@Controller
public class TestController {
    
    
    @RequestMapping("/")
    public String test1(){
    
    
        System.out.println("public String test1()");
        return "test1.html";
    }

    @RequestMapping("test1")
    public String test2(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    

        System.out.println("public String test2()");
        ArrayList<String> list = new ArrayList<>();
        list.add("你好 1");
        list.add("你好 2");
        list.add("你好 3");
        request.setAttribute("mylist", list);
        request.getRequestDispatcher("test2.jsp").forward(request,response);
        return "test2.jsp";
    }
}

在地址栏输入http://localhost:8080/test1即可调用controller进入jsp。
在地址栏输入http://localhost:8080/即可调用controller进入test1.html。

三、参数传递

3.1 控制层参数传递

3.1.1 控制层无传参

@RequestMapping(“x1”)
public String x1(){
System.out.println(“public String x1()”);
return “x1.html”;
}

3.1.2 控制层有传参

@RequestMapping("x2")
public String x2(@RequestParam("username") String username, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
    System.out.println("public String x2()" + username);
    ArrayList<String> list = new ArrayList<>();
    list.add("你好 1");
    list.add("你好 2");
    list.add("你好 3");
    request.setAttribute("mylist", list);
    request.getRequestDispatcher("test2.jsp").forward(request,response);
    return "x2.jsp";
}

3.1.3 控制层有传参简化版

@RequestMapping("x3")
public String x3(String username, String password,HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
    System.out.println("username = " + username + "password = " + password);
    return "x3.jsp";
}

3.1.4 将url参数封装到实体类

创建实体类dto.Userinfo

package com.wqq.www.dto;

public class Userinfo {
    
    
    private String username;
    private String password;

    public Userinfo(String username, String password) {
    
    
        this.username = username;
        this.password = password;
    }

    public Userinfo() {
    
    
    }

    public String getUsername() {
    
    
        return username;
    }

    public void setUsername(String username) {
    
    
        this.username = username;
    }

    public String getPassword() {
    
    
        return password;
    }

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

controller层获得实体类参数

 @RequestMapping("login2")
    public String login2(Userinfo userinfo){
    
    
        if (userinfo.getUsername().equals("a")&&userinfo.getPassword().equals("aa")){
    
    
            return "ok.jsp";

        }
        else {
    
    
            return "no.jsp";
        }
    }

3.1.5 限制提交method的方式

注解上加入method = RequestMethod.XXX

@RequestMapping(value = "login3",method = RequestMethod.POST)

3.2 参数类型

3.2.1 控制层方法的参数类型

控制层方法参数类型 解释
WebRequest/NativeWebRequest 可以访问request的parameters,request 和 session的 attributes,而不需要使用Servlet API。
javax.servlet.ServletRequest / javax.servlet.ServletResponse / MultipartRequest / MultipartHttpServletRequest 使用指定的request或response对象。
javax.servlet.http.HttpSession 使用指定的HttpSession对象。 注意:访问HttpSession不是线程安全的,如果有多个请求同时访问HttpSession对象,则需要将RequestMappingHandlerAdapter类的synchronizeOnSession属性设置为true.
HttpMethod request请求的method方式。
java.util.Locale 当前请求的区域。
java.util.TimeZone +java.time .ZoneId 当前请求关联的Zone.
java.io.Inputstream java.io.Reader 访问request body最原始的数据。
java.io.outputStream java.io.writer 访问response body最原始的数据。
@PathVariable 访问URI模板变量。
@MatrixVariable 访问以name-value形式存在于URI路径中的片段。
@RequestParam 访问request中的parameters,该注解是可选的。
@RequestHeader 访问request headers中的数据。
@CookieValue 访问Cookie。
@RequestBody 访问request body。
@HttpEntity< B> 访问request中的headers和body。
@RequestPart 处理"multipart/form-data"请求中的part。
java.util.Map org.springframework.ui.Model org.springframework.ui.ModelMap 用于View层的交互。
RedirectAttributes 在重定向时添加attributes处理,有2种用法:(1)可以将数据放在query string中。 (2)结合flash attributes将数据存储到临时的空间,当重定向结束后删除临时空间中的数据。
@ModelAttribute 访问已存在的attribute
Errors / BindingResult 访问的Errors来自于数据验证和绑定,或者Errors来自于对@RequestBody或@RequestPart的验证。一个Errors或BindingResult参数要声明在验证方法参数之后。
类级别的@SessionAttributes 定义HttpSession中的 attributes,在处理完成后触发清理。
@SessionAttribute 访问session中的attribute。与作为类级的@SessionAttribute结果而存储在绘画中的Model属性形成对比
@RequestAttribute 访问request中的attributes

3.2.2 控制层方法的返回值类型

控制层方法的返回值类型 解释
@ResponseBody 通过HttpMessageConverters转换返回值,并写入到response中。
HttpEntity< B> / ResponseEntity< B> Response包括完整的headers和body,并且通过HttpMessageConverters转换返回值,并且谢图到response中
HttpHeaders 返回response headers,但不包括body
String 使用ViewResolver解析视图的名称。
View 返回View实例
java.util.Map / org.springframework.ui.Mode 要添加到隐式Model中的属性,并通过RequestToViewNameT确定视图名称。
@ModelAttribute 要添加到隐式Model中的属性,并通过RequestToViewNameT确定视图名称。
ModelAndView 用于确定View和attributes
void 如果具有void返回值或返回null值的方法还具有ServletResponse,OutputStream参数或@Response Status注解,则视为已完全处理响应。

3.3 取得request-response-session对象

介绍

通过Controller层的参数HttpServletRequest , HttpServletResponse HttpSession来获取request、response、session对象。

代码

控制层代码:

    @RequestMapping("y1")
    public String y1(HttpServletRequest request, HttpServletResponse response, HttpSession session){
    
    
        System.out.println(request);
        System.out.println(response);
        System.out.println(session);
        System.out.println(request.getServletContext().getRealPath("/"));
        request.setAttribute("my", "requestValue");
        session.setAttribute("my", "sessionValue");
        return "y1.jsp";
}

view层代码(通过requestScope、sessionScope获取不同范围的值):

    request:${my}
    request:${requestScope.my}
    session:${sessionScope.my}

3.4 实现登录失败后的提示信息

介绍

控制层在处理前进行验证,如果所传数据不符合规范,则传到map类型的容器中,前端通过el表达式显示失败信息。

代码

jsp页面代码:

<form action="login4" method="post">
    username:<input type="text" name="username"><br/>
    ${message.usernameisnull}<br/>
    password:<input type="text" name="password"><br/>
    ${message.passwordisnull}<br/>
    <input type="submit" value="登录">
</form>

controller层代码:

  private Map validateForm4(Userinfo userinfo ){
    
    
      Map map = new HashMap();
      if (userinfo.getUsername()  == null||"".equals(userinfo.getUsername()))
          map.put("usernameisnull", "账号为空!");
      if (userinfo.getPassword()  == null||"".equals(userinfo.getPassword()))
          map.put("passwordisnull", "密码为空!");
      return map;
  }

  @RequestMapping("login4")
  public String login4(Userinfo userinfo, HttpServletRequest request){
    
    
      Map map =  validateForm4(userinfo);
      if (map.size() > 0) {
    
    
          request.setAttribute("message", map);
          return "login4.jsp";
      }
      else {
    
    
          if (userinfo.getUsername().equals("a")&&userinfo.getPassword().equals("aa"))
              return "ok.jsp";
          else
              return "no.jsp";
      }
  }

3.5 控制层的重定向

3.5.1 重定向-无参数传递

(1)通过返回"redirect:/xx"来重定向
    @RequestMapping("z2")
    public String z2(){
    
    
        System.out.println("z2");
        return "redirect:/z3";
    }
(2)通过返回"xx.jsp"来重定向
    @RequestMapping("z3")
    public String z3(){
    
    
        System.out.println("z3");
        return "no.jsp";
    }

3.5.2 重定向-有参数传递

(1)通过返回字符串传递参数
//发送
@RequestMapping("z4")
public String z4() throws UnsupportedEncodingException {
    
    
    System.out.println("z4");
    String username = "中国";
    username = URLEncoder.encode(username, "utf-8");
    System.out.println(username);
    return "redirect:/z5?username="+username;
}
//接收
@RequestMapping("z5")
public String z5(String username) throws UnsupportedEncodingException {
    
    
    System.out.println("z5");
    username = URLDecoder.decode(username, "utf-8");
    System.out.println("z5 username = " + username);
    return "no.jsp";
}
(2)通过RedirectAttributes.addAttrubute方法传递参数
@RequestMapping("z6")
public String z6(RedirectAttributes attr) throws UnsupportedEncodingException {
    
    
    System.out.println("z6");
    String username = "中国";
    String password = "123";
    username = URLEncoder.encode(username, "utf-8");
    attr.addAttribute("username",username);
    attr.addAttribute("password",password);
    return "redirect:/z7";
}
@RequestMapping("z7")
public String z7(String username,String password) throws UnsupportedEncodingException {
    
    
    username = URLDecoder.decode(username, "utf-8");
    System.out.println("z7 username = " + username + "password = "+password);
    return "no.jsp";
}
(3)通过RedirectAttributes.addFlashAttrubute方法传递参数

注:该种方式与上面方式的区别,此种方式将参数放入HttpSession中,而上种方式存放于url中。这种方式更安全,更透明。且在重定向结束后,HttpSession自动清除数据,进一步增强安全性。

    @RequestMapping("z8")
    public String z8(RedirectAttributes attr) throws UnsupportedEncodingException {
    
    
        System.out.println("z8");
        String username = "中国";
        String password = "123";
        username = URLEncoder.encode(username, "utf-8");
        attr.addFlashAttribute("username",username);
        attr.addFlashAttribute("password",password);
        return "redirect:/z9";
    }
//注意@ModelAttribute("username")需要加
    @RequestMapping("z9")
    public String z9(@ModelAttribute("username") String username,@ModelAttribute("password") String password) throws UnsupportedEncodingException {
    
    
        username = URLDecoder.decode(username, "utf-8");
        System.out.println("z9 username = " + username + "password = "+password);
        return "no.jsp";
    }

3.5.3 在服务端将json字符串转化为多种数据类型(使用AJAX) P35

(1) 概述

前端传送的json字符串可以通过Spring5MVC默认使用的jackson库来将json转化为各种数据类型。
使用@RequestBody注解后,前台只需要向Controller提交一段符合JSON格式的字符串便可完成自动解析。

(2)代码

实体类Userinfo含有username、password两个属性。
控制层代码(包含转化的各种类型示例):

//转化成实体类
    @RequestMapping("ajaxTest1")
    @ResponseBody
    public String ajaxTest1(@RequestBody Userinfo userinfo){
    
    //RequestBody必须加
        System.out.println(userinfo.getUsername());
        System.out.println(userinfo.getPassword());
        return "1";
    }
//转化成字符串列表
    @RequestMapping("ajaxTest2")
    @ResponseBody
    public String ajaxTest2(@RequestBody ArrayList<String> list){
    
    //RequestBody必须加
        list.forEach(item->{
    
    
            System.out.println(item);
        });
        return "1";
    }
//转化成实体类列表
    @RequestMapping("ajaxTest3")
    @ResponseBody
    public String ajaxTest3(@RequestBody ArrayList<Userinfo> list){
    
    //RequestBody必须加
        list.forEach(item->{
    
    
            System.out.println(item.getUsername() + item.getPassword());
        });
        return "1";
    }
//转化为Map
    @RequestMapping("ajaxTest4")
    @ResponseBody
    public String ajaxTest4(@RequestBody Map list){
    
    //RequestBody必须加
        System.out.println(list.get("username"));
        List<HashMap<String,String>> workList = (List<HashMap<String, String>>) list.get("work");
        workList.forEach(item->{
    
    
            System.out.println(item.get("address"));
        });
        HashMap<String,String> school = (HashMap<String, String>) list.get("school");
        System.out.println(school.get("name"));
        System.out.println(school.get("address"));
        return "1";
    }
//复杂object对象的转换
    @RequestMapping("ajaxTest5")
    @ResponseBody
    public String ajaxTest5(@RequestBody HashMap<String,Object> map){
    
    //RequestBody必须加
        List list1 = (List) map.get("myArray");
        Map map1 = (Map) list1.get(0);
        System.out.println(map1.get("username1"));
        Map map2 = (Map) list1.get(1);
        System.out.println(map2.get("username2"));

        List list2 = (List) list1.get(2);
        System.out.println(list2.get(0));
        System.out.println(list2.get(1));
        System.out.println(list2.get(2));

        List list3 = (List) list2.get(3);
        System.out.println(list3.get(0));
        System.out.println(list3.get(1));

        Map map3 = (Map) map.get("myObject");
        System.out.println(map3.get("username"));

        Map map4 = (Map) map.get("myObject1");
        List<Map> list4 = (List) map4.get("address");
        System.out.println(list4.get(0).get("name"));
        System.out.println(list4.get(1).get("name"));

        return "1";
    }

前端数据传输方法(与controller层对应):

            function Userinfo(username,password){
    
    
                this.username=username;
                this.password=password;
            }
            $(document).ready(function (){
    
    
                {
    
    
                    let userinfo = new Userinfo("中国","中国人");
                    let jsonString = JSON.stringify(userinfo);
                    $("#button1").click(function (){
    
    
                        $.ajax({
    
    
                            "url":"ajaxTest1?t="+new Date().getTime(),
                            "type":"post",
                            "data":jsonString,
                            "contentType":"application/json"
                        })
                    })
                }

                {
    
    
                    let stringArray_ = new Array();
                    stringArray_[0] = "中国1";
                    stringArray_[1] = "中国2";
                    stringArray_[2] = "中国3";
                    let jsonString_ = JSON.stringify(stringArray_);
                    $("#button2").click(function (){
    
    
                        $.ajax({
    
    
                            "url":"ajaxTest2?t="+new Date().getTime(),
                            "type":"post",
                            "data":jsonString_,
                            "contentType":"application/json"
                        })
                    })
                }
                {
    
    
                    let stringArray = new Array();
                    stringArray[0] = new Userinfo("中国1","中国人1");
                    stringArray[1] = new Userinfo("中国2","中国人2");
                    stringArray[2] = new Userinfo("中国3","中国人3");
                    let jsonString = JSON.stringify(stringArray);
                    $("#button3").click(function (){
    
    
                        $.ajax({
    
    
                            "url":"ajaxTest3?t="+new Date().getTime(),
                            "type":"post",
                            "data":jsonString,
                            "contentType":"application/json"
                        })
                    })
                }
                {
    
    
                    let jsonObject = {
    
    
                        "username": "accp",
                        "work": [{
    
    
                            "address": "address1"
                        }, {
    
    
                            "address": "address2"
                        }],
                        "school": {
    
    
                            "name": "tc",
                            "address": "pjy"
                        }
                    }
                    let jsonString = JSON.stringify(jsonObject);
                    $("#button4").click(function (){
    
    
                        $.ajax({
    
    
                            "url":"ajaxTest4?t="+new Date().getTime(),
                            "type":"post",
                            "data":jsonString,
                            "contentType":"application/json"
                        })
                    })
                }
                {
    
    
                    let userinfo = {
    
    
                        "myArray": [{
    
    
                            "username1": "usernameValue11"
                        }, {
    
    
                            "username2": "usernameValue22"
                        }, ["abc", 123, true, [123, 456]]],
                        "myObject": {
    
    
                            "username": "大中国"
                        },
                        "myObject1": {
    
    
                            "address": [{
    
    
                                "name": "name1"
                            }, {
    
    
                                "name": "name2"
                            }]
                        },
                    };
                    let jsonString = JSON.stringify(userinfo);
                    $("#button5").click(function (){
    
    
                        $.ajax({
    
    
                            "url":"ajaxTest5?t="+new Date().getTime(),
                            "type":"post",
                            "data":jsonString,
                            "contentType":"application/json"
                        })
                    })
                }


P39


    @RequestMapping("ajaxTest6")
    @ResponseBody
    public Userinfo ajaxTest6(@RequestBody Userinfo userinfo){
    
    //RequestBody必须加
        System.out.println(userinfo.getUsername());
        System.out.println(userinfo.getPassword());

        Userinfo returnUser = new Userinfo();
        returnUser.setUsername("法国");
        returnUser.setPassword("法国人");
        return returnUser;
    }

    @RequestMapping("ajaxTest7")
    @ResponseBody
    public String ajaxTest7(@RequestBody Userinfo userinfo) throws JsonProcessingException {
    
    //RequestBody必须加
        System.out.println(userinfo.getUsername());
        System.out.println(userinfo.getPassword());

        UserinfoExt returnUser = new UserinfoExt();
        returnUser.setUsername("法国");
        returnUser.setPassword("法国人");
        returnUser.getMyList().add("德国");
        returnUser.getMyList().add("土耳其");

        String jsonString = new ObjectMapper().writeValueAsString(returnUser);

        return jsonString;
    }

    @RequestMapping("ajaxTest8")
    @ResponseBody
    public void ajaxTest8(@RequestBody Userinfo userinfo, HttpServletResponse response) throws IOException {
    
    //RequestBody必须加
        System.out.println(userinfo.getUsername());
        System.out.println(userinfo.getPassword());

        UserinfoExt returnUser = new UserinfoExt();
        returnUser.setUsername("法国");
        returnUser.setPassword("法国人");
        returnUser.getMyList().add("德国");
        returnUser.getMyList().add("土耳其");
        String jsonString = new ObjectMapper().writeValueAsString(returnUser);
        response.setContentType("text/html;charset=utf-8");
        PrintWriter writer = response.getWriter();
        writer.print(jsonString);
        writer.flush();
        writer.close();
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_43399489/article/details/119315642