SpringMvc---学习笔记

ssm:mybatis+Spring+SpringMVC MVC三层架构 

什么是MVC

  • MVC是模型(Model)、视图(View)、控制器(Controller)的简辱,是一种软件设计规范。
  • 是将业务逻辑、数据、显示分离的方法来组织代码。
  • MVC主要作用是降低了视图与业务逻辑间的双向偶合。
  • MVC不是一种设计模式,MVC是一种架构模式。当然不同的MVC存在差异。

Model(模型)︰数据模型,提供要展示的数据,因此包含数据和行为,可以认为是领域模型或JavaBean组件(包含数据和行为),不过现在一般都分离开来: Value Object(数据Dao)和服务层(行为Service)。也就是模型提供了模型数据查询和模型数据的状态更新等功能,包括数据和业务。

View(视图)︰负责进行模型的展示,一般就是我们见到的用户界面,客户想看到的东西。

Controller(控制器)∶接收用户请求,委托给模型进行处理(状态改变),处理完毕后把返回的模型数据返回给视图,由视图负责展示。也就是说控制器做了个调度员的工作。

最经典的MVC就是JSP+Servlet+Javabean模式

  1. 用户发送请求
  2. Servlet接受请求数据,并调用对应的业务逻辑方法
  3. 业务处理完毕,返回更新后的数据给Servlet
  4. Servlet转向到JSP,由JSP来渲染页面
  5. 响应给前端更新后的页面

职责分析:

Controller:控制器

  1. 取得表单数据
  2. 调用业务逻辑
  3. 转向指定的页面

Model:模型

  1. 业务逻辑
  2. 保存数据的状态

View:视图

  1. 显示页面

Model2这样不仅提高的代码的复用率与项目的扩展性,且大大降低了项目的维护成本。Model 1模式的实现比较简单,适用于快速开发小规模项目,Model1中JSP页面身兼View和Controller两种角色,将控制逻辑和表现逻辑混杂在一起,从而导致代码的重用性非常低,增加了应用的扩展性和维护的难度。Model2消除了Model1的缺点。
 

回顾Servlet

1、新建一个Maven工程当做父工程!pom依赖!

    <!--导入依赖-->
    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.3.13</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>2.5</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>jsp-api</artifactId>
            <version>2.1</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>
    </dependencies>

2、建立一个Moudle:springmvc-01-servlet,添加Web app的支持

3、导入Servlet和JSP的jar依赖

    <dependencies>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>3.0-alpha-1</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>jsp-api</artifactId>
            <version>2.2.1-b03</version>
        </dependency>
    </dependencies>

4、编写一个Servlet类,用来处理用户的请求

//实现Servlet接口
public class HelloServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1.获取前端参数
        String method = req.getParameter("method");
        if(method.equals("add")){
            req.getSession().setAttribute("msg","执行了add方法");
        }
        if(method.equals("delete")){
            req.getSession().setAttribute("msg","执行了delete方法");
        }
        //2.调用业务层
        //3.视图转发或者重定向
        req.getRequestDispatcher("/WEB-INF/jsp/test.jsp").forward(req,resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

5、编写Hello.jsp,在WEB-INF目录下新建一个jsp的文件夹,新建hello.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
${msg}
</body>
</html>

6.在web.xml种注册Servlet

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
    <servlet>
        <servlet-name>hello</servlet-name>
        <servlet-class>com.hzx.servlet.HelloServlet</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>/hello</url-pattern>
    </servlet-mapping>

    <session-config>
        <session-timeout>15</session-timeout>
    </session-config>


</web-app>

7、配置Tomcat,并启动测试

  • localhost:8080/user?method=add
  • localhost:8080/user?method=delete

MVC框架要做哪些事情

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

说明

常见的服务器端MVC框架有:Struts、Spring MVC、ASP.NET MVC、Zend Framework,JSF;常见前端MVC框架: vue、angularjs、react、backbone;由MVC演化出了另外一些模式如:MVP、MVVM等等....
MVVM: M V  VM-->ViewModel:双向绑定

SpringMVC


什么是SpringMVC

SpringMVC是SpringFramework的一部分,是基于Java实现MVC的轻量级Web框架

为什么要学SpringMVC

SpringMVC的特点:

  1. 轻量级,简单易学
  2. 高效,基于请求响应的MVC框架
  3. 与Spring兼容性好,无缝结合
  4. 约定优于配置
  5. 功能强大:RESTful、数据验证、格式化、本地化、主题等
  6. 简介灵活

Spring的web框架围绕DispatcherServlet[调度Servlet ]设计。
DispatcherServlet的作用是将请求分发到不同的处理器。从Spring 2.5开始,使用Java 5或者以上版本的用户可以采用基于注解形式进行开发,十分简洁;
正因为SpringMVC好,简单,便捷,易学,天生和Spring无缝集成(使用SpringloC和Aop),使用约定优于配置﹒能够进行简单的junit测试﹒支持Restful风格﹒异常处理,本地化,国际化,数据验证,类型转换,拦截器等等......所以我们要学习.

中心控制器

Spring的web框架围绕DispatcherServlet设计。DispatcherServlet的作用是将请求分发到不同的处理器。从Spring 2.5开始,使用Java 5或者以上版本的用户可以采用基于注解的controller声明方式。

Spring MVC框架像许多其他MVC框架一样,以请求为驱动,围绕一个中心Servlet分派请求及提供其他功能,DispatcherServlet是一个实际的Servlet(它继承自HttpServlet基类)

SpringMVC的原理如下图所示:

当发起请求时被前置的控制器拦截到请求,根据请求参数生成代理请求,找到请求对应的实际控制器,控制器处理请求,创建数据模型,访问数据库,将模型响应给中心控制器,控制器使用模型与视图渲染视图结果,将结果返回给中心控制器,再将结果返回给请求者。

springMVC执行流程

1. DispatcherServlet表示前置控制器,是整个SpringMVC的控制中心。用户发出请求,DispatcherServlet接收请求并拦截请求。

  • 我们假设请求的url为 : http://localhost:8080/SpringMVC/hello
  • 如上url拆分成三部分
  • http://localhost:8080服务器域名.
  • SpringMVC部署在服务器上的web站点.
  • hello表示控制器
  • 通过分析,如上url表示为:请求位于服务器localhost:8080上的SpringMVC站点的hello控制器。

2.HandlerMapping为处理器映射。DispatcherServlet调用
HandlerMapping, HandlerMapping根据请求url查找Handler。

3.HandlerExecution表示具体的Handler,其主要作用是根据url查找控制器,如上url被查找控制器为: hello。

4.HandlerExecution将解析后的信息传递给DispatcherServlet,如解析控制器映射等。

5.HandlerAdapter表示处理器适配器,其按照特定的规则去执行Handler。

6. Handler让具体的Controller执行。

7.Controller将具体的执行信息返回给HandlerAdapter,如ModelAndView。

8.HandlerAdapter将视图逻辑名或模型传递给DispatcherServlet。

9. DispatcherServlet调用视图解析器(ViewResolver)来解析HandlerAdapter传递的逻辑视图名。

10.视图解析器将解析的逻辑视图名传给DispatcherServlet。

11.DispatcherServlet根据视图解析器解析的视图结果,调用具体的视图。12.最终视图呈现给用户。

Controller和RestFul风格


Controller

控制器Controller

  • 控制器复杂提供访问应用程序的行为,通常通过接口定义或注解定义两种方法实现
  • 控制器负责解析用户的请求并将其转换为一个模型。
  • 在Spring MVC中一个控制器类可以包含多个方法
  • 在Spring MVC中,对于Controller的配置方式有很多种

RestFul风格

Restful就是一个资源定位及资源操作的风格。不是标准也不是协议,只是一种风格。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。

功能

  • 资源:互联网所有的事物都可以被抽象为资源
  • 资源操作:使用POST、DELETE、PUT、GET,使用不同方法对资源进行操作
  • 分别对应添加、删除、修改、查询

传统方式操作资源︰通过不同的参数来实现不同的效果!方法单一,post和get

  • http://127.0.0.1/item/queryltem.action?id=1查询,GET
  • http://127.0.0.1/item/saveltem.action新增,POST
  • http://127.0.0.1/item/updateltem.action更新,POST
  • http://127.0.0.1/item/deleteltem.action?id=1删除,GET或POST

使用RESTful操作资源︰可以通过不同的请求方式来实现不同的效果!如下:请求地址一样,但是功能可以不同!

  • http://127.0.0.校/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

结果跳转方式


ModelAndView

设置ModelAndView对象,根据view的名称,和视图解析器跳到指定的页面

页面︰{视图解析器前缀}+ viewName +{视图解析器后缀}

ServletAPI

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

1.通过HttpServletResponse进行输出

2.通过HttpServletResponse实现重定向

3.通过HttpServletResponse实现转发

SpringMVC

SpirngMVC重定向和转发 有无视图解析器

SpringMVC数据处理


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

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

处理方法:

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

后台输出:kuangshen

2.提交的域名称和处理方法的参数名不一致

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

处理方式:

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

后台输出:kuangshen

3.提交的是一个对象

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

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

数据显示对比

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

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

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

JSON讲解


什么是JSON?

  • JSON(JavaScript Object Notation,JS对象标记)是一种轻量级的数据交换格式,目前使用特别广泛。
  • 采用完全独立于编程语言的文本格式来存储和表示数据。·简洁和清晰的层次结构使得JSON成为理想的数据交换语言。
  • 易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率。

在JavaScript 语言中,一切都是对象。因此,任何JavaScript支持的类型都可以通过JSON来表示,例如字符串、数字、对象、数组等。看看他的要求和语法格式:

  • 对象表示为键值对,数据由逗号分隔
  • 花括号保存对象
  • 方括号保存数组

JSON键值对是用来保存JavaScript对象的一种方式,和JavaScript对象的写法也大同小异,键/值对组合中的键名写在前面并用双引号""包裹,使用冒号∶分隔,然后紧接着值:

{"name":"hzx"}

很多人搞不清楚JSON和JavaScript对象的关系,甚至连谁是谁都不清楚。其实,可以这么理解:

  • JSON是JavaScript对象的字符串表示法,它使用文本表示一个JS对象的信息,本质是一个字符串。
    var obj = {a:'hello',b:'world'};//这是一个对象 注意键名也是可以使用引号包裹的
    var json = '{"a":"hello","b":"world"}';//这是一个JSON字符串,本质是一个字符串 

    JSON和JavaScript对象互转

  •  要实现从JSON字符串转换为JavaScript对象,使用JSON.parse()方法:
    var obj = JSON.parse('{"a":"hello","b":"world"}');
    //结果是{a:'hello',b:'world'}
  • 要实现从JavaScript对象转换为JSON字符串,使用JSON.stringify()方法:
    var json = JSON.stringify({a:'hello',b:'world'});
    // 结果是'{"a":"hello","b":"world"}'

Controller返回JSON数据

  • Jackson应该是目前比较好的json解析工具了
  • 当然工具不止这一个,比如还有阿里巴巴的fastjson等等
  • 我们这里使用Jackson,使用它需要导入它的jar包;
            <dependency>
                <groupId>com.fasterxml.jackson.core</groupId>
                <artifactId>jackson-databind</artifactId>
                <version>2.13.0</version>
            </dependency>

 Json工具类:

public class JsonUtils {

    public static String getJson(Object object){
        return getJson(object,"yyyy-MM-dd HH:mm:ss");
    }

    public static String getJson(Object object,String dateFormat){
        ObjectMapper mapper = new ObjectMapper();

        //不使用时间戳的方式
        mapper.configure(SerializationFeature.WRITE_DATE_KEYS_AS_TIMESTAMPS,false);
        //自定义日期的格式
        SimpleDateFormat sdf = new SimpleDateFormat(dateFormat);
        mapper.setDateFormat(sdf);

        try {
            return mapper.writeValueAsString(object);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }

        return null;
    }
}

Ajax技术


  • AJAX = Asynchronous JavaScript and XML(异步的JavaScript和XML)。
  • AJAX是一种在无需重新加载整个网页的情况下,能够更新部分网页的技术。
  • Ajax 不是一种新的编程语言,而是一种用于创建更好更快以及交互性更强的Web应用程序的技术。
  • 在2005年,Google通过其Google Suggest使 AJAX变得流行起来。Google Suggest能够自动帮你完成搜索单词。
  •  Google Suggest使用AJAX创造出动态性极强的 web界面:当您在谷歌的搜索框输入关键字时,JavaScript会把这些字符发送到服务器,然后服务器会返回一个搜索建议的列表。
  • 就和国内百度的搜索框一样
  • 传统的网页(即不用ajax技术的网页),想要更新内容或者提交一个表单,都需要重新加载整个网页。
  • 使用ajax技术的网页,通过在后台服务器进行少量的数据交换,就可以实现异步局部更新。
  • 使用Ajax,用户可以创建接近本地桌面应用的直接、高可用、更丰富、更动态的Web用户界面。

伪造Ajax

iframe

js:

  • 函数:闭包
  • DOM
    • id,name,tag
    • create,remove
  • BOM
    • window
    • document

ES6:import require

拦截器


SpringMVC的处理器拦截器类似于Servlet开发中的过滤器Filter,用于对处理器进行预处理和后处理。开发者可以自己定义一些拦截器来实现特定的功能。

过滤器与拦截器的区别:拦截器是AOP思想的具体应用。

过滤器

  • servlet规范中的一部分,任何java web工程都可以使用
  • 在url-pattern中配置了/*之后,可以对所有要访问的资源进行拦截

拦截器

  • 拦截器是Spring MVC框架自己的,只有使用了SpringMVC框架的工程才能使用
  • 拦截器只会拦截访问的控制器方法,如果访问的是jsp/html/css/image/js是不会进行拦截的
    <!-- 拦截器配置-->
    <mvc:interceptors>
        <mvc:interceptor>
            <!--   包括这个请求下的所有请求   -->
            <mvc:mapping path="/**"/>
            <bean class="com.hzx.config.MyInterceptor"></bean>
        </mvc:interceptor>
    </mvc:interceptors>

文件上传


    <!--  文件上传配置  -->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <!--  请求的编码格式 必须和jsp的pageEncoding属性一致 以便正确读取表单的内容 默认为ISO-8859-1 -->
        <property name="defaultEncoding" value="UTF-8"></property>
        <!--  上传文件大小上限 单位为字节  (10485760=10M) -->
        <property name="maxUploadSize" value="10485760"></property>
        <property name="maxInMemorySize" value="40960"></property>

    </bean>

文件上传下载


package com.hzx.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.commons.CommonsMultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;

@RestController
public class FileController {

    //@RequestParam("file") 将name=file控件得到的文件封装称CommonsMultipartFile对象
    //批量上传CommonsMultipartFile则为数组即可
    @RequestMapping("/upload")
    public String upload(@RequestParam("file")CommonsMultipartFile file, HttpServletRequest request) throws IOException {

        //获取文件名:file.getOriginalFilename();
        String uploadFileName = file.getOriginalFilename();

        //如果文件名为空 直接回到首页
        if("".equals(uploadFileName)){
            return "redirect:/index.jsp";
        }
        System.out.println("上传文件名:"+uploadFileName);

        //上传路径保存设置
        String path = request.getSession().getServletContext().getRealPath("/upload");
        //如果路径不存在 创建一个
        File realPath = new File(path);
        if(!realPath.exists()){
            realPath.mkdir();
        }
        System.out.println("上传文件保存地址:"+realPath);

        InputStream is = file.getInputStream();//文件输入流
        OutputStream os = new FileOutputStream(new File(realPath,uploadFileName));//文件输出流

        //读取写出
        int len = 0;
        byte[] buffer = new byte[1024];
        while((len = is.read(buffer)) != -1){
            os.write(buffer,0,len);
            os.flush();
        }
        os.close();
        is.close();
        return "redirect:/index.jsp";
    }

    /*
        采用filie.Transto来保存上传的文件
     */
    @RequestMapping("/upload2")
    public String fileUpload2(@RequestParam("file")CommonsMultipartFile file,HttpServletRequest request) throws IOException {

        //上传路径保存设置
        String path = request.getSession().getServletContext().getRealPath("/upload");
        //如果路径不存在 创建一个
        File realPath = new File(path);
        if(!realPath.exists()){
            realPath.mkdir();
        }
        System.out.println("上传文件保存地址:"+realPath);

        //通过ConmmonsMultipartFile的方法直接写文件
        file.transferTo(new File(realPath+"/"+file.getOriginalFilename()));

        return "redirect:/index.jsp";
    }

    /**
     * 文件下载
     */
    @RequestMapping("/download")
    public String downloads(HttpServletResponse response,HttpServletRequest request) throws IOException {
        //要下载的图片地址
        String path = request.getSession().getServletContext().getRealPath("/upload");
        String fileName = "基础语法.jpg";

        //1、设置response响应头
        response.reset();//设置页面而不缓存 清空buffer
        response.setCharacterEncoding("UTF-8");//字符编码
        response.setContentType("multipart/form-data");//二进制传输数据
        //设置响应头
        response.setHeader("Content-Disposition","attachment;fileName="+ URLEncoder.encode(fileName,"UTF-8"));

        File file = new File(path,fileName);
        //2、读取文件 输入流
        InputStream inputStream = new FileInputStream(file);
        //3、写出文件 输出流
        OutputStream outputStream = response.getOutputStream();

        byte[] buffer = new byte[1024];
        int len = 0;
        //4、执行 写出擦欧总
        while((len = inputStream.read(buffer)) != -1){
            outputStream.write(buffer,0,len);
            outputStream.flush();
        }
        outputStream.close();
        inputStream.close();
        return null;
    }


}


学Java关注狂神说

猜你喜欢

转载自blog.csdn.net/qq_45304571/article/details/121380909
今日推荐