首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >SpringMVC入门终结篇

SpringMVC入门终结篇

作者头像
大忽悠爱学习
发布于 2021-11-15 04:00:33
发布于 2021-11-15 04:00:33
1.6K00
代码可运行
举报
文章被收录于专栏:c++与qt学习c++与qt学习
运行总次数:0
代码可运行

SpringMVC入门第四部分

自定义类型对象和请求参数的数据绑定流程


自定义类型转换器

自定义类型转换器,实现String----->employee对象的转换和封装

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<form action="${ctp}/quickAdd">
    <%--将员工所有信息都写上,自动封装对象--%>
     <input type="text" name="empInfo" value="大忽悠-总裁办-@123-1"/>
   <input type="submit" value="快速添加员工"/>
</form>

快速添加员工的方法:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    @RequestMapping("quickAdd")
    //获取请求参数empInfo
    //employee=request.getParame("empInfo")---->大忽悠-总裁办-@123-1
    public String quickAdd(@RequestParam("empInfo") Employee employee)
    {
        employeeDao.save(employee);
      return  "redirect:/emps";
    }

ConversionService是一个接口,里面通过一个Converter转换器进行工作


步骤1:实现Converter接口,写一个自定义类型转换器

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/*
* 两个泛型S,T
* S:source
* T:target
* 把s转换为t
* */
//自定义类型转换器
public class MyConverter implements Converter<String, Employee> {
    //自定义转换规则
    public Employee convert(String source) {
        System.out.println("要转换的字符串:"+source);
        Employee employee=new Employee();
        if(source.contains("-"))
        {
            //大忽悠-总裁办-@123-1
            String[] ret=source.split("-");
            employee.setName(ret[0]);
            employee.setDepartment(ret[1]);
            employee.setEamil(ret[2]);
            employee.setGender(Integer.parseInt(ret[3]));
        }
        return employee;
    }
}

步骤2:Converter是ConversionService中的一个组件,我们需要把Converter放入到ConversionService中

步骤3:将WebDataBinder中的ConversionService设置成我们这个加了自定义类型ConversionService

步骤4:让SpringMVC使用我们的ConversionService

配置文件中实现步骤1:配置出ConversionService


converters在源码中是一个set集合


代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    <!--告诉SpringMVC别用默认的ConversionService,
    而是使用自定义的ConversionService
    ,里面有我们自定义的converter-->
    <bean id="conversionService"
          class="org.springframework.context.support.ConversionServiceFactoryBean">
        <!--在converters转换器中添加我们自定义的类型转换器-->
        <property name="converters">
            <set>
                <bean class="com.Converter.MyConverter"/>
            </set>
        </property>
    </bean>
    <!--使用我们自己的配置的类型转换组件-->
    <mvc:annotation-driven conversion-service="conversionService"></mvc:annotation-driven>

总结三步


annotation-driven介绍

mvc:annotation-driven和mvc:default对动态和静态资源的影响

当mvc:annotation-driven和mvc:default-servlet-handler都没配置时,只有动态资源能够访问,静态资源访问不了

常见动态资源: @RequestMapping映射的资源,.jsp

常见的静态资源: .html , .js , .img


只加mvc:default-servlet-handler,那么静态资源能访问,动态资源不能访问


只配置mvc:annotation-driven,那么只能访问动态资源,不能访问静态资源


mvc:default-servlet-handler和mvc:annotation-driven都配置后,那么静态资源和动态资源都可以访问了


数据格式化之日期格式化

ConversionServiceFactoryBean创建的ConversionService组件是没有格式化器存在的

解决方法1:不使用自定义类型的转换器

解决方法2:将自定义类型转换器注册到FormattingConversionServiceFactoryBean,这样就有格式化功能了

以后写自定义数据类型转换器的时候,就使用FormattingConversionServiceFactoryBean来注册自定义类型转换器,这样就既具有类型转换,又具有格式化功能
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    <bean id="conversionService"
          class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
        <!--在converters转换器中添加我们自定义的类型转换器-->
        <property name="converters">
            <set>
                <bean class="com.Converter.MyConverter"/>
            </set>
        </property>
    </bean>
    <!--使用我们自己的配置的类型转换组件-->
    <mvc:annotation-driven conversion-service="conversionService"></mvc:annotation-driven>

后端规定提交的日期格式,不对就报错

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//规定提交的日期格式
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date birth;

后端规定提交的数字格式

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@NumberFormat(pattern = "#,###,###.##")//类似这样的数字格式: 1,000,000.98
private double salary;

数据校验:只做前端校验是不安全的,在重要的数据一定要加上后端校验

SpingMVC可以使用JSR303来做数据校验

Hibernate Validator是第三方框架实现了JSR303规范


实现步骤:

1.maven管理引入springmvc注解数据校验所需jar包:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
   <!-- maven管理引入springmvc注解数据校验所需jar包:-->
    <dependency>
      <groupId>javax.validation</groupId>
      <artifactId>validation-api</artifactId>
      <version>1.1.0.Final</version>
    </dependency>
    <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-validator</artifactId>
      <version>5.1.0.Final</version>
    </dependency>

2.只需要给javaBean的属性上加上校验注解

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@NotEmpty
@Length(min=6,max=8)//至少6个字符,最多8个字符
private  String name;
private  String department;
@Email
private  String eamil;

3.在SpringMVC封装对象的时候,告诉SpringMVC这个javaBean对象需要校验----@Valid注解

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
   //只接收Post请求
    @RequestMapping(value = "/emp",method = RequestMethod.POST)
    //@Valid注解,告诉SpringMVC,封装这个javabean对象时,按照这个对象里面变量规定的校验规则进行校验
    public String addEmp(@Valid Employee employee)//这里会自动赋值
    {
        System.out.println("要添加的员工信息:"+employee);
            employeeDao.save(employee);
            //返回列表页面,直接重定向到查询所有员工的请求
            return  "redirect:/emps";
    }

4.如何知道校验结果,给需要校验的javaBean后面紧跟一个BindingResult,这个BindingResult就是封装前一个bean的校验结果

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    //只接收Post请求
    @RequestMapping(value = "/emp",method = RequestMethod.POST)
    //@Valid注解,告诉SpringMVC,封装这个javabean对象时,按照这个对象里面变量规定的校验规则进行校验
    public String addEmp(@Valid Employee employee,BindingResult res)//这里会自动赋值
    {
        System.out.println("要添加的员工信息:"+employee);
            employeeDao.save(employee);
            //返回列表页面,直接重定向到查询所有员工的请求
            return  "redirect:/emps";
    }

5.根据不同的校验结果决定怎么做

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    //只接收Post请求
    @RequestMapping(value = "/emp",method = RequestMethod.POST)
    //@Valid注解,告诉SpringMVC,封装这个javabean对象时,按照这个对象里面变量规定的校验规则进行校验
    public String addEmp(@Valid Employee employee,BindingResult res)//这里会自动赋值
    {
        System.out.println("要添加的员工信息:"+employee);
        //获取是否有校验错误
        boolean hasErrors = res.hasErrors();
        if(hasErrors)
        {
            System.out.println("有校验错误");
            return "addPage";
        }
        else
        {
            employeeDao.save(employee);
            //返回列表页面,直接重定向到查询所有员工的请求
            return  "redirect:/emps";
        }
    }

6.将错误信息回显在页面上

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<%pageContext.setAttribute("ctp",request.getContextPath());%>
<form:form modelAttribute="employee" action="${ctp}/emp" method="post">
    <%--显示错误信息,有默认的错误信息,也可也自己写显示的错误西信息--%>
    员工id:<form:input path="id"/><form:errors path="id"></form:errors><br/>
    姓名:<form:input path="name"/><form:errors path="name"></form:errors><br/>
    邮箱:<form:input path="eamil"/><form:errors path="eamil"></form:errors><br/>
    性别:<br/>
    :<form:radiobutton path="gender" value="1"/>
    :<form:radiobutton path="gender" value="0"/>
    请选择员工所在的部门:
    <form:select path="department" items="${departments}"/>
    <br/>
    <input type="submit" value="提交">
</form:form>

普通表单将请求信息放在请求域中去页面获取

通过BindingResult的res对象的 getFieldErrors方法,可以获得当前属性值出现的全部错误,然后通过一个Model对象存储错误信息,放到隐含模型中

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    //只接收Post请求
    @RequestMapping(value = "/emp",method = RequestMethod.POST)
    //@Valid注解,告诉SpringMVC,封装这个javabean对象时,按照这个对象里面变量规定的校验规则进行校验
    public String addEmp(@Valid Employee employee,BindingResult res,Model model)//这里会自动赋值
    {
        System.out.println("要添加的员工信息:"+employee);
        //获取是否有校验错误
        boolean hasErrors = res.hasErrors();
        Map<String,String> errorMap=new HashMap<String, String>();
        if(hasErrors)
        {
            List<FieldError> fieldErrors = res.getFieldErrors();
            for(FieldError fieldError:fieldErrors)
            {
                System.out.println("错误消息提示:"+fieldError.getDefaultMessage());
                System.out.println("错误的字段:"+fieldError.getField());
                System.out.println(fieldError);
                System.out.println("----------------------------------------");
                errorMap.put(fieldError.getField(),fieldError.getDefaultMessage());
            }
            model.addAttribute("errorInfo",errorMap);
            System.out.println("有校验错误");
            return "addPage";
        }
        else
        {
            employeeDao.save(employee);
            //返回列表页面,直接重定向到查询所有员工的请求
            return  "redirect:/emps";
        }
    }

jsp页面通过${},从请求域中拿出之前存放的错误信息,显示在页面上

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<html>
<head>
    <title>员工添加页面</title>
</head>
<body>

<%pageContext.setAttribute("ctp",request.getContextPath());%>
<form:form modelAttribute="employee" action="${ctp}/emp" method="post">
    员工id:<form:input path="id"/>${errorInfo.id}<br/><%--取不出来就为空--%>
    姓名:<form:input path="name"/>${errorInfo.name}<br/>
    邮箱:<form:input path="eamil"/>${errorInfo.eamil}<br/>
    性别:<br/>
    :<form:radiobutton path="gender" value="1"/>
    :<form:radiobutton path="gender" value="0"/>
    请选择员工所在的部门:
    <form:select path="department" items="${departments}"/>
    <br/>
    <input type="submit" value="提交">
</form:form>
</body>
</html>

自定义国际化错误消息的显示,Hibernate Validator已经实现了默认的国际化错误消息显示格式

步骤1:编写国际化文件,起名要规范,放在conf资源文件夹下面


注意:国际化文件里面写的key有规定,每一个字段发生错误以后,都会有一个自己的错误代码,国际化资源文件中的错误消息的key必须对应一个错误代码

什么是错误代码:


步骤2:编写国际化配置资源文件

error_en_US.properties.properties:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Email.email=email error--->
NotEmpty=not empty--->
Length.java.lang.String=type is not I want--->

error_zh_CN.properties.properties:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Email.email=邮箱书写的格式有误
NotEmpty=不能为空哦
Length.java.lang.String=长度不合法哦

步骤3:让SpringMVC管理国际化资源文件

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    <!--让SpringMVC管理国际化资源文件-->
    <bean id="messageSource"  class="org.springframework.context.support.ResourceBundleMessageSource">
    <!--basename:指定国际化资源文件的基础名-->
    <property name="basename" value="error"></property>
    <!-- 支持UTF-8的中文 -->
    <property name="defaultEncoding" value="UTF-8"/>
    </bean>

精确优先:同时写了Eamil.eamil和Eamil的错误显示信息,那么先走前者,因为前者更加精确

国际化资源文件支持从JSR-303注解中获取属性的参数值的,例如从@Length注解中,获取min和max属性的值


可以通过注解上的message属性来指定错误消息,如果配置了国际化,先走国际化中配置的

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@NotEmpty(message = "你小子用户名填的有问题呀")
private  String name;

SpringMVC支持ajax

导入jquery的依赖

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    <!--引入jquery的依赖-->
    <dependency>
      <groupId>org.webjars</groupId>
      <artifactId>jquery</artifactId>
      <version>3.3.1-2</version>
    </dependency>
  </dependencies>

导入JackSon的依赖

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    <!--jackSon的依赖-->
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>2.10.0</version>
    </dependency>

    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-core</artifactId>
      <version>2.10.0</version>
    </dependency>


    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>2.10.0</version>
    </dependency>

@JsonIgnore 输出数据的时候,不将当前数据发送给前端

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    @JsonIgnore//输出数据的时候,忽略id字段
private Integer id;

@JsonFormat与@DateTimeFormat注解的配合使用

@JsonFormat与@DateTimeFormat注解的使用


jQuery的each()函数补充知识点

jQuery的each()函数


@ResponseBody注解将服务器端将对象以json对象形式返回,前端收到数据,显示在页面上

ajaxController:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Controller
public class ajaxController {

    @Autowired
    EmployeeDao employeeDao;

    @ResponseBody//将返回的数据放在响应体中,如果返回的是对象,jackson自动将对象转换为json格式
    @RequestMapping("/getAllAjax")
    public  List<Employee> getAjaxAll()
    {
        List<Employee> allEmployees = employeeDao.getAllEmployees();
        return allEmployees;
    }
}

index.jsp:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<% pageContext.setAttribute("ctx",request.getContextPath());%>
<html>
<head>
    <title>JQuery显示页面</title>
</head>
<body>
<script type="text/javascript" src="${ctx}/webjars/jquery/3.3.1-2/jquery.min.js"></script>
<script type="text/javascript">
$("#b1").click(function (){
    //1.发送ajax请求,获取所有员工
    $.ajax(
        {
            url:"${ctx}/getAllAjax",
            type:"get",
            success:function (data)
            {
                $.each(data,function (){
                     var empInfo=data.name+" "+data.department;
                       $("div").append(empInfo);
                })
            }
        }
    )
})
</script>
<button id="b1">ajax请求发送</button>
<div>大忽悠</div>
</body>
</html>

@ReuqestBody获取请求体----只有Post请求才有请求体

ajaxController:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Controller
public class ajaxController {

    @Autowired
    EmployeeDao employeeDao;

    //放在视图解析器进行拼串
    @ResponseBody//将返回的数据放在响应体中,如果返回的是对象,jackson自动将对象转换为json格式
    @RequestMapping("/getAllAjax")
    public  List<Employee> getAjaxAll()
    {
        System.out.println("ajax方法调用");
        List<Employee> allEmployees = employeeDao.getAllEmployees();
        return allEmployees;
    }

    //获取一个请求的请求体
    @RequestMapping("/Body")
    public String testRequestBody(@RequestBody String Body)
    {
        System.out.println("请求体"+Body);
        return "success";
    }
}

index.jsp:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<% pageContext.setAttribute("ctx",request.getContextPath());%>
<html>
<head>
    <title>无标题</title>
</head>
<body>
 <form action="${ctx}/Body" method="post" enctype="multipart/form-data">
     <input name="username" value="大忽悠"/>
     <input type="file" name="file"><%--文件上传--%>
     <button>提交</button>
 </form>
</body>
</html>

将请求体中的数据直接封装为自定义类型对象—@RequestBody

@RequestBody接收json数据,封装为对象(高级用法)

@ResponseBody把对象转换为json数据,返回给浏览器(高级用法)

@RequestBody可以直接将得到的json字符串直接封装为自定义类型对象,前提是自定义对象的属性名和请求参数名一一对应,并且有get和set方法,还有无参构造器

@ResponseBody与@RequestBody注解的用法

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//获取一个请求的请求体,直接封装为people对象
    @RequestMapping("/peo")
    public String getPeople(@RequestBody people p)
    {
        System.out.println("p的值为:"+p);
        return "success";
    }

index.ja

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<% pageContext.setAttribute("ctx",request.getContextPath());%>
<head>
    <title>JQuery显示页面</title>
</head>
<body>
<script type="text/javascript" src="${ctx}/webjars/jquery/3.3.1-2/jquery.js"></script>
<script>
    $(function ()
    {
        $("#b1").click(function (){
            console.log("=====");
            var emp={"name":"大忽悠","age":"18"};
            //打印emp的类型----》是一个json对象
            alert(typeof emp);
            //将这个json对象,转换为一个json形式的字符串
            var stringEmp=JSON.stringify(emp);
            //打印stringEmp的类型----->字符串
            alert(typeof  stringEmp);
            //1.发送ajax请求,获取所有员工
            $.ajax(
                {
                    url:"${ctx}/peo",
                    type:"post",
                    data:stringEmp,
                    //指定要提交的数据格式为json----告诉浏览器
                    contentType:"application/json",
                    success:function (data)
                    {
                        alert(data);
                    }
                }
            )
            return false;
        })
    })
</script>
<a id="b1" href="${ctx}/peo">点击,ajax请求发送</a>
</body>
</html>

在参数位置写HttpEntity< String>,比@RequestBody更强,可以拿到请所有请求头和请求体数据

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    @RequestMapping("/peo")
    public String getPeople(HttpEntity<String>  ret)
    {
        System.out.println(ret);
        return "success";
    }

@ResponseBody加在方法上—》本质是将返回的数据直接塞在请求体中

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    @ResponseBody
    @RequestMapping("/peo")
    public String getPeople(HttpEntity<String>  ret)
    {
        return "<h1>success<h1>";
    }

设置方法返回类型为: ResponseEntity< T >:泛型是响应体数据的类型,可以自定义响应

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    @RequestMapping("/peo")
    public ResponseEntity<String> getPeople(HttpEntity<String>  ret)
    {
        //三个参数: 响应体,响应头,状态码
        String body="Success";
        MultiValueMap<String, String> headers=new HttpHeaders();
        //让浏览器保存一个cookie
        headers.add("Set-Cookie","username=大忽悠");
      return   new ResponseEntity<String>(body,headers,HttpStatus.OK);
    }

SpringMVC中提供的文件下载—较为鸡肋—>ResponseEntity方式

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 @RequestMapping("/peo")
    public ResponseEntity<Byte[]> download(HttpServletRequest request) throws IOException {
        //1.得到要下载的文件的流
        //找到要下载的文件在服务器中的真实路径
        ServletContext context=request.getSession().getServletContext();
        //当前项目路径下的picture包下的pig.img资源
        String realPath=context.getRealPath("/picture/pig.img");
        //获取要下载的文件流---》创建一个要读取的输入流
        FileInputStream is=new FileInputStream(realPath);
        byte[] temp=new byte[is.available()];
        is.read(temp);
        is.close();
        //将要下载的文件流返回给浏览器
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.set("Content-Disposition","attachment;filename="+"pig.img");
        return new ResponseEntity<byte[]>(temp,httpHeaders,HttpStatus.OK);
    }

总结: ResponseEntity响应数据的同时,可以自定义响应头 ,HttpEntity< String>获取响应体数据的同时,获取响应头

对于这些怪异的返回值,视图解析器就不会进行拼串了,具体工作机制,看源码


SpringMVC的文件上传

导入依赖

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    <!--文件上传的依赖-->
    <dependency>
      <groupId>commons-fileupload</groupId>
      <artifactId>commons-fileupload</artifactId>
      <version>1.3.1</version>
    </dependency>
    <dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.5</version>
    </dependency>

文件上传表单准备

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<% pageContext.setAttribute("ctx",request.getContextPath());%>
<head>
    <title>JQuery显示页面</title>
</head>
<body>
<script type="text/javascript" src="${ctx}/webjars/jquery/3.3.1-2/jquery.js"></script>
<form action="${ctx}/upload" method="post" enctype="multipart/form-data">
    用户头像:<input type="file" name="head"/><br/>
    用户名:<input type="text" name="username"/><br/>
    <input type="submit"/>
</form>
结果: ${msg}
</body>
</html>

SpringMVC中配置文件上传解析器

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    <!--文件上传解析器: id必须是multipartFile-->
    <bean  id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <!--设置文件上传最大量为5m-->
        <property name="maxUploadSize" value="5242880"></property><!--spel运算符,计算最大可上传文件体积-->
        <!--设置默认的编码-->
        <property name="defaultEncoding" value="utf-8"></property>
    </bean>

文件上传请求处理

在处理器方法上写一个 @RequestParam(“head”) MultipartFile file,封装当前文件信息,可以直接保存

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Controller
public class uploadController {
         @RequestMapping("/upload")
    public String upload(
                 @RequestParam(value = "username",required = false) String username,
                 @RequestParam("head") MultipartFile file
                 ,Model model)
         {
             System.out.println("上传的文件信息:");
             System.out.println("文件项的name:"+file.getName());
             System.out.println("文件的名字"+file.getOriginalFilename());
           //文件保存
             try {
                 file.transferTo(new File("D:\\dhy\\"+file.getOriginalFilename()));
                 model.addAttribute("msg","文件上传成功");
             } catch (IOException e) {
                 e.printStackTrace();
                 model.addAttribute("msg","文件上传失败");
             }

return "forward:/index.jsp";
         }
}

多文件上传

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Controller
public class uploadController {
         @RequestMapping("/upload")
    public String upload(
                 @RequestParam(value = "username",required = false) String username,
                 @RequestParam(value = "head") MultipartFile[] file1
                 ,Model model)
         {
             System.out.println("上传的文件信息:");
             for(MultipartFile file:file1)
             {
                 if(!file.isEmpty())
                 {
                     try {
                         file.transferTo(new File("D:\\dhy\\"+file.getOriginalFilename()));
                         model.addAttribute("msg","文件上传成功");
                     } catch (IOException e) {
                         e.printStackTrace();
                         model.addAttribute("msg","文件上传失败");
                     }
                 }
             }
return "forward:/index.jsp";
         }

index.jsp

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<% pageContext.setAttribute("ctx",request.getContextPath());%>
<head>
    <title>JQuery显示页面</title>
</head>
<body>
<form action="${ctx}/upload" method="post" enctype="multipart/form-data">
    用户头像:<input type="file" name="head"/><br/>
    用户头像:<input type="file" name="head"/><br/>
    用户头像:<input type="file" name="head"/><br/>
    用户名:<input type="text" name="username"/><br/>
    <input type="submit" value="提交"/>
</form>
结果: ${msg}
</body>
</html>

拦截器

单拦截器运行流程

1.创建拦截器类

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class MyInterceptor implements HandlerInterceptor {

    /**
     * 该方法在目标方法之前被调用.
     * 若返回值为 true, 则继续调用后续的拦截器和目标方法.
     * 若返回值为 false, 则不会再调用后续的拦截器和目标方法.
     *
     * 可以考虑做权限. 日志, 事务等.
     */
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        System.out.println("[MyInterceptor] preHandle");
        return true;
    }

    /**
     * 调用目标方法之后, 但渲染视图之前.
     * 可以对请求域中的属性或视图做出修改.
     */
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
                           ModelAndView modelAndView) throws Exception {
        System.out.println("[MyInterceptor] postHandle");
    }

    /**
     * 渲染视图之后被调用. 释放资源
     */
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception {
        System.out.println("[MyInterceptor] afterCompletion");
    }
}

2.在spingMVC的配置文件中注册这个拦截器的工作,配置这个拦截器来拦截哪些请求的方法

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    <!--测试拦截器-->
    <mvc:interceptors>
        <!--配置某个拦截器,默认是拦截所有请求-->
    <bean class="com.Controller.MyInterceptor"/>
        <!--具体配置某个拦截器-->
  <!--      <mvc:interceptor>
            &lt;!&ndash;只拦截test01请求&ndash;&gt;
            <mvc:mapping path="/test01"/>
            <bean class="com.Controller.MyInterceptor"/>
        </mvc:interceptor>-->
    </mvc:interceptors>

拦截器正常运行流程和其他流程


多个拦截器运行流程

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    <!--测试拦截器-->
    <mvc:interceptors>
        <!--配置某个拦截器,默认是拦截所有请求-->
    <bean class="com.Controller.MyInterceptor"/>
        <!--具体配置某个拦截器-->
        <mvc:interceptor>
            <!--只拦截hello请求-->
            <mvc:mapping path="/hello"/>
            <bean class="com.Controller.MyInterceptor"/>
        </mvc:interceptor>
    </mvc:interceptors>

多拦截器异常运行流程

已经放行了的拦截器的afterCompletion总会执行
目标方法出现异常,postHandle不会执行

国际化

1.创建国际化资源文件夹

error_en_US.properties:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
welcome=welocme page
username=username
password=password

error_zh_CN.properties:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
welcome=登录界面
username=用户名
password=密码

2.配置

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    <!--让SpringMVC管理国际化资源文件,id不能改-->
    <bean id="messageSource"  class="org.springframework.context.support.ResourceBundleMessageSource">
    <!--basename:指定国际化资源文件的基础名-->
    <property name="basename" value="error"></property>
    <!-- 支持UTF-8的中文 -->
    <property name="defaultEncoding" value="UTF-8"/>
    </bean>

3.在页面进行内容替换

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<% pageContext.setAttribute("ctx",request.getContextPath());%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<head>
   <h1>
       <fmt:message key="welcome"/>
   </h1>
</head>
<body>
    <form action="">
        <fmt:message key="username"/>:<input/><br/>
        <fmt:message key="password"/>:<input/><br/>
        <input type="submit" value="提交"/>
    </form>
</body>
</html>

国际化必看注意事项

注意不能直接进入国际化的页面中,因为直接进入某个jsp页面的时候,就相当直接向Tomcat请求页面,没有经过Spring,然而Spring管理的国际化也就不会生效

Idea SpringMVC框架i国际化页面乱码解决方法

SpringMVC国际化实现完整流程,详细介绍

SpringMVC国际化实现 idea


springmvc区域信息是由区域信息解析器得到的


通过MessageSource对象,来获取国际化资源文件中对应key对应的值,也可以获取国际化资源文件中的错误信息

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Controller
public class hello {
    @Autowired
    private MessageSource messageSource;
    @RequestMapping("/hello")
public String hai(Locale locale)
{
    System.out.println(locale);//打印当前区域信息
    String username = messageSource.getMessage("username", null, locale);//第二个参数是占位符数组
    System.out.println("用户名:"+username);
    return "guojihua";
}
}

打印结果为: zh_CN 用户名: 用户名


自定义区域信息解析器----实现点击不同超链接,切换当前页面的语言

MyLocalResolve:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/*自定义区域解析器*/
public class MyLocalResolve implements LocaleResolver {
    //解析返回locale
    public Locale resolveLocale(HttpServletRequest request)
    {
        String localeStr=request.getParameter("locale");
        Locale l=null;
        //如果带了locale参数就用参数指定的区域信息,否则就用请求头的
        if(localeStr!=null&&!"".equals(localeStr))
        {
            l=new Locale(localeStr.split("_")[0],localeStr.split("_")[1]);
        }
        else{
            l=request.getLocale();
        }
        return l;
    }
     //修改locale
    public void setLocale(HttpServletRequest request, HttpServletResponse response, Locale locale)
    {

    }
}

国际化展示页面:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<% pageContext.setAttribute("ctx",request.getContextPath());%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<head>
    <h1>
        <fmt:message key="welcome"/>
    </h1>
</head>
<body>
<form action="">
    <fmt:message key="username"/>:<input/><br/>
    <fmt:message key="password"/>:<input/><br/>
    <input type="submit" value="提交"/>
</form>
<a href="hello?locale=zh_CN">中文</a><br/>
    <a href="hello?locale=en_US">英文</a><br/>
</body>
</html>

hello页面跳转类:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Controller
public class hello {
    @Autowired
    private MessageSource messageSource;
    @RequestMapping("/hello")
public String hai(Locale locale)
{
    System.out.println(locale);//打印当前区域信息
    String username = messageSource.getMessage("username", null, locale);//第二个参数是占位符数组
    System.out.println("用户名:"+username);
    return "guojihua";
}
}

将自定义区域解析器放到容器中,让springMVC使用

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    <!--配置自定义区域信息解析器 id固定-->
    <bean id="localeResolver" class="com.Controller.MyLocalResolve"></bean>

演示效果


完整流程看下面这篇文章

完整流程


SessionLocaleResolver实现点击链接切换国际化----信息从session中获取

SessionLocaleResolver保存客户的Locale到HttpSession对象中,并且支持获取和修改

1.在配置文件中配置使用SessionLocaleResolver

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<!--区域信息从session中获取-->
    <bean id="localeResolver" class="org.springframework.web.servlet.i18n.SessionLocaleResolver"/>

2.在跳转资源hello中获取区域信息,并防止再session域中,让SessionLocaleResolver进行国际化操作实现

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Controller
public class hello {
    @Autowired
    private MessageSource messageSource;
    @RequestMapping("/hello")         //如果有请求参数locale,那么就使用,否则默认为中文
public String hai(@RequestParam(value = "locale",defaultValue = "zh_CN") String localeStr,
                  Locale locale,//这里locale是获取当前请求头里面的区域信息
                  HttpSession httpSession)
{
    Locale l=null;
    //如果带了locale参数就用参数指定的区域信息,否则就用请求头的
    if(localeStr!=null&&!"".equals(localeStr))
    {
        l=new Locale(localeStr.split("_")[0],localeStr.split("_")[1]);
    }
    else{
        l=locale;
    }
     httpSession.setAttribute(SessionLocaleResolver.class.getName()+".LOCALE",l);
    return "guojihua";
}
}

guojihua.jsp

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<% pageContext.setAttribute("ctx",request.getContextPath());%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<head>
    <h1>
        <fmt:message key="welcome"/>
    </h1>
</head>
<body>
<form action="">
    <fmt:message key="username"/>:<input/><br/>
    <fmt:message key="password"/>:<input/><br/>
    <input type="submit" value="提交"/>
</form>
<a href="hello?locale=zh_CN">中文</a><br/>
    <a href="hello?locale=en_US">英文</a><br/>
</body>
</html>

Session的区域信息解析器SessionLocaleResolver配合LocaleChangeInterceptor拦截器使用

1.配置文件中配置解析器和拦截器

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    <!--区域信息从session中获取-->
    <bean id="localeResolver" class="org.springframework.web.servlet.i18n.SessionLocaleResolver"/>
    <mvc:interceptors>
        <!--配置拦截器-->
        <bean id="localeChangeInterceptor" class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor"/>
    </mvc:interceptors>

配置了解析器和拦截器后,其他操作都可以省略

跳转类:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Controller
public class hello {
    @RequestMapping("/hello")       
public String hai()
{
    return "guojihua";
}
}

guojihua.jsp:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<% pageContext.setAttribute("ctx",request.getContextPath());%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<head>
    <h1>
        <fmt:message key="welcome"/>
    </h1>
</head>
<body>
<form action="">
    <fmt:message key="username"/>:<input/><br/>
    <fmt:message key="password"/>:<input/><br/>
    <input type="submit" value="提交"/>
</form>
<a href="hello?locale=zh_CN">中文</a><br/>
    <a href="hello?locale=en_US">英文</a><br/>
</body>
</html>

工作原理


异常处理

@ExceptionHandler()注解使用演示

里面参数可以填数组,每一个参数代表当前处理异常的方法能够处理的异常类型,返回值可以跳转到定制的错误页面

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Controller
public class exception
{
   @RequestMapping("/dhy")
     public String handle01(Integer i)
     {
         System.out.println(10/i);
        return "success";
     }
     //里面参数可以填数组
     //每一个参数代表当前处理异常的方法能够处理的异常类型,返回值可以跳转到定制的错误页面
     @ExceptionHandler({ArithmeticException.class,NullPointerException.class})
     public  String exceptionHandle()
     {
         System.out.println("发生错误");
         //视图解析器拼串
         return "error";
     }
}

index.jsp

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<%@ page contentType="text/html;charset=UTF-8" language="java" %>

<a href="dhy?i=0">点我</a>

error.jsp

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Error</title>
</head>
<body>
error
</body>
</html>

注意事项:

返回ModelAndView,可以将错误信息带给页面

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Controller
public class exception
{
   @RequestMapping("/dhy")
     public String handle01(Integer i)
     {
         System.out.println(10/i);
        return "success";
     }
     //里面参数可以填数组
     //每一个参数代表当前处理异常的方法能够处理的异常类型,返回值可以跳转到定制的错误页面
     @ExceptionHandler({ArithmeticException.class,NullPointerException.class})
     public  ModelAndView exceptionHandle(Exception exception)
     {
        ModelAndView m=new ModelAndView("error");//参数:设置跳转页面
        m.addObject("ex",exception);//将错误信息放到隐含模型中
        return m;
     }
}

error页面:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Error</title>
</head>
<body>
<h1>错误信息为: ${ex}</h1>
</body>
</html>

如果有多个@ExceptionHandler都能处理一个异常,那么精确优先


@ControllerAdvice注解----》表明当前类是集中处理异常的类,可以全局处理异常

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@ControllerAdvice
public class exception
{
    @ExceptionHandler({ArithmeticException.class,NullPointerException.class})
    public  ModelAndView exceptionHandle(Exception exception)
    {
        ModelAndView m=new ModelAndView("error");//参数:设置跳转页面
        m.addObject("ex",exception);//将错误信息放到隐含模型中
        return m;
    }
}

全局异常处理与本类异常处理同时存在,那么本类异常处理优先,不论精确与否


@ResponseStatus标注在自定义异常上,返回一个服务器错误页面,省去做错误页面

ex异常类:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package com.Exception;

import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;

//第一个参数自定义的错误信息,第二个参数是错误显示的状态码
@ResponseStatus(reason = "用户登录异常",value = HttpStatus.NOT_FOUND)
public class ex extends RuntimeException{
private  static  final  long serialVersionUID=1l;
}

hello类:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Controller
public class hello
{
    @RequestMapping("/dhy")
  public String show(String name)
  {
      System.out.println(name);
      if(!name.equals("大忽悠"))
      {
throw new ex();
      }
      return "success";
  }
}

登录页面:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<form action="dhy">
    用户名:<input type="text" name="name"><br/>
    <input type="submit" value="登录"/>
</form>

@ResponseStatus注解工作的前提是,上面没有@ExceptionHandler标注的异常处理方法能处理该异常,否则走@ExceptionHandler标注的异常处理方法


Spring默认的异常如果没人处理,就使用默认的处理方法来进行处理---->DefaultHandlerExceptionResolver


基于SpringMVC.xml配置的异常处理方式-----在处理异常的顺序上,优先级最低

xml配置

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
        <!--exceptionMappings配置哪些异常区哪些页面-->
        <property name="exceptionMappings">
            <props>
                <!--key: 异常全类名 value:要去的页面视图名-->
                <prop key="java.lang.NullPointerException">error</prop>
            </props>
        </property>
        <!--指定错误信息取出时指定的key,默认是exception-->
        <property name="exceptionAttribute" value="ex"></property>
    </bean>

error页面:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Error</title>
</head>
<body>
<h1>错误信息为: ${ex}</h1>
</body>
</html>

Hai:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Controller
public class Hai
{
    @RequestMapping("/dhy")
  public String show(String name)
  {
      String s=null;
      s.length();//引发空指针异常
      return "success";
  }
}

SpringMVC运行流程总结


SpringMVC和Spring整合

如果采用上面的合并配置文件,那么相当于系统一起动只有一个IOC容器,这样一部分报错,整个容器就凉凉


建议SpringMVC和spring分容器操作—》通过区分注解扫描范围来达到效果,各自创建自己的容器,在自己的容器中创建自己扫描到或者配置文件中配置的Bean

需要先禁止掉扫描所有包的默认行为

Spring.xml包扫描配置:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    <context:component-scan base-package="com.service" use-default-filters="false">
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
        <context:exclude-filter type="annotation" expression="org.springframework.web.bind.annotation.ControllerAdvice"/>
    </context:component-scan>

SpringMVC包扫描配置:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    <context:component-scan base-package="com.controller" use-default-filters="false">
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
        <!--第二个是SpringMVC错误控制的注解-->
        <context:include-filter type="annotation" expression="org.springframework.web.bind.annotation.ControllerAdvice"/>
    </context:component-scan>

父子容器概念: SpringMVC作为子容器,而Spring作为父容器

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021/07/22 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
​中科大 & 腾讯微信 & 新加坡国立大学 & 复旦等 将视觉特征与 LLM 的参数空间对齐,LoRA 再升级, 效率更上一层!
大型语言模型(LLM)在大多数自然语言任务上取得了令人鼓舞的性能,并在解决现实世界问题中展现出了强大的泛化能力。从LLM派生出的多模态大型语言模型(MLLM)通过感知现实世界的视觉信息,向人工通用智能(AGI)迈出了一步。因此,感知视觉信息的方式是从LLM向MLLM转变的关键。
AIGC 先锋科技
2024/07/08
4540
​中科大 & 腾讯微信 & 新加坡国立大学 & 复旦等 将视觉特征与 LLM 的参数空间对齐,LoRA 再升级, 效率更上一层!
FastChat——一个用于训练、部署和评估基于大型语言模型的聊天机器人的开放平台
在AI盛起的当下,各类AI应用不断地出现在人们的视野中,AI正在重塑着各行各业。相信现在各大公司都在进行着不同程度的AI布局,有AI大模型自研能力的公司毕竟是少数,对于大部分公司来说,在一款开源可商用的大模型基础上进行行业数据微调也正在成为一种不错的选择。
山行AI
2023/06/26
37.6K0
FastChat——一个用于训练、部署和评估基于大型语言模型的聊天机器人的开放平台
正面硬刚GPT-4V!浙大校友开源多模态大模型LLaVA-1.5,130亿参数8个A100一天训完
9月底,OpenAI宣布ChatGPT多模态能力解禁。多模态GPT-4V的神奇能力让众人惊呼:这就是GPT-4.5吧?
新智元
2023/10/08
3.7K0
正面硬刚GPT-4V!浙大校友开源多模态大模型LLaVA-1.5,130亿参数8个A100一天训完
​浅析多模态大模型的前世今生
前段时间 ChatGPT 进行了一轮重大更新:多模态上线,能说话,会看图!微软发了一篇长达 166 页的 GPT-4V 测评论文,一时间又带起了一阵多模态的热议,随后像是 LLaVA-1.5、CogVLM、MiniGPT-5 等研究工作紧随其后,到处刷屏。大模型的多模态能力到底是怎么来的?今天来分享一下多模态相关的一些工作和个人的理解。
腾讯技术工程官方号
2023/11/01
4.4K0
​浅析多模态大模型的前世今生
Xmodel-VLM | 多模态视觉语言模型,解决高成本难题,实现高效部署 !
近年来,自然语言处理(NLP)与计算机视觉的结合在多模态学习领域引发了重大创新和突破。特别是,如GPT-4V [30] 和 Gemini [39]等先进的视觉语言模型(VLMs)利用文本与视觉数据的协同作用,实现了对世界的先进理解和交互。凭借其强大的能力,它们在各种下游视觉语言任务中表现出色。
AIGC 先锋科技
2024/07/08
5200
Xmodel-VLM | 多模态视觉语言模型,解决高成本难题,实现高效部署 !
赶超Gemini Pro,提升推理、OCR能力的LLaVA-1.6太强了
去年 4 月,威斯康星大学麦迪逊分校、微软研究院和哥伦比亚大学研究者共同发布了 LLaVA(Large Language and Vision Assistant)。尽管 LLaVA 是用一个小的多模态指令数据集训练的,却在一些样本上展示了与 GPT-4 非常相似的推理结果。10 月,LLaVA-1.5 重磅发布,通过对原始 LLaVA 的简单修改,在 11 个基准上刷新了 SOTA。
机器之心
2024/02/06
8750
赶超Gemini Pro,提升推理、OCR能力的LLaVA-1.6太强了
MMFuser 用于精细视觉-语言理解的多模态多层特征融合器 !
近年来,多模态大型语言模型(MLLMs)在人工智能领域(AGI)的研究热点中崭露头角。这些模型通过跨模态互动和学习在理解和表达复杂人类意图方面取得了重要进展。在大型语言模型(LLMs)快速发展的基础上,MLLMs利用预训练的视觉编码器来提取图像特征,并将其与先进的LLMs相结合,展示了在各种视觉语言任务上的显著能力。
AIGC 先锋科技
2024/12/03
4070
MMFuser 用于精细视觉-语言理解的多模态多层特征融合器 !
【论文解读】LLaVA 多模态大模型,微软首创用GPT-4生成多模态指令数据集进行指令微调
在本文中,我们首次尝试使用仅基于语言的GPT-4生成多模态语言-图像指令跟随(instruction following)数据。通过对这些生成数据进行指令调整,我们介绍了LLaVA:Large Language and Vision Assistant,这是一个端到端训练的大型多模态模型,将视觉编码器与LLM连接起来,用于通用目的的视觉和自然语言理解。
唐国梁Tommy
2023/09/01
3.3K0
【论文解读】LLaVA 多模态大模型,微软首创用GPT-4生成多模态指令数据集进行指令微调
开源大语言模型LLMs汇总
大语言模型(LLM)是指使用大量文本数据训练的深度学习模型,可以生成自然语言文本或理解语言文本的含义。大语言模型可以处理多种自然语言任务,如文本分类、问答、对话等,是通向人工智能的一条重要途径。
机器学习AI算法工程
2023/09/04
2.6K0
开源大语言模型LLMs汇总
多模态推理革命!LLaVA-vLLM联合部署实战​​
​随着大语言模型(LLM)在生成式AI产业中广泛应用,如何高效、经济地部署和推理这些庞大的模型,成为每一位开发者和企业面临的核心挑战。尤其是在构建真实的在线AI应用时,性能瓶颈、资源浪费、高昂费用等问题层出不穷。
聚客AI
2025/08/14
6300
多模态推理革命!LLaVA-vLLM联合部署实战​​
高效轻量级LLM | Imp模型,通过低比特量化分辨率和降低实现高通骁龙8Gen3 芯片高性能部署 !
4B规模下能力极高的LMMs。 值得注意的是,作者的Imp-3B模型在所有现有相似规模的轻量级LMMs中表现稳定地超越,甚至超过了13B规模下的最先进LMMs。 通过低比特量化技术和分辨率降低技术,作者的Imp模型可以部署在高通骁龙8Gen3移动芯片上,具有高达约13个 Token /秒的高推理速度。
AIGC 先锋科技
2024/07/08
4320
高效轻量级LLM | Imp模型,通过低比特量化分辨率和降低实现高通骁龙8Gen3 芯片高性能部署 !
小算力LVLMs,gpt4平替
LVLMs是干什么的?其实非常好理解,简单来说就是GPT4o干的事情,输入一张图片和一句话,LVLMs会给出一个回答。GPT4目前是闭源的,目前开源的做法都是想法了接近gpt4的性能。而对于研究人员而言,没有强大的算力的支持,也只能在一些小规模的LVLMs上寻找一些方法上的创新。下面将介绍一种MOE-LLaVA的方法。
Srlua
2025/01/02
1530
小算力LVLMs,gpt4平替
7B模型超越GPT4-V!港科大等发布「图推理问答」数据集GITQA:视觉图可提升推理能力
图神经网络(GNNs)擅长利用图的结构信息进行推理,但它们通常需要特定于领域的调优才能达到峰值性能,这阻碍了它们在不同任务之间的泛化性。
新智元
2024/03/05
3040
7B模型超越GPT4-V!港科大等发布「图推理问答」数据集GITQA:视觉图可提升推理能力
《书生大模型实战营第3期》进阶岛 第4关: InternVL 多模态模型部署微调实践
InternVL 是一种用于多模态任务的深度学习模型,旨在处理和理解多种类型的数据输入,如图像和文本。它结合了视觉和语言模型,能够执行复杂的跨模态任务,比如图文匹配、图像描述生成等。通过整合视觉特征和语言信息,InternVL 可以在多模态领域取得更好的表现
流川疯
2024/08/24
1.2K0
《书生大模型实战营第3期》进阶岛 第4关: InternVL 多模态模型部署微调实践
细粒度视觉处理,MG-LLaVA 多模态大型语言模型,从3.8B到34B,物体识别能力大幅提升 !
多模态大型语言模型(MLLMs)在视觉语言理解、视觉推理、视觉交互和定位方面取得了迅速发展。大多数MLLMs采用预训练的大型语言模型(LLMs)作为基础架构来处理连接的视觉和语言嵌入。以LLaVA [3]作为代表作品,它采用低分辨率(, 等)图像作为输入,并通过MLP投影器将视觉嵌入与文本模态对齐,然后进行指令调整。LLaVA的架构已被后续工作广泛采用,并已应用于各种视觉任务,包括检测、分割和视频理解。
AIGC 先锋科技
2024/07/08
7930
细粒度视觉处理,MG-LLaVA 多模态大型语言模型,从3.8B到34B,物体识别能力大幅提升 !
熔岩羊驼LLaVA来了:像GPT-4一样可以看图聊天,无需邀请码,在线可玩
机器之心报道 编辑:赵阳 尽管 LLaVA 是用一个小的多模态指令数据集训练的,但它在一些示例上展示了与多模态模型 GPT-4 非常相似的推理结果。 GPT-4 的识图能力什么时候能上线呢?这个问题目前依然没有答案。 但研究社区已经等不及了,纷纷自己上手 DIY,其中最火的是一个名为 MiniGPT-4 的项目。MiniGPT-4 展示了许多类似于 GPT-4 的能力,例如生成详细的图像描述并从手写草稿创建网站。此外,作者还观察到 MiniGPT-4 的其他新兴能力,包括根据给定的图像创作故事和诗歌,提供
机器之心
2023/05/01
3120
熔岩羊驼LLaVA来了:像GPT-4一样可以看图聊天,无需邀请码,在线可玩
中山大学 & 华为诺亚实验室提出 HiRes-LLaVA 框架,解决切片的高分辨率LVLM引起的输入碎片化问题 !
近期在大型视觉-语言模型(LVLMs)方面的进展显著提高了视觉-语言任务的能力,促进了理解、推理和交互的改进。早期的LVLMs[34; 82; 44]以低分辨率处理图像,通常是,这限制了它们捕捉详细视觉信息的能力。这种局限性常常导致对图像中物体及其上下文关系的识别不准确[17; 41]。
AIGC 先锋科技
2024/07/31
4920
中山大学 & 华为诺亚实验室提出 HiRes-LLaVA 框架,解决切片的高分辨率LVLM引起的输入碎片化问题 !
打造自己的AIGC应用(一)入门篇
其实细数AI的发展历程非常之久,而让AI的应用一下子出现在人们眼前的其实就是ChatGPT的出现,这意味着AIGC应用已经从概念为王变的非常实用了。伴随着ChatGPT的出现,大量的开源大模型也如雨后春笋一样出现。就现在而言,打造一个自己的AIGC应用已经非常简单了。
LoRexxar
2023/10/17
4.8K1
打造自己的AIGC应用(一)入门篇
多模态GPT:国内发布一款可以在线使用的多模态聊天机器人!快来把玩~
论文: MultiModal-GPT: A Vision and Language Model for Dialogue with Humans 代码: https://github.com/open-mmlab/Multimodal-GPT (包含代码、数据、demo) 作者:OpenMMLab
zenRRan
2023/08/22
6280
多模态GPT:国内发布一款可以在线使用的多模态聊天机器人!快来把玩~
视觉的跨界 Wiki-LLaVA | lmage + Question 的奇妙反应,生成多模态大型语言模型(MLLMs)!
近期,大型语言模型(LLM)在零样本文本任务中展现了令人印象深刻的性能。特别是,近期的研究设计出了能够根据用户指示处理多样任务的模型[6, 30, 41]。在这个背景下,经典的方法是在多种通过自然语言描述的任务上微调模型[7, 34],从而使模型能够吸收外部提供的指示,并促进在多个领域内的强大泛化能力。 在这些进展之后,计算机视觉界开始研究将这些模型扩展到视觉和语言的情境中,从而生成多模态大型语言模型(MLLMs)。在这方面,通过视觉到语言的 Adapter 将视觉特征融合到LLM的主干中,引起了显著的性能提升,使得对需要精心设计的视觉描述的视觉和语言任务能够广泛泛化。
AIGC 先锋科技
2024/07/08
4980
视觉的跨界 Wiki-LLaVA  |  lmage + Question 的奇妙反应,生成多模态大型语言模型(MLLMs)!
推荐阅读
​中科大 & 腾讯微信 & 新加坡国立大学 & 复旦等 将视觉特征与 LLM 的参数空间对齐,LoRA 再升级, 效率更上一层!
4540
FastChat——一个用于训练、部署和评估基于大型语言模型的聊天机器人的开放平台
37.6K0
正面硬刚GPT-4V!浙大校友开源多模态大模型LLaVA-1.5,130亿参数8个A100一天训完
3.7K0
​浅析多模态大模型的前世今生
4.4K0
Xmodel-VLM | 多模态视觉语言模型,解决高成本难题,实现高效部署 !
5200
赶超Gemini Pro,提升推理、OCR能力的LLaVA-1.6太强了
8750
MMFuser 用于精细视觉-语言理解的多模态多层特征融合器 !
4070
【论文解读】LLaVA 多模态大模型,微软首创用GPT-4生成多模态指令数据集进行指令微调
3.3K0
开源大语言模型LLMs汇总
2.6K0
多模态推理革命!LLaVA-vLLM联合部署实战​​
6300
高效轻量级LLM | Imp模型,通过低比特量化分辨率和降低实现高通骁龙8Gen3 芯片高性能部署 !
4320
小算力LVLMs,gpt4平替
1530
7B模型超越GPT4-V!港科大等发布「图推理问答」数据集GITQA:视觉图可提升推理能力
3040
《书生大模型实战营第3期》进阶岛 第4关: InternVL 多模态模型部署微调实践
1.2K0
细粒度视觉处理,MG-LLaVA 多模态大型语言模型,从3.8B到34B,物体识别能力大幅提升 !
7930
熔岩羊驼LLaVA来了:像GPT-4一样可以看图聊天,无需邀请码,在线可玩
3120
中山大学 & 华为诺亚实验室提出 HiRes-LLaVA 框架,解决切片的高分辨率LVLM引起的输入碎片化问题 !
4920
打造自己的AIGC应用(一)入门篇
4.8K1
多模态GPT:国内发布一款可以在线使用的多模态聊天机器人!快来把玩~
6280
视觉的跨界 Wiki-LLaVA | lmage + Question 的奇妙反应,生成多模态大型语言模型(MLLMs)!
4980
相关推荐
​中科大 & 腾讯微信 & 新加坡国立大学 & 复旦等 将视觉特征与 LLM 的参数空间对齐,LoRA 再升级, 效率更上一层!
更多 >
LV.6
阿里算法工程师
目录
  • SpringMVC入门第四部分
  • 自定义类型对象和请求参数的数据绑定流程
  • 自定义类型转换器
    • ConversionService是一个接口,里面通过一个Converter转换器进行工作
    • 步骤1:实现Converter接口,写一个自定义类型转换器
    • 步骤2:Converter是ConversionService中的一个组件,我们需要把Converter放入到ConversionService中
    • 步骤3:将WebDataBinder中的ConversionService设置成我们这个加了自定义类型ConversionService
    • 步骤4:让SpringMVC使用我们的ConversionService
    • 配置文件中实现步骤1:配置出ConversionService
    • 总结三步
  • annotation-driven介绍
  • mvc:annotation-driven和mvc:default对动态和静态资源的影响
    • 当mvc:annotation-driven和mvc:default-servlet-handler都没配置时,只有动态资源能够访问,静态资源访问不了
      • 常见动态资源: @RequestMapping映射的资源,.jsp
      • 常见的静态资源: .html , .js , .img
    • 只加mvc:default-servlet-handler,那么静态资源能访问,动态资源不能访问
    • 只配置mvc:annotation-driven,那么只能访问动态资源,不能访问静态资源
    • mvc:default-servlet-handler和mvc:annotation-driven都配置后,那么静态资源和动态资源都可以访问了
  • 数据格式化之日期格式化
    • ConversionServiceFactoryBean创建的ConversionService组件是没有格式化器存在的
      • 解决方法1:不使用自定义类型的转换器
      • 解决方法2:将自定义类型转换器注册到FormattingConversionServiceFactoryBean,这样就有格式化功能了
      • 后端规定提交的日期格式,不对就报错
      • 后端规定提交的数字格式
  • 数据校验:只做前端校验是不安全的,在重要的数据一定要加上后端校验
    • SpingMVC可以使用JSR303来做数据校验
    • Hibernate Validator是第三方框架实现了JSR303规范
    • 实现步骤:
    • 1.maven管理引入springmvc注解数据校验所需jar包:
    • 2.只需要给javaBean的属性上加上校验注解
    • 3.在SpringMVC封装对象的时候,告诉SpringMVC这个javaBean对象需要校验----@Valid注解
    • 4.如何知道校验结果,给需要校验的javaBean后面紧跟一个BindingResult,这个BindingResult就是封装前一个bean的校验结果
    • 5.根据不同的校验结果决定怎么做
    • 6.将错误信息回显在页面上
  • 普通表单将请求信息放在请求域中去页面获取
    • 通过BindingResult的res对象的 getFieldErrors方法,可以获得当前属性值出现的全部错误,然后通过一个Model对象存储错误信息,放到隐含模型中
    • jsp页面通过${},从请求域中拿出之前存放的错误信息,显示在页面上
  • 自定义国际化错误消息的显示,Hibernate Validator已经实现了默认的国际化错误消息显示格式
    • 步骤1:编写国际化文件,起名要规范,放在conf资源文件夹下面
      • 注意:国际化文件里面写的key有规定,每一个字段发生错误以后,都会有一个自己的错误代码,国际化资源文件中的错误消息的key必须对应一个错误代码
      • 什么是错误代码:
    • 步骤2:编写国际化配置资源文件
    • 步骤3:让SpringMVC管理国际化资源文件
      • 精确优先:同时写了Eamil.eamil和Eamil的错误显示信息,那么先走前者,因为前者更加精确
      • 国际化资源文件支持从JSR-303注解中获取属性的参数值的,例如从@Length注解中,获取min和max属性的值
    • 可以通过注解上的message属性来指定错误消息,如果配置了国际化,先走国际化中配置的
    • SpringMVC支持ajax
    • 导入jquery的依赖
    • 导入JackSon的依赖
    • @JsonIgnore 输出数据的时候,不将当前数据发送给前端
    • @JsonFormat与@DateTimeFormat注解的配合使用
    • jQuery的each()函数补充知识点
    • @ResponseBody注解将服务器端将对象以json对象形式返回,前端收到数据,显示在页面上
    • @ReuqestBody获取请求体----只有Post请求才有请求体
    • 将请求体中的数据直接封装为自定义类型对象—@RequestBody
      • @RequestBody接收json数据,封装为对象(高级用法)
      • @ResponseBody把对象转换为json数据,返回给浏览器(高级用法)
      • @RequestBody可以直接将得到的json字符串直接封装为自定义类型对象,前提是自定义对象的属性名和请求参数名一一对应,并且有get和set方法,还有无参构造器
      • @ResponseBody与@RequestBody注解的用法
    • 在参数位置写HttpEntity< String>,比@RequestBody更强,可以拿到请所有请求头和请求体数据
    • @ResponseBody加在方法上—》本质是将返回的数据直接塞在请求体中
    • 设置方法返回类型为: ResponseEntity< T >:泛型是响应体数据的类型,可以自定义响应
    • SpringMVC中提供的文件下载—较为鸡肋—>ResponseEntity方式
      • 总结: ResponseEntity响应数据的同时,可以自定义响应头 ,HttpEntity< String>获取响应体数据的同时,获取响应头
      • 对于这些怪异的返回值,视图解析器就不会进行拼串了,具体工作机制,看源码
  • SpringMVC的文件上传
    • 导入依赖
    • 文件上传表单准备
    • SpringMVC中配置文件上传解析器
    • 文件上传请求处理
      • 在处理器方法上写一个 @RequestParam(“head”) MultipartFile file,封装当前文件信息,可以直接保存
      • 多文件上传
  • 拦截器
    • 单拦截器运行流程
      • 1.创建拦截器类
      • 2.在spingMVC的配置文件中注册这个拦截器的工作,配置这个拦截器来拦截哪些请求的方法
      • 拦截器正常运行流程和其他流程
    • 多个拦截器运行流程
      • 多拦截器异常运行流程
  • 国际化
    • 1.创建国际化资源文件夹
    • 2.配置
    • 3.在页面进行内容替换
      • 国际化必看注意事项
      • 注意不能直接进入国际化的页面中,因为直接进入某个jsp页面的时候,就相当直接向Tomcat请求页面,没有经过Spring,然而Spring管理的国际化也就不会生效
      • SpringMVC国际化实现完整流程,详细介绍
      • springmvc区域信息是由区域信息解析器得到的
      • 通过MessageSource对象,来获取国际化资源文件中对应key对应的值,也可以获取国际化资源文件中的错误信息
    • 自定义区域信息解析器----实现点击不同超链接,切换当前页面的语言
      • 将自定义区域解析器放到容器中,让springMVC使用
      • 演示效果
      • 完整流程看下面这篇文章
    • SessionLocaleResolver实现点击链接切换国际化----信息从session中获取
      • 1.在配置文件中配置使用SessionLocaleResolver
      • 2.在跳转资源hello中获取区域信息,并防止再session域中,让SessionLocaleResolver进行国际化操作实现
    • Session的区域信息解析器SessionLocaleResolver配合LocaleChangeInterceptor拦截器使用
      • 1.配置文件中配置解析器和拦截器
      • 配置了解析器和拦截器后,其他操作都可以省略
      • 工作原理
  • 异常处理
    • @ExceptionHandler()注解使用演示
    • 里面参数可以填数组,每一个参数代表当前处理异常的方法能够处理的异常类型,返回值可以跳转到定制的错误页面
    • 注意事项:
      • 返回ModelAndView,可以将错误信息带给页面
    • 如果有多个@ExceptionHandler都能处理一个异常,那么精确优先
    • @ControllerAdvice注解----》表明当前类是集中处理异常的类,可以全局处理异常
    • 全局异常处理与本类异常处理同时存在,那么本类异常处理优先,不论精确与否
    • @ResponseStatus标注在自定义异常上,返回一个服务器错误页面,省去做错误页面
    • @ResponseStatus注解工作的前提是,上面没有@ExceptionHandler标注的异常处理方法能处理该异常,否则走@ExceptionHandler标注的异常处理方法
    • Spring默认的异常如果没人处理,就使用默认的处理方法来进行处理---->DefaultHandlerExceptionResolver
    • 基于SpringMVC.xml配置的异常处理方式-----在处理异常的顺序上,优先级最低
      • xml配置
  • SpringMVC运行流程总结
  • SpringMVC和Spring整合
    • 建议SpringMVC和spring分容器操作—》通过区分注解扫描范围来达到效果,各自创建自己的容器,在自己的容器中创建自己扫描到或者配置文件中配置的Bean
    • 父子容器概念: SpringMVC作为子容器,而Spring作为父容器
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档