SpringMVC笔记--4处理请求数据

qt5.14.2+vs2019配置msvc2017编译器 qt5.14.2+vs2019配置msvc2017编译器 在使用qt编译程序时此前一直使用的是自带的MinGW 32-bit和64-bit,现在想使用msvc编译器。本次使用的是qt5.14.2,vs2019,需要配置msvc2017的32-bit和64-bit编译器。 1、首先安装好qt5.14.2和vs2019,其次在visual studio installer选择修改,然后选择msvc2017对应的组件,本次安装的是这两个 2、打开qt creator的工具–选项–kits–编译器,选择Manu 阅读详情

第4章 处理请求数据

下面是可以在请求处理方法中出现的参数类型:

  • javax.servlet.ServletRequest或javax.servlet.http.HttpServletRequest;
  • javax.servlet.ServletResponse或javax.servlet.http.HttpServletResponse;
  • javax.servlet.http.HttpSession;
  • org.springframework.web.context.request.WebRequest或org.springframework.web.context.request.NativeWebRequest;
  • java.util.Locale;
  • java.io.InputStream或java.io.Reader;
  • java.io.OutputStream或java.io.Writer;
  • java.security.Principal;
  • HttpEntity<?>paramters;
  • org.springframework.ui.Model;
  • org.springframework.ui.ModelMap;
  • org.springframework.web.servlet.mvc.support.RedirectAttributes.;
  • org.springframework.validation.Errors;
  • org.springframework.validation.BindingResult;
  • 命令或表单对象;
  • org.springframework.web.bind.support.SessionStatus;
  • org.springframework.web.util.UriComponentsBuilder;
  • 带@PathVariable、@MatrixVariable、@RequestParam、@RequestHeader、@RequestBody或@RequestPart注解的对象;

4.1请求处理方法签名

1) Spring MVC 通过分析处理方法的签名,HTTP请求信息绑定到处理方法的相应形参中。

2) Spring MVC 对控制器处理方法签名的限制是很宽松的,几乎可以按喜欢的任何方式对方法进行签名。

3) 必要时可以对方法及方法入参标注相应的注解( @PathVariable 、@RequestParam、@RequestHeader 等)

4) Spring MVC 框架会将 HTTP 请求的信息绑定到相应的方法入参中,并根据方法的返回值类型做出相应的后续处理。

方法的签名:方法的名字+参数列表

入参:形参

可以直接接收request的参数,以同名的方式直接接收到方法的形参中。该接收方式适用于get和post提交请求方式。

4.2 请求参数@RequestParam注解

在处理方法入参处使用 @RequestParam 可以把请求参数传递给请求方法。如果请求参数名与形参名一致, 则可以省略@RequestParam的指定。但建议写。

@RequestParam ()括号内可以写:

  • value:参数名,请求原来的参数名
  • required:是否必须。默认为 true,表示请求参数中必须包含对应的参数,若不存在,将抛出异常。@RequestParam 注解标注的形参必须要赋值。 必须要能从请求对象中获取到对应的请求参数。可以使用required来设置为不是必须的。 不必须的适合必须有默认值
  • defaultValue:形参默认值,当没有传递参数时使用该值。使用该参数时,自动将required设为false。可以使用defaultValue来指定一个默认值取代null。用的不多

如果传入的是checkbox,java中写@RequestParam("name名") List<类型>即可

4.2.1 实验代码

1) 增加控制器方法

/**
 * @RequestParam 注解用于映射请求参数:
 *       value 用于映射请求参数名称
 *       required 用于设置请求参数是否必须的
 *       defaultValue 设置默认值,当没有传递参数时使用该值
 */
@RequestMapping(value="/testRequestParam")
public String testRequestParam(
    @RequestParam(value="username") String username,
    @RequestParam(value="age",required=false,defaultValue="0") int age){
    
    System.out.println("testRequestParam - username="+username +",age="+age);
    return "success";
}

2) 增加页面链接

<!--测试 请求参数 @RequestParam 注解使用 -->
<a href="springmvc/testRequestParam?username=atguigu&age=10">testRequestParam</a>

4.3 请求头@RequestHeader 注解

RequestParam是获取请求参数的,而RequestHeader 是获取请求头信息的。

1) 使用 @RequestHeader 绑定请求报头的属性值

2) 请求头包含了若干个属性,服务器可据此获知客户端的信息,通过 @RequestHeader 即可将请求头中的属性值绑定到处理方法的入参中

4.3.1 实验代码

//了解: 映射请求头信息 用法同 @RequestParam
@RequestMapping(value="/testRequestHeader")
public String testRequestHeader(
    @RequestHeader(value="Accept-Language") String al){
    
    System.out.println("testRequestHeader - Accept-Language:"+al);
    return "success";
}
<!-- 测试 请求头@RequestHeader 注解使用 -->
<a href="springmvc/testRequestHeader">testRequestHeader</a>

4.4 Rest@PathVariable

在@RequestMapping(value="/{}/{}")

方法(@Pathvarieble)

@RequestMapping(value="/testRESTGet/{id}",method=RequestMethod.GET)//要求的请求方式
public String testRESTGet(@PathVariable(value="id") Integer id){
    System.out.println("testRESTGet id="+id);
    return "success";
}

4.5 @CookieValue

1) 使用 @CookieValue 绑定请求中的 Cookie 值

2) @CookieValue 可让处理方法入参绑定某个 Cookie 值

4.4.1实验代码

1) 增加控制器方法

//了解:@CookieValue: 映射一个 Cookie 值. 属性同 @RequestParam
@RequestMapping("/testCookieValue")
public String testCookieValue(@CookieValue("JSESSIONID") String sessionId) {
    System.out.println("testCookieValue: sessionId: " + sessionId);
    return "success";
}

2) 增加页面链接

<!--测试 请求Cookie @CookieValue 注解使用 -->
<a href="springmvc/testCookieValue">testCookieValue</a>

4.6 使用POJO作为参数

使用场景:原来是多个参数就要多个形参

1) 使用 POJO 对象绑定请求参数值

2) Spring MVC 会按请求参数名和 POJO 属性名进行自动匹配,自动为该对象填充属性值。支持级联属性。如:dept.deptId、dept.address.tel 等

默认保证参数名称和请求中传递的参数名相同

4.5.1实验代码

1) 增加实体类

我们首先由如下的实体类

package com.atguigu.springmvc.entities;
 
public class Address {
 
    private String province;
    private String city;

    //get/set.........
}
-----------------------
package com.atguigu.springmvc.entities;
 
public class User {
    private Integer id ;
    private String username;
    private String password;
    private String email;
    private int age;

    private Address address;// 注意这个属性是个类
    //如果是个list,在jsp中就可以使用[0]的形式
    //get/set 
}

2) 增加控制器方法、表单页面

/**
 * Spring MVC 会按请求参数名和 POJO 属性名进行自动匹配, 自动为该对象填充属性值。
 * 支持级联属性
 *                 如:dept.deptId、dept.address.tel 等
 */
@RequestMapping("/testPOJO")
public String testPojo(User user) {//将URL附带的参数传入user的属性中
    System.out.println("testPojo: " + user);
    return "success";
}

<!-- 测试 POJO 对象传参,支持级联属性 -->
<form action=" testPOJO" method="POST">
    username: <input type="text" name="username"/><br>
    password: <input type="password" name="password"/><br>
    email: <input type="text" name="email"/><br>
    age: <input type="text" name="age"/><br>
    city: <input type="text" name="address.city"/><br><!--支持级联的方式-->
    province: <input type="text" name="address.province"/>
    <input type="submit" value="Submit"/>
</form>

3) 执行结果:

User[id=null ,username=zhansgan,password=,email=.com,age=22]

4) 如果中文有乱码,需要配置字符编码过滤器,且配置其他过滤器之前,

如(HiddenHttpMethodFilter),否则不起作用。(思考method=”get”请求的乱码问题怎么解决的)

	<!-- 配置字符集 -->
	<filter>
		<filter-name>encodingFilter</filter-name>
		<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
		<init-param>
			<param-name>encoding</param-name>
			<param-value>UTF-8</param-value>
		</init-param>
		<init-param>
			<param-name>forceEncoding</param-name>
		<param-value>true</param-value>
		</init-param>
	</filter>
	<filter-mapping>
		<filter-name>encodingFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>

pojo的问题可以参数4.1节

4.7 使用Servlet原生API作为参数

1) MVC 的 Handler 方法可以接受 ServletAPI 类型的参数:

  • HttpServletRequest 常用
  • HttpServletResponse 常用:如果使用它,则处理方法的返回值设置为void即可。
  • HttpSession:
  • java.security.Principal
  • Locale
  • InputStream
  • OutputStream
  • Reader
  • Writer
/**
* 可以使用 Serlvet 原生的 API 作为目标方法的参数 具体支持以下类型
* 
* HttpServletRequest 
* HttpServletResponse 
* HttpSession
* java.security.Principal 
* Locale InputStream 
* OutputStream 
* Reader 
* Writer
* @throws IOException 
*/
@RequestMapping("/testServletAPI")
public void testServletAPI(
   HttpServletRequest request,
   HttpServletResponse response, 
   Writer out) throws IOException {//只要写个形参,就会自动写到形参里
   
   
   System.out.println("testServletAPI, " + request + ", " + response);
   // 可以利用原生API进行请求转发或重定向
   request.getRequestDispatcher("/WEV-INF/views/success.jsp").forward(request,response);
   response.getWriter.println("hello");//写到页面
   out.write("hello springmvc");
   //return "success";
}

--------------------------
@RequestMapping("/testServletAPI")
public String testServletAPI(
   HttpServletRequest request,
   HttpServletResponse response, 
   @CookieValue(value="sessionId",required=false) String sessionId)

<!-- 测试 Servlet API 作为处理请求参数 -->
<a href="springmvc/testServletAPI">testServletAPI</a>

2) 源码参考:AnnotationMethodHandlerAdapter L866

@Override
    protected Object resolveStandardArgument(Class<?> parameterType, NativeWebRequest webRequest) throws Exception {
    HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
    HttpServletResponse response = webRequest.getNativeResponse(HttpServletResponse.class);

    if (ServletRequest.class.isAssignableFrom(parameterType) || 
        MultipartRequest.class.isAssignableFrom(parameterType)) {
        
    	Object nativeRequest = webRequest.getNativeRequest(parameterType);
		if (nativeRequest == null) {
        throw new IllegalStateException(
        "Current request is not of type [" + parameterType.getName() + "]: " + request);
        }
        return nativeRequest;
    }
    else if (ServletResponse.class.isAssignableFrom(parameterType)) {
        
        this.responseArgumentUsed = true;
        Object nativeResponse = webRequest.getNativeResponse(parameterType);
    	if (nativeResponse == null) {
    	throw new IllegalStateException(
    	"Current response is not of type [" + parameterType.getName() + "]: " + response);
    	}
    	return nativeResponse;
    }
    else if (HttpSession.class.isAssignableFrom(parameterType)) {
    	return request.getSession();
    }
    else if (Principal.class.isAssignableFrom(parameterType)) {
    	return request.getUserPrincipal();
    }
    else if (Locale.class.equals(parameterType)) {
    	return RequestContextUtils.getLocale(request);
    }
    else if (InputStream.class.isAssignableFrom(parameterType)) {
    	return request.getInputStream();
    }
    else if (Reader.class.isAssignableFrom(parameterType)) {
    	return request.getReader();
    }
    else if (OutputStream.class.isAssignableFrom(parameterType)) {
    	this.responseArgumentUsed = true;
    	return response.getOutputStream();
    }
    else if (Writer.class.isAssignableFrom(parameterType)) {
    	this.responseArgumentUsed = true;
    	return response.getWriter();
    }
    	return super.resolveStandardArgument(parameterType, webRequest);
    }

    @Override
    protected Object resolveStandardArgument(Class<?> parameterType, NativeWebRequest webRequest) throws Exception {
    	HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
    	HttpServletResponse response = webRequest.getNativeResponse(HttpServletResponse.class);

    	if (ServletRequest.class.isAssignableFrom(parameterType) ||
    	MultipartRequest.class.isAssignableFrom(parameterType)) {
    		Object nativeRequest = webRequest.getNativeRequest(parameterType);
    		if (nativeRequest == null) {
    		throw new IllegalStateException(
    		"Current request is not of type [" + parameterType.getName() + "]: " + request);
    		}
    	return nativeRequest;
    	}
    	else if (ServletResponse.class.isAssignableFrom(parameterType)) {
    		this.responseArgumentUsed = true;
    		Object nativeResponse = webRequest.getNativeResponse(parameterType);
    		if (nativeResponse == null) {
   		 throw new IllegalStateException(
    		"Current response is not of type [" + parameterType.getName() + "]: " + response);
    		}
			return nativeResponse;
    	}
        else if (HttpSession.class.isAssignableFrom(parameterType)) {
        	return request.getSession();
        }
        else if (Principal.class.isAssignableFrom(parameterType)) {
        	return request.getUserPrincipal();
        }
        else if (Locale.class.equals(parameterType)) {
        	return RequestContextUtils.getLocale(request);
        }
        else if (InputStream.class.isAssignableFrom(parameterType)) {
        	return request.getInputStream();
        }
        else if (Reader.class.isAssignableFrom(parameterType)) {
        	return request.getReader();
        }
        else if (OutputStream.class.isAssignableFrom(parameterType)) {
        	this.responseArgumentUsed = true;
        	eturn response.getOutputStream();
        }
        else if (Writer.class.isAssignableFrom(parameterType)) {
        	this.responseArgumentUsed = true;
        	return response.getWriter();
        }
    	return super.resolveStandardArgument(parameterType, webRequest);
}

@ModelAttribure接收请求参数

@ModelAttribure注解放在方法的形参上,用于将多个请求参数封装到一个实体对象,从而简化数据绑定流程,而且自动暴露为模型数据,于视图页面展示时使用。

处理方法的数据绑定

我们知道 Spring会根据请求方法签名的不同,将请求消息中的信息以一定的方式转换并绑定到请求方法的入参中。在请求消息到达真正调用处理方法的这一段时间内, Spring MvC还完成了很多工作,包括数据转换、数据格式化及数据校验等。

1 数据绑定流程剖析

Spring MVC通过反射机制对目标处理方法的签名进行分析,将请求消息绑定到处理方法的入参中。数据绑定的核心部件是 DataBinder,其运行机制描述如图所示

pring mvc主框架将 ServletRequest对象及处理方法的入参对象实例传递给DataBinnder, DataBinder调用装配在 Spring Web上下文中的ConversionService组件进行数据类型转换、数据格式化的工作,将 ServletRequest中的消息填充到入参对象中。然后再调用 Validator组件对已经绑定了请求消息数据的入参对象进行数据合法性校验,并最终生成数据绑定结果 BindingResult对象。 Binding Result包含了已完成数据绑定的入参对象,还包含相应的校验错误对象,Spring MVC抽取BindingResult中的入参对象及校验错误对象,将它们赋给处理方法的相应入参。

后面我们将对数据绑定过程中发生的数据转换、数据格式化及数据校验等工作进行详细的阐述。

2 数据转换

在第5章中,我们已经学习了如何编写并装配自定义属性编辑器的知识。Java标准的Poperty Editor的核心功能是将一个字符串转换为一个Java对象,以便根据界面的输入或配置文件中的配置字符串构造出一个WM内部的Java对象。

但是Java原生的 Property Editor存在以下不足:

  • 只能用于字符串和Java对象的转换,不适用于任意两个Java类型之间的转换
  • 对源对象及目标对象所在的上下文信息(如注解、所在宿主类的结构等)不敏感,在类型转换时不能利用这些上下文信息实施高级转换逻辑

有鉴于此, Spring3.0在核心模型中添加了一个通用的类型转换模块,类型转换模块位于org. springframeworkcoreconvert包中 。Spring希望用这个类型转换体系替换Java标准的 Property Editor。但由于历史原因, Spring将同时支持两者,在Bean配置、 Spring MVC处理方法入参绑定中使用它们。

Conversion Service

ConversionService是 Spring类型转换体系的核心接口,它位于 org.springframework.core.convert包中,亦是该报中的唯一一个接口。ConversionSService接口定义了以下4个方法:

boolean can Convert(Class<? source /ype, Class<> targetType):判断是否可以将一个Java类转换为另一个Java类

Boolean can Convert(TypeDescriptor sourceType, TypeDescriptor targetType):需转换的类将以成员变量的方式出现在宿主类中, TypeDescriptor不但描述了需转换类的信息,还描述了从宿主类的上下文信息:如成员变量上的注解,成员变量是否以数组、集合或M的方式呈现等。类型转换逻辑可以利用这些信息做出各种灵活的控制。
    
<T> T convert(Object source, Class<T> targetType,)将原类型对象转换为目标类型
    
Object convert( Object source, Type Descriptor source Type, Type Descriptor targetType): 对象从原类型对象转换为目标类型对象,此时往往会利用到宿主类中的上下文信息。

第1和第3个接口方法类似于 Property Editor,它不关注类型对象所在的上下文信息,只简单地完成两个类型对象的转换,唯一区别在于这两个方法支持任意两个类型的转换

而第2和第4个接口方法,会参考类型对象所在宿主类的上下文信息,并利用这些信息进行类型转换

可以利用 org.springframeworkcontext.support.ConversionServiceFactoryBean在 Spring的上下文中定义一个 ConversionService。 Spring将自动识别出上下文中的ConversionService,并在Bean属性配置及 Spring MVC处理方法入参绑定等场合使用它进行数据的转换。具体配置如下所示

<bean id="conversionService" class=org.springframework.context.support.ConversionServiceFactoryBean">

该 FactoryBean创建 ConversionService内建了很多的转换器,可完成大多数Java类型的转换工作除了包括将Sing对象转换为各种基础类型的对象外,还包括 String、 Number、Aray、 Collection、Map、 Properties及object之间的转换器。

可通过 ConversionServiceFactoryBean的 converters属性注册自定义的类型转换器,如下所示

<bean id=“conversionService class="org.springframework.context.support.ConversionServiceFactoryBean">
    <property name="converters">
        <list>
            <bean class="com. baobaotao.MyCustomConverter1"/>
            <bean class="com. baobaotao.MyCustomConverter2"/>
        </list>
    </property>
</bean>

在52节中,我们知道,通过 CustomEditor Configurer注册的自定义属性编辑器必须实现 PropertyEditor接口。现在注册到 ConversionServiceFactoryBean中的自定义转换器必须实现哪些接口,并满足哪些约定呢?我们将在接下来的小节中进行说明。

Spring支持哪些转换器

Spring在 org.springframework.core.convert.converter包中定义了3种类型的转换器接口,实现任意一个转换器接口都可以作为自定义转换器注册到 ConversionService-FactoryBean中。这3种类型的转换器接口分别为

  • Converter<S, T>
  • GenericConverter
  • ConverterFactory

首先,我们要了解的转换器接口是 Converter接口,它是 Spring最简单的一个转换器接口,仅包括一个接口方法。接口定义如下

package org.springframework.core.convert.converter;

public interface Converter<S,T>{
    T converter(S source);
}

T converter(S source)负责将S类型的对象转换为T类型的对象。如果希望将一种类型的对象转换为另一种类型及其子类的对象,举例来说,将String转换为 Number及 Number子类( Integer、Long、 Double等)对象,就需要一系列的 Converter,如 StringTolnteger、StringToLong及 StringToDouble等。 Spring提供了一个将相同系列多个“同质” Converter封装在一起的 ConverterFactory接口,定义如下:

package org.springframework.core.convert.converter;

public interface ConverterFactory<S, R>{
    <T extends R> Converter<S, T> getConverter(Class<T> targetType);
}

S为转换的源类型,R为目标类型的基类,而T为扩展于R基类的类型。如Spring的StringToNumberConverterFactory就实现了 ConverterFactory接口,封装了String转换到各种数据类型的Converter。

Converter只是负责将一个类型的对象转换为另一个类型的对象,并没有考虑类型对象所在宿主类上下文的信息,因此并不能完成“复杂”类型转换的工作。 GenericConverter接口会根据源类对象及目标类对象所在宿主类中的上下文信息进行类型转换工作,其接口定义如下

package org.springframework.core.convert.converter;

public interface GenericConverter{
    public Set< ConvertiblePair> getConvertibleTypes();
    Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType);
}

ConvertiblePair封装了源类型和目标类型,组成一个“对子”,而 TypeDescriptor包含了需转换类型对象所在宿主类的信息,因此 Generic Converter的 converto接口方法可以利用这些上下文信息进行类型转换的工作。

ConditionalGenericConverter扩展于 GenericConverter接口,并添加了一个接口方法:

boolean matches(Type Descriptor source Type, TypeDescriptor targetType

在Spring MVC中使用ConversionService

参考类型转换文档:思路为实现Converter接口,然后在xml中配置

四、数据校验

应用程序在执行业务逻辑前,必须通过数据校验保证接收到的输入数据是正确合法的,如代表生日的日期应该是一个过去的时间,工资的数值必须是一个正数。很多时候同样的数据校验会出现在不同的层中,违反了DRY原则,为了避免数据的冗余校验,将验证逻辑和相应的域模型进行绑定,将代码验证的逻辑集中起来管理。

JSR 303是Java为Bean数据合法性校验提供的标准框架,它已经包含在JavaEE 6.0中 ,JSR 303通过在Bean属性上标注类似于@NotNull、@Max等标准的注解指定校验规则,并通过标准的验证接口对Bean进行验证,SpringMVC可通过Hibernate Validator(JSR303的参考实现)进行JSR303校验

Spring拥有自己独立的数据校验框架,同时支持JSR-303标准的校验框架。Spring的DataBinder在进行数据绑定时,可同时调用校验框架完成数据校验工作。在SpringMVC中,可直接通过注解驱动的方式进行数据校验。

Spring的org.springframework.validation是校验框架所在的包,Validator接口拥有以下两个方法:

  • boolean supports(Class<?> clazz):该校验器能够对clazz类型的对象进行校验
  • void validate(Object target,Errors erros):对目标类target进行校验,并将校验错误记录在errors中

LocalValidatorFactoryBean既实现了Spring的Validator接口,也实现了JSR-303的Validator接口,只要再Spring容器中定义一个LocalValidatorFactoryBean,即可将其注入需要数据校验的Bean中。定义一个LocalValidatorFactoryBean非常简单

<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"/>

注意:Spring本身没有提供JSR-303的实现,所以必须将JSR-303的实现者(如Hibernate Validator)的jar文件放到类路径下,Spring将自动加载并装配好JSR 303的实现者。

<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>5.2.0.Final</version>
</dependency>

<mvc:annotaion-driver/>会默认装配好一个LocalValidatorFactoryBean,通过在处理方法的入参上标注@Valid注解即可让SpringMVC在完成数据绑定后执行数据校验工作。

public class User {
    //加入 JSR303 验证注解
    @NotNull
    private Integer id;
    private String name;
    @DateTimeFormat(pattern="yyyy-MM-dd")
    private Date birthday;
    private String address;
        //省略 setter getter......
}

@RequestMapping(value="testConversion",method=RequestMethod.POST)
//此处注意 :@Valid 注解表示其后面的java bean注入需要JSR303验证,如果其验证错误
//那么必须在其后面紧跟一个BindingResult(或Error)类型参数,不可打乱顺序,验证bean和BindingResult间不能有其他参数
public String testConversion(@Valid User user,BindingResult result){
    if(result.hasErrors()){
        for (FieldError error : result.getFieldErrors()) {
            System.out.println(error.getField()+"--"+error.getDefaultMessage());
        }
    }
    System.out.println(user);
    return SUCCESS;
}

在已经标注了JSR-303注解的入参对象前添加@Valid注解,Spring MVC框架在将请求数据绑定到该入参对象之后,就会调用校验框架根据注解声明的校验规则实施校验。

BindingResult紧随校验入参对象之后,成对出现,它们之间不允许有其他入参。

音频链路分析 音频链路分析摘要 本文分析了蓝牙音频设备(BES2700)的音频传输链路,主要包括通话和音乐播放两种场景: 通话链路: 下行:蓝牙接收数据→解码→通过Codec输出到扬声器 上行:麦克风采集→Codec处理→蓝牙编码发送 音乐播放链路: 通过A2DP协议接收高质量音频数据 经过解码、EQ调节等音频处理后输出 系统采用多线程消息机制处理音频任务,通过mailbox传递控制消息,由回调函数处理具体音频数据流。不同应用场景使用不同的蓝牙协议栈(HFP/HSP用于通话,A2DP用于媒体)和编码方式(mSBC/SBC 阅读详情

相关推荐

STM32实战指南:TFTLCD液晶屏驱动与ILI9341应用解析

本文详细解析了STM32驱动TFTLCD液晶屏的实战技巧,重点介绍了ILI9341控制器的硬件连接、寄存器操作及性能优化方法。通过8080并行接口时序分析、GRAM操作优化和DMA传输应用,帮助开发者高效实现液晶屏驱动,适用于工业控制、智能家居等场景。

weixin_26873711的博客 232

HttpServletRequest详解

y

斯客风的博客 1万+

使用Python开发TreeATE的测试脚本常见问题

ImportError: No module named py_compile 找不到 DevLangPython3.dll 以上2个问题都是没有安装正确的Python,当前TreeATE依赖32位Python 2.7版本,暂时不支持Python 3以上版本

蓝白云的专栏 1032

cas 单点登录设置用户信息(二)

cas 3.4登录成功返回用户更多信息。cas登录成功默认返回的只有用户名,  java客户端获取:   AttributePrincipal principal = (AttributePrincipal) request.getUserPrincipal(); String username = principal.getName();   我们的程序中也可能遇到需要得到更多如姓名...

SmileTimLi的博客 5381

【教程4>第1章>第11节】使用MATLAB快速产生批量verilog语句加快FPGA开发

...........如果手动写,那么就非常麻烦,这个时候,我们借助matlab,则可以快速生成上述类型的verilog程序,我们编写如下的MATLAB语句。\n");\n");end。

FPGA/MATLAB学习教程/源码/项目合作开发 1239

解锁 Bootloader 不再难!HyperOS澎湃系统小米与红米手机通用

必要时,可以在工具右上角安装驱动模块,手动安装驱动。解决方法:确保手机升级到最新稳定版,登录同一个小米账号,并在。新机型解锁时需要等待一段时间,通常为 7 天。如果账号安全评分较低,解锁等待时间会更长。如果解锁失败提示权限不足,说明账号存在安全问题。出现这个错误时,通常是因为网络不稳定。如果解锁次数已满,需要等到下个月。解锁后,手机会重启,首次开机会稍微慢一些,等耐心等待即可。按钮,开始解锁过程,注意:解锁会清除手机内所有数据。7次,开启开发者选项。,右键解压到指定文件夹。,使用小米账号登录。

代码简单说 Vue、JAVA、PHP、Node.js 熟练运用,接口、架构、性能全搞定。 7214

getUserPrincipal() 这个方法到底是做什么用的?

getUserPrincipal() 这个方法到底是做什么用的? 2013-07-11 14:35匿名 | 分类:编程语言 | 浏览1518次 我查了资料是说如果用户未能通过认证返回null,通过认证的意思是用户登录吗?然后检验用户是否已经登录? 我有更好的答案 分享到: 按默认排序 | 按时间排序 0条回答 2013-

evilcry2012的专栏 2万+

【华为OD机试真题】4、字符统计及重排 | 机试真题+思路参考+代码解析(C++、Java、Py)

题目描述 >给出一个仅包含字母的字符串,不包含空格,统计字符串中各个字母(区分大小写)出现的次数, 并按照字母出现次数从大到小的顺序。输出各个字母及其出现次数。 如果次数相同,按照自然顺序进行排序,且小写字母在大写字母之前

KJ.JK 3289

HttpServletRequest中getRemoteUser和getUserPrincipal方法

HttpServletRequest是一个接口类,继承自ServletRequest,并且又新增了许多抽象方法,getRemoteUser()方法和getUserPrincipal()方法就在其中。许多web项目中会定义基于HttpServletRequest的实现类,比如shiro中的ShiroHttpServletRequest,该类中对getRemoteUser和getUserPrincip...

weixin_30378623的博客 4988

基于Simulink的光伏+储能家庭能源管理系统仿真

本文通过Simulink建模,分析了家庭光伏+储能系统的优化调度问题。针对光伏发电与用电高峰不匹配导致电费节省有限的问题,构建了包含5kW光伏、10kWh电池和6kW负荷的完整模型,设计了无控、规则控制和24小时经济优化三种策略。仿真结果显示,经济优化策略可使日电费降低32%,光伏自用率从45%提升至89%,尤其在晚高峰时段能显著减少高价购电。文章详细介绍了物理层建模、分时电价实现和控制策略设计方法,并探讨了天气预测、V2H等高级扩展功能,为家庭能源智能管理提供了实用解决方案。

xiaoheshang_123的博客 188

SAP-ABAP:SAP信贷管理核心:CL_UKM_BUPA_FACTORY类完整解析与实践指南

SAP信贷管理核心类CL_UKM_BUPA_FACTORY解析 CL_UKM_BUPA_FACTORY是SAP信贷管理(UKM)模块的核心类,作为业务伙伴信贷数据的中央控制台,它提供: 统一入口:标准化实例化客户/供应商信贷对象 主要功能: 获取单条/批量业务伙伴数据 安全保存数据变更 封装底层数据访问逻辑 典型应用场景: 信贷主数据批量维护 自动化限额调整 订单信贷实时检查 性能优化建议: 使用批量方法替代循环单条处理 合理设置字段选择 实施缓存策略 该类通过简洁API简化复杂信贷操作,是SAP信贷管理开

baidu_35680696的博客 1208

servlet request请求对象常用方法总结

1. request请求对象常用方法: public void doPost(HttpServletRequest request, HttpServletResponse response)             throws ServletException, IOException {         response.setContentType("text/html; chars

燃木刀法 3万+

24、虚拟地理信息系统:技术与应用的全面解析

本文全面解析了虚拟地理信息系统(虚拟GIS)的技术架构与应用前景。文章从地理空间数据的增长出发,探讨了虚拟GIS在地形、建筑、天气等多维度数据的交互式可视化技术,重点介绍了全球层次结构、多分辨率模型、缓存分页机制及交互导航方法。系统已应用于天气分析、城市规划、应急响应等领域,并展望了未来在数据处理、模拟操作、移动可视化及智能城市、文化遗产保护等方向的发展路径与技术挑战。

v4w5x6的博客 88

SpringMVC的请求处理

手动将 RequestMappingHandlerMapping 也注册到 SpringMVC 容器中就可以了,这样 DispatcherServlet 在进行初始化时,就会从容器中同时获得 RequestMappingHandlerMapping 存储到 DispatcherServlet 中名为 handlerMappings 的 List 集合中,对@RequestMapping 注解进行解析。这么复杂繁琐的配置,是不是看上去有点头大?

m0_62943934的博客 2407

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

springMVC处理请求全过程

总的来说,Spring MVC 的请求处理流程是一个经典的 MVC 模式的实现,通过各个组件的配合,实现了请求的接收、处理、响应的完整流程,为开发者提供了一种简单、灵活且可扩展的方式来构建 Web 应用程序。熟悉这些流程和组件对于理解 Spring MVC 的工作原理和实现机制非常重要,有助于更加高效地开发和调试应用程序。

Supreme13的博客 3984

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

SpringMVC 处理 Ajax 请求

SpringMVC 是 Spring 框架的一个模块,它实现了模型-视图-控制器(MVC)设计模式,用于构建 Web 应用程序。SpringMVC 分离了应用程序的不同部分,使得开发更加高效、可维护。Ajax(Asynchronous JavaScript and XML)即异步 JavaScript 和 XML,它允许在不刷新整个页面的情况下,与服务器进行数据交互。通过 Ajax,可以提高用户体验,减少页面加载时间,实现更加流畅的交互效果。通过使用和。

dawn191228的博客 1567

【SpringMVC】请求数据和响应数据的处理

肝了一万字~

Le vent se lève, il faut tenter de vivre 932

SpringMVC处理请求或响应数据

SpringMVC处理请求数据或响应数据: 请求处理方法签名 Spring MVC 通过分析处理方法的签名,HTTP请求信息绑定到处理方法的相应人参中。 Spring MVC 对控制器处理方法签名的限制是很宽松的,几乎可以按喜欢的任何方式对方法进行签名。 必要时可以对方法及方法入参标注相应的注解( @PathVariable 、@Req...

测试 1296

SpringMVC对请求的处理流程

  前言         在没有这些开发框架的传统项目中一般都是使用jsp+Servlet的实现方式,基本上是一个url对应一个Servlet,如果项目比较大的时候就会出现很多的问题,所以,后来出现了strusts、SpringMVC等等一些框架,SpringMVC是我们经常使用到的开发框架,MVC(Model/View/Controller)它是一种设计模式,简化了web开发的工作量,并且很...

xpsallwell的专栏 3208

SpringMVC_处理请求数据

在上一篇博客中说到了@RequestMapping这个注解,那么今天就继续老说说SpringMVC是怎样处理请求数据的。

斗鹰的技术专栏 656

SpringMVC 处理请求原理

SpringMVC 处理请求原理

学习笔记! 1118

SpringMVC处理请求流程

下面是一个常见的SpringMVC处理请求的流程从上面的流程中可以看出核心对象是DispatcherServlet,下面我们根据上面的流程图来分析源码,不过需要先知道一些前置知识。

wsb_2526的博客 1132

SpringMVC 请求处理流程

SpringMVC 请求处理流程 一,如何进行初始化,初始化时做了什么,Filter和Servlet什么时候注入的? 1,springboot启动时onRefresh中会调用,ServletWebServerApplicationContext.createWebServer创建Tomcat 2,启动容器时触发TomcatStarter(实现了ServletContainerInitializer)onStartup方法初始化ServletContextInitializer接口的onStartup方法,第

u011309181的博客 2737

SpringMvc请求与参数处理

入门案例基础上编写BookController和UserController 最终创建好的项目结构如下:把环境准备好后,启动Tomcat服务器,后台会报错:从错误信息可以看出:团队多人开发,每人设置不同的请求路径,冲突问题该如何解决?解决思路:为不同模块设置模块名作为请求路径前置对于Book模块的save,将其访问路径设置对于User模块的save,将其访问路径设置这样在同一个模块中出现命名冲突的情况就比较少了。 问题是解决了,但是每个方法前面都需要进行修改,写起来比较麻烦而且还有很多重复代码,如果/u

几许的博客 1672

Spring 学习总结笔记【十、SpringMVC数据响应与请求】

SpringMVC数据响应与请求

qq_51938362的博客 1322

【SpringMVC应用篇】SpringMVC请求参数接收处理

2、Post方式的Body请求体传参。

输入技术、输出想法 3852

SpringMVC(二)——处理请求和响应请求

一、处理请求 (一)处理请求的方式 1.ModelAndView: 通过setViewName方法 2.不响应: void + @Respository注解 3.直接指定响应页面: 返回值为String类型,返回结果指定跳转地址 4.重定向: 跳转地址前到redirect:前缀即可 5.HttpServletRequest和HttpServletResponse: 形参中声明这两个变量,然后通过相...

Nancy1709的博客 3230
上一篇: SpringMVC笔记--3 REST
下一篇: SpringMVC笔记--5处理响应数据ModelAndView
hancoder
博客等级 码龄9年 4135粉丝 167原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值