component
Service
Repository
Controller
RequestBody
ResponseBody
RestController
Resource
Autowired & Qualifier
RequestMapping
PathVariable
RequestParam
Scheduled
Param
JsonAlias & JsonProperty
JSONType
JSONField
Scope
PostConstruct & PreDestroy
在类上加上注解后,这个时候Spring还不认识它,这个时候需要把这个bean交给Spring来管理。有两种方式可以管理:
<!--基于注解的装配-->
<!--方式一-->
<bean class="com.HelloWorld"/>
<!--方式二-->
<context:component-scan base-package="com"/>
or
<!--如果只想扫描包下的@Controller或其他内容,则设置use-default-filters属性为false-->
<context:component-scan base-package="com" user-default-filters="false">
<context:include-filter type="regex" expression="com.tan.*"/>
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
@component
作用:
Component是一个元注解,带此注解的类看为组件,当使用基于注解的配置和类路径扫描的时候,这些类就会被实例化
Component可以注解其他类注解,如:@Controller @Service @Repository @Aspect
把普通pojo实例化到spring容器中,相当于配置文件中的 <bean id="" class=""/>
位置:
类
属性:
不指定bean的名称,默认为类名首字母小写
指定bean的名称@Component(“xxx”)
细节:
@Component("demo")
public class Demo(){}
ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
Demo demo = (Demo)ctx.getBean("xxx");
@Service
作用:
springvmc采用经典的三层分层控制结构 :业务层
服务,注入dao,用于标注服务层,主要用来进行业务的逻辑处理
位置:
类
属性:
不指定bean的名称,默认为类名首字母小写
指定bean的名称@Service(“xxx”)
@Repository
作用:
springvmc采用经典的三层分层控制结构:持久层
用于标注数据访问层,也可以说用于标注数据访问组件,即DAO组件,实现dao访问
位置:
类
属性:
不指定bean的名称,默认为类名首字母小写
指定bean的名称@Repository(“xxx”)
细节:
先定义一个接口
public interface IIocDao{
public void add();
}
然后实现类
//Dao层中定义了一些接口 表示将Dao类声明为bean
@Repository
public class IocDao implements IIocDao{
public void add(){System.out.println("调用了Dao"); }
}
@Controller
作用:
springvmc采用经典的三层分层控制结构:控制层
使用它标记的类就是一个SpringMvc Controller对象,分发处理器会扫描使用该注解的类的方法,并检测该方法是否使用了@RequestMapping注解。Controller只是定义了一个控制器类,而使用@RequestMapping注解的方法才是处理请求的处理器。
@controller 控制器(注入服务)
位置:
类
细节:
@Controller
public class HelloWorld{
@RequestMapping(value="/demo")
public String printHello() {
return "hello";
}
@Autowried
private IocSerevce service;
public void add(){service.add(); }
}
@RequestBody
示例详细说明: 一定要看!
https://blog.csdn.net/justry_deng/article/details/80972817
作用:
@RequestBody主要用来接收前端传递给后端的json字符串中的数据的(请求体中的数据的);GET方式无请求体,所以使用@RequestBody接收数据时,前端不能使用GET方式提交数据,而是用POST方式进行提交。在后端的同一个接收方法里,@RequestBody与@RequestParam()可以同时使用,@RequestBody最多只能有一个,而@RequestParam()可以有多个。
位置:
形参列表
属性:
当同时使用@RequestParam()和@RequestBody时,@RequestParam()指定的参数可以是普通元素、数组、集合、对象等等(即:当,@RequestBody 与@RequestParam()可以同时使用时,原SpringMVC接收参数的机制不变,只不过RequestBody 接收的是请求体里面的数据;而RequestParam接收的是key-value里面的参数,所以它会被切面进行处理从而可以用普通元素、数组、集合、对象等接收)。即:如果参数时放在请求体中,传入后台的话,那么后台要用@RequestBody才能接收到;如果不是放在请求体中的话,那么后台接收前台传过来的参数时,要用@RequestParam来接收,或则形参前什么也不写也能接收。
如果参数前写了@RequestParam(xxx),那么前端必须有对应的xxx名字才行(不管其是否有值,当然可以通 过设置该注解的required属性来调节是否必须传),如果没有xxx名的话,那么请求会出错,报400。
如果参数前不写@RequestParam(xxx)的话,那么就前端可以有可以没有对应的xxx名字才行,如果有xxx名的话,那么就会自动匹配;没有的话,请求也能正确发送。
这里与feign消费服务时不同;feign消费服务时,如果参数前什么也不写,那么会被默认是@RequestBody的。
细节:
如果后端参数是一个对象,且该参数前是以@RequestBody修饰的,那么前端传递json参数时,必须满足以下要求:
- 后端@RequestBody注解对应的类在将HTTP的输入流(含请求体)装配到目标类(即:@RequestBody后面的类)时,会根据json字符串中的key来匹配对应实体类的属性,如果匹配一致且json中的该key对应的值符合(或可转换为),实体类的对应属性的类型要求时,会调用实体类的setter方法将值赋给该属性。
- json字符串中,如果value为"“的话,后端对应属性如果是String类型的,那么接受到的就是”",如果是后端属性的类型是Integer、Double等类型,那么接收到的就是null。
- json字符串中,如果value为null的话,后端对应收到的就是null。
- 如果某个参数没有value的话,在传json字符串给后端时,要么干脆就不把该字段写到json字符串中;要么写value时, 必须有值,null 或"“都行。千万不能有类似"stature”:,这样的写法,如:
{
"stature":, // 错误
"age":null, // 正确
"name":"" // 正确
}
@RequestBody与前端传过来的json数据的匹配规则
声明:根据不同的Content-Type等情况,Spring-MVC会采取不同的HttpMessageConverter实现来进行信息转换解析。下面介绍的是最常用的:前端以Content-Type 为application/json,传递json字符串数据;后端以@RequestBody模型接收数据的情况。
解析json数据大体流程概述:
Http传递请求体信息,最终会被封装进com.fasterxml.jackson.core.json.UTF8StreamJsonParser中(提示:Spring采CharacterEncodingFilter设置了默认编码为UTF-8),然后在public class BeanDeserializer extends BeanDeserializerBase implements java.io.Serializable中,通过public Object deserializeFromObject(JsonParser p, DeserializationContext ctxt) throws IOException方法进行解析
@ResponseBody
作用:
@ResponseBody的作用其实是将java对象转为json格式的数据。
@ResponseBody 表示该方法的返回结果直接写入 HTTP response body 中,一般在异步获取数据时使用【也就是AJAX】,在使用 @RequestMapping后,返回值通常解析为跳转路径,但是加上 @ResponseBody 后返回结果不会被解析为跳转路径,而是直接写入 HTTP response body 中。 比如异步获取 json 数据,加上 @ResponseBody 后,会直接返回 json 数据。@RequestBody 将 HTTP 请求正文插入方法中,使用适合的 HttpMessageConverter 将请求体写入某个对象。当方法上面没有写ResponseBody,底层会将方法的返回值封装为ModelAndView对象。
假如是字符串则直接将字符串写到客户端,假如是一个对象,此时会将对象转化为json串然后写到客户端。这里需要注意的是,如果返回对象,按utf-8编码。如果返回String,默认按iso8859-1编码,页面可能出现乱码。因此在注解中我们可以手动修改编码格式,例如@RequestMapping(value="/cat/query",produces=“text/html;charset=utf-8”),前面是请求的路径,后面是编码格式。
位置:
通常使用在控制层(controller)的方法上
controller类上
属性:
@ResponseBody
@RequestMapping("/login.do")
public Object login(@RequestBody User loginUuser, HttpSession session) {
user = userService.checkLogin(loginUser);
session.setAttribute("user", user);
return new JsonResult(user);
}
细节:
在使用此注解之后不会再走视图处理器,而是直接将数据写入到输入流中,他的效果等同于通过response对象输出指定格式的数据。
@RestController
@Controller和@RestController的区别?
作用:
Spring中@RestController的作用等同于@Controller + @ResponseBody。
位置:
类
属性:
- 如果只是使用@RestController注解Controller,则Controller中的方法无法返回jsp页面,或者html,配置的视图解析器 InternalResourceViewResolver不起作用,返回的内容就是Return 里的内容。
- 如果需要返回到指定页面,则需要用 @Controller配合视图解析器InternalResourceViewResolver才行。
- 如果需要返回JSON,XML或自定义mediaType内容到页面,则需要在对应的方法上加上@ResponseBody注解。
@Resource
作用:
@Resource(name=“XXX”)//默认按name注入,可以通过name和type属性进行选择性注入,如名称无找到则通过类型注入
如果name属性一旦指定,就只会按照名称进行装配
位置:
字段,setter方法
属性:
@Resource的作用相当于@Autowired,只不过@Autowired按byType自动注入,而@Resource默认按 byName自动注入罢了。@Resource有两个属性是比较重要的,分是name和type,Spring将@Resource注解的name属性解析为bean的名字,而type属性则解析为bean的类型。所以如果使用name属性,则使用byName的自动注入策略,而使用type属性时则使用byType自动注入策略。如果既不指定name也不指定type属性,这时将通过反射机制使用byName自动注入策略。
细节:
@Resource 由jdk提供
@Resource装配顺序
1. 如果同时指定了name和type,则从Spring上下文中找到唯一匹配的bean进行装配,找不到则抛出异常
2. 如果指定了name,则从上下文中查找名称(id)匹配的bean进行装配,找不到则抛出异常
3. 如果指定了type,则从上下文中找到类型匹配的唯一bean进行装配,找不到或者找到多个,都会抛出异常
4. 如果既没有指定name,又没有指定type,则自动按照byName方式进行装配;如果没有匹配,则回退为一个原始类型进行匹配,如果匹配则自动装配;
@Autowired & @Qualifier
作用:
@Autowired 默认是按照byType进行注入的,如果发现找到多个bean,则,又按照byName方式比对,如果还有多个,则报出异常。
@Autowired也可以手动指定按照byName方式注入,使用@Qualifier标签,例如:
@Autowired () @Qualifier ( “baseDao” ) //一般作为@Autowired()的修饰用
位置:
@Autowired 可以对成员变量、方法以及构造函数进行注释,而 @Qualifier 的标注对象是成员变量、方法入参、构造函数入参。
属性:
细节:
@Autowired 由spring提供
@Autowired默认情况下必须要求依赖对象必须存在,如果要允许null值,可以设置它的required属性为false,如:@Autowired(required=false)
@RequestMapping
作用:
使用@RequestMapping 注解映射请求路径
类级别的注解负责将一个特定(或符合某种模式)的请求路径映射到一个控制器上,同时通过方法级别的注解来细化映射,即
根据特定的HTTP请求方法(GET、POST 方法等)、HTTP请求中是否携带特定参数等条件,将请求映射到匹配的方法上
位置:
类,方法
属性:
映射单个URL@RequestMapping("")
或 @RequestMapping(value="")
映射多个URL@RequestMapping({"",""})
或 @RequestMapping(value={"",""})
路径开头是否加斜杠/均可,建议加上,如:@RequestMapping("/hello")
RequestMapping注解有六个属性,下面我们把她分成三类进行说明。
1、 value, method;
value: 指定请求的实际地址,指定的地址可以是URI Template 模式;
method: 指定请求的method类型, GET、POST、PUT、DELETE等;
2、 consumes,produces;
consumes: 指定处理请求的提交内容类型(Content-Type),例如application/json, text/html;
produces: 指定返回的内容类型,仅当request请求头中的(Accept)类型中包含该指定类型才返回;
3、 params,headers;
params: 指定request中必须包含某些参数值是,才让该方法处理。
headers: 指定request中必须包含某些指定的header值,才能让该方法处理请求。
细节:
@RequestMapping 一共有五种映射方式:
1、标准URL 映射
@RequestMapping("/hello")
或@RequestMapping({"/hello","/world"})
2、Ant 风格的 URL 映射
通配符 | 说明 |
---|---|
? | 匹配任何单字符 |
* | 匹配任意数量的字符(含 0 个) |
** | 匹配任意数量的目录(含 0 个) |
例如:
(1)@RequestMapping("/?/hello/")
(2)@RequestMapping("/*/hello")
(3)@RequestMapping("/**/hello")
3、占位符URL 映射
URL 中可以通过一个或多个 {} 占位符映射
例如:@RequestMapping("/user/{userId}/show")
可以通过@PathVariable("")
注解将占位符中的值绑定到方法参数上
/**
* 如果 URL 中的 userId 是纯数字,那么使用 @PathVariable
* 做绑定时,可以根据自己的需求将方法参数类型设置为 Long、Integer、String
*/
@RequestMapping("/user/{userId}/show")
public ModelAndView show(@PathVariable("userId") Long userId) {
// 创建 ModelAndView 对象,并设置视图名称
ModelAndView mv = new ModelAndView("show");
// 添加模型数据
mv.addObject("msg", "User ID:" + userId);
return mv;
}
注意:@PathVariable("") 不能简写为 @PathVariable。因为在正常编译时,Java 类反射对象不包含方法的参数名称。如果在编
译时将Debug 打开(javac -debug=no),方法的参数名称才会记录到类中,此时才能简写,但不建议简写。
4、限制请求方法的URL 映射
在HTTP 请求中最常用的请求方法是 GET、POST,还有其他的一些方法,如:DELET、PUT、HEAD 等
限制请求方法,例如:@RequestMapping(value="/hello", method=RequestMethod.POST)
如需限制多个请求方法,以大括号包围,逗号隔开即可,例如:method={RequestMethod.GET,RequestMethod.POST}
5、限制请求参数的URL 映射
限制请求参数来映射URL,例如:@RequestMapping(value="/user/show", params="userId")
即请求中必须带有userId 参数参数的限制规则如下:
(1)params="userId" //请求参数中必须包含 userId
(2)params="!userId" //请求参数中不能包含 userId
(3)params="userId!=1" //请求参数中必须包含 userId,但不能为 1
(4)params={"userId","userName"} //必须包含 userId 和 userName 参数
//可以通过@RequestParam("") 注解将请求参数绑定到方法参数上
@RequestMapping(value="/user/show",params="userId")
public ModelAndView show(@RequestParam("userId") Long userId) {
// 创建 ModelAndView 对象,并设置视图名称
ModelAndView mv = new ModelAndView("show");
// 添加模型数据
mv.addObject("msg", "User ID:" + userId);
return mv;
}
要注意@PathVariable("") 和 @RequestParam("") 的不同:
@PathVariable("") 是将 URL 中占位符处的值绑定到方法参数上
@RequestParam("") 是将 URL 后的请求参数绑定到方法参数上
@PathVariable
作用:
@PathVariable 映射 URL 绑定的占位符,带占位符的 URL 是 Spring3.0 新增的功能,该功能在SpringMVC 向 REST 目标挺进发展过程中具有里程碑的意义
@PathVariable 可以将 URL 中占位符参数绑定到控制器处理方法的入参中:URL 中的 {xxx} 占位符可以通过@PathVariable(“xxx“) 绑定到操作方法的入参中。
位置:
方法形参
属性:
@PathVariable只支持一个属性value,类型是为String,代表绑定的属性名称。默认不传递时,绑定为同名的形参。 应用时,在@RequestMapping请求路径中,将需要传递的参数用花括号{}括起来,然后,通过@PathVariable(“参数名称”)获取URL中对应的参数值。如果@PathVariable标明参数名称,则参数名称必须和URL中参数名称一致。
//@PathVariable可以用来映射URL中的占位符到目标方法的参数中
@RequestMapping("/testPathVariable/{id}")
public String testPathVariable(@PathVariable("id") Integer id)
{
System.out.println("testPathVariable:"+id);
return SUCCESS;
}
//@Description @PathVariable未标注参数名称,则被注解参数名必须后URL中的一致
//URI 模板 “/owners/{ownerId}” 指定了一个名叫 ownerId的变量。当控制器处理这个请求时,ownerId的值被设置为从 URI 中解析出来。比如,当请求 /viewUser/100 进来时,100 就是 ownerId的值
@RequestMapping("/owners/{ownerId}")
public Map<String, Object> viewUser2(@PathVariable Integer ownerId) {
System.out.println("@PathVariable中 请求参数 ownerId = " + ownerId);
return user;
}
细节:
REST:即 Representational State Transfer。(资源)表现层状态转化。是目前最流行的一种互联网软件架构。它结构清晰、符合标准、易于理解、扩展方便,所以正得到越来越多网站的采用。
1) 资源(Resources):网络上的一个实体,或者说是网络上的一个具体信息。它可以是一段文本、一张图片、一首歌曲、一种服务,总之就是一个具体的存在。可以用一个URI(统一资源定位符)指向它,每种资源对应一个特定的 URI 。要获取这个资源,访问它的URI就可以,因此 URI 即为每一个资源的独一无二的识别符。
2)表现层(Representation):把资源具体呈现出来的形式,叫做它的表现层(Representation)。比如,文本可以用 txt 格式表现,也可以用 HTML 格式、XML 格式、JSON 格式表现,甚至可以采用二进制格式。
3)状态转化(State Transfer):每发出一个请求,就代表了客户端和服务器的一次交互过程。HTTP协议,是一个无状态协议,即所有的状态都保存在服务器端。因此,如果客户端想要操作服务器,必须通过某种手段,让服务器端发生“状态转化”(State Transfer)。而这种转化是建立在表现层之上的,所以就是 “表现层状态转化”。具体说,就是 HTTP 协议里面,四个表示操作方式的动词:GET、POST、PUT、DELETE。它们分别对应四种基本操作:GET 用来获取资源,POST 用来新建资源,PUT 用来更新资源,DELETE 用来删除资源。
@RequestParam
作用:
将请求参数绑定到你控制器的方法参数上
位置:
方法形参
属性:
@RequestParam(value=”参数名”, required=true/false, defaultValue=””)
1)value:请求参数名(必须配置)单一参数时,可简化如下:
/**
* @Description: url参数中的name必须要和@RequestParam("name")一致
*/
@GetMapping("edit1")
public String edit1(@RequestParam("userId") Integer userId, Model model) {
System.out.println("*******************" + userId);
model.addAttribute("userId" , userId);
return "/admin/ronghe/rongheMobileList/edit";
}
/**
* @Description: url参数中的name必须要和@RequestParam("name")一致
* 参数名字不一样
*/
@GetMapping("edit2")
public String edit2(@RequestParam("userId") Integer id, Model model) {
System.out.println("*******************" + id);
model.addAttribute("id" , id);
return "/admin/ronghe/rongheMobileList/edit";
}
(2)required:是否必需,默认为 true,即 请求中必须包含该参数,如果没有包含,将会抛出异常(可选配置)
/**
* @Description: required = true时必须有参数id,否则会报错
* required = false时参数id可不传,默认为null,所以此时参数类型不能为int
*/
@GetMapping("edit3")
public String edit3(@RequestParam(value = "id", required = true) Integer id, Model model) {
System.out.println("*******************" + id);
model.addAttribute("id" , id);
return "/admin/ronghe/rongheMobileList/edit";
}
(3)defaultValue:默认值,如果设置了该值,required 将自动设为 false,无论你是否配置了required,配置了什么值,都是 false;如果没有传该参数,就使用默认值(可选配置)
/**
* @Description: 设置defaultValue值时,required无论设置是何值,都默认为false
*/
@GetMapping("edit4")
public String edit4(@RequestParam(value = "id", required = false, defaultValue = "10") Integer id, Model model) {
System.out.println("*******************" + id);
model.addAttribute("id" , id);
return "/admin/ronghe/rongheMobileList/edit";
}
细节:
如果@requestParam注解的参数是int类型,并且required=false,此时如果不传参数的话,会报错。原因是,required=false时,不传参数的话,会给参数赋值null,这样就会把null赋值给了int,因此会报错。
//接收的参数ids是数组
@PostMapping("delete")
@ResponseBody
public RestResponse delete(@RequestParam(value = "ids[]", required = false) List<Long> ids) {
if (null == ids) {
return RestResponse.failure("ID不能为空" );
}
for (Long id : ids) {
rongheMobileListService.deleteById(id);
}
return RestResponse.success();
}
//接收的参数data是Map<String, Object>
@PostMapping("entry")
@ResponseBody
public RestResponse add(@RequestParam(value = "data[mobile]") String mobile,
@RequestParam(value = "data[pro]") String pro,
@RequestParam(value = "data[realTime]", required = false) String realTime,
@RequestParam(value = "data[sjbm]", required = false) String sjbm,
@RequestParam(value = "data[sjmc]", required = false) String sjmc,
@RequestParam(value = "data[mobBm]", required = false) String mobBm,
@RequestParam(value = "data[mobMc]", required = false) String mobMc,
@RequestParam(value = "data[orderId]", required = false) String orderId,
@RequestParam(value = "data[sn]") String sn,
@RequestParam(value = "data[bakMobile]", required = false) String bakMobile) {
return RestResponse.success();
}
@Scheduled
在线cron表达式生成器:http://cron.qqe2.com/
在线cron执行时间计算: https://tool.lu/crontab/
作用:
spring-quartz定时器注解
位置:
方法
属性:
fixedRate 和 fixedDelay 的区别
fixedRate任务两次执行时间间隔是任务的开始点,而 fixedDelay 的间隔是前次任务的结束与下次任务的开始。
// fixedDelay
// 上一次执行完毕时间点之后多长时间再执行。
@Scheduled(fixedDelay = 5000) //上一次执行完毕时间点之后5秒再执行
// fixedDelayString
// 与fixedDelay 意思相同,只是使用字符串的形式。唯一不同的是支持占位符。
@Scheduled(fixedDelayString = "5000") //上一次执行完毕时间点之后5秒再执行
//占位符的使用(配置文件中有配置:time.fixedDelay=5000):
@Scheduled(fixedDelayString = "${time.fixedDelay}")
void testFixedDelayString() {
System.out.println("Execute at " + System.currentTimeMillis());
}
// fixedRate
// 上一次开始执行时间点之后多长时间再执行。
@Scheduled(fixedRate = 5000) //上一次开始执行时间点之后5秒再执行
// fixedRateString
// 与fixedRate 意思相同,只是使用字符串的形式。唯一不同的是支持占位符。
// initialDelay
// 第一次延迟多长时间后再执行。
@Scheduled(initialDelay=1000, fixedRate=5000) //第一次延迟1秒后执行,之后按fixedRate的规则每5秒执行一次
// initialDelayString
// 与initialDelay 意思相同,只是使用字符串的形式。唯一不同的是支持占位符。
配置方法:
1)在xml里加入task的命名空间
xmlns:task="http://www.springframework.org/schema/task"
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.1.xsd
2)启用注解驱动的定时任务
<task:annotation-driven scheduler="myScheduler"/>
3)配置定时任务的线程池
推荐配置线程池,若不配置多任务下会有问题。
<task:scheduler id="myScheduler" pool-size="5"/>
4)写我们的定时任务
@Scheduled注解为定时任务,cron表达式里写执行的时机
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@Component
public class quartzDemo{
@Scheduled(cron="0/10 * * * * ? ") //每10秒执行一次
public void demo(){ System.out.println("10s exec on time...");}
}
cron
Cron格式中特殊字符说明
注意:
LW:这两个字符可以连用,表示在某个月最后一个工作日,即最后一个星期五。
#:用于确定每个月第几个星期几,只能出现在DayofMonth域。例如在4#2,表示某月的第二个星期三。
@Param
作用:
@Param是MyBatis所提供的(org.apache.ibatis.annotations.Param),作为Dao层的注解,作用是用于传递参数,从而可以与SQL中的的字段名相对应,一般在2=<参数数<=5时使用最佳。
位置:
dao类方法入参
属性:
//在userDAO类中有这么一个函数:
public User selectByNameAndPwd(@Param("userName") String name,@Param("Password") String )
//在其对应的dao.xml文件中的查询语句则为:
select username,password from user where username=${userName} and password=${Password}
例子:
当只有一个参数,传进去一个值也只有一个参数可以匹配。当存在多个参数时,传进去的值就区分不开了,这时可以考虑用Map
public List<Role> findRoleByMap(Map<String, Object> parameter);
xml 配置
<select id="findRoleByMap" parameterType="map" resultType="role">
SELECT id,name FROM t_role
WHERE roleName=#{roleName}
AND note=#{note}
<select>
测试文件
RoleMapper roleMapper = sqlSession.getMapper(RoleMapper.class);
Map<String, Object> parameter = new HashMap<>();
parameter.put("roleName", "剑士");
parameter.put("note", "决战紫禁之巅");
List<Role> roles = roleMapper.findRolesByMap(parameter);
使用@Param
修改接口
public List<Role> findRoleByAnnotation(@Param("roleName") String roleName, @Param("note") String note);
这样就可以直接传入对应的值了。当然也可以使用Java Bean来传递多个参数,定义一个POJO
public class RoleParam {
private String roleName;
private String note;
}
接口变为:
public List<Role> findRoleByBean(RoleParam role);
这样对应的xml文件与1处的区别就在于id和parameterType发生了变化,id对应的方法和parameterType对应该类的权限定名。
而使用更多的场景可能是这样的,对应多个POJO
public List<Role> findRoleByMix(@Param("roleP") RoleParam role, @Param("permissionP") PermissionParam permission);
xml 注意此时并不需要写出parameterType属性,Mybatis会进行自动搜索。
<select id="findRoleByMix" resultType="role">
SELECT id,name FROM t_role WHERE roleName=#{roleP.roleName} AND note=#{rolep.note} AND level=#{permissionP.level}
<select>
细节:
在不使用@Param注解的时候,函数的参数只能为一个,并且在查询语句取值时只能用#{},且其所属的类必须为Javabean,而使用@Param注解则可以使用多个参数,在查询语句中使用时可以使用#{}或者${}
@Param和@RequestParam没有关系
@JsonAlias & @JsonProperty
给出Controller中的测试类:
给出模型中的属性(setter/getter方法没截出来):
使用postman测试一下,示例:
全面的结论:
结论①:@JsonAlias注解,实现:json转模型时,使json中的特定key能转化为特定的模型属性;但是模型转json时,
对应的转换后的key仍然与属性名一致,见:上图示例中的name字段的请求与响应。
以下图进一步说明:
此时,json字符串转换为模型时,json中key为Name或为name123或为name的都能识别。
结论②:@JsonProperty注解,实现:json转模型时,使json中的特定key能转化为指定的模型属性;同样的,模
型转json时,对应的转换后的key为指定的key,见:示例中的motto字段的请求与响应。
以下图进一步说明:
此时,json字符串转换为模型时,key为MOTTO的能识别,但key为motto的不能识别。
结论③:@JsonAlias注解需要依赖于setter、getter,而@JsonProperty注解不需要。
结论④:在不考虑上述两个注解的一般情况下,key与属性匹配时,默认大小写敏感。
结论⑤:有多个相同的key的json字符串中,转换为模型时,会以相同的几个key中,排在最后的那个key的值给模
型属性复制,因为setter会覆盖原来的值。见示例中的gender属性。
结论⑥:后端@RequestBody注解对应的类在将HTTP的输入流(含请求体)装配到目标类(即:@RequestBody后面
的类)时,会根据json字符串中的key来匹配对应实体类的属性,如果匹配一致且json中的该key对应的值
符合(或可转换为)实体类的对应属性的类型要求时,会调用实体类的setter方法将值赋给该属性。
@JSONType
作用:
定制序列化JSON
位置:
类
属性:
放在实体类中就会只装配列举的字段
@JSONType(includes = {"name","sex"}) //只装配 name, sex
@JSONType(ignores ={"id", "sex"}) // 忽略 id , sex
@JSONType(orders={"id", "name", "sex"}) // 按照顺序装配
@JSONField
作用:
改变JSON输出的属性
位置:
方法(method),属性(field)以及方法中的参数(parameter)
属性:
JSONField中的name属性用来指定JSON串中key的名称
// @JSONField作用在Field时,其name不仅定义了输入key的名称,同时也定义了输出的名称。
public class Person {
@JSONField(name = "name") // 注意观察生成的JSON串中name和age的区别
private String name;
@JSONField(name = "AGE")
private String age;
public String getName() { return name; }
public void setName(String name) {this.name = name; }
public String getAge() {return age;}
public void setAge(String age) {this.age = age;}
}
// @JSONField也可以直接作用在get或set方法上
@JSONField(name = "name")
public String getName() {return name;}
@JSONField(name = "name")
public void setName(String name) {this.name = name;}
@JSONField(name = "AGE")
public String getAge() {return age;}
@JSONField(name = "AGE")
public void setAge(String age) {this.age = age;}
// FastJson在进行操作时,是根据getter和setter的方法进行的,并不是依据Field进行。
demo
public class PersonTest {
private Person person;
/**
* 初始化对象
*/
@Before
public void setUp() {
person = new Person();
person.setName("gyl");
person.setAge("20");
}
@Test
public void test() {
String jsonStr = JSONObject.toJSONString(person);
System.out.println("bean to json:" + jsonStr);
person = JSONObject.toJavaObject(JSONObject.parseObject(jsonStr), Person.class);
System.out.println("json to bean:" + person.getName());
}
}
///
Output:
bean to json:{"AGE":"20","name":"gyl"}
json to bean:gyl
JSONField默认支持的类型
public @interface JSONField {
int ordinal() default 0;
String name() default "";
String format() default "";
boolean serialize() default true;
boolean deserialize() default true;
SerializerFeature[] serialzeFeatures() default {};
Feature[] parseFeatures() default {};
String label() default "";
boolean jsonDirect() default false;
Class<?> serializeUsing() default Void.class;
Class<?> deserializeUsing() default Void.class;
String[] alternateNames() default {};
boolean unwrapped() default false;
}
format规定日期格式
@JSONField(format="yyyy-MM-dd HH:mm:ss")
private Date date;
ordinal规定字段的顺序
@JSONField(ordinal = 3)
private int f0;
@JSONField(ordinal = 2)
private int f1;
@JSONField(ordinal = 1)
private int f2;
//fastjson序列化⼀个java bean,是根据fieldName的字母序进⾏序列的你可以通过ordinal指定字段的顺序。
serialize/deserialize指定字段不序列化
@JSONField(serialize=false)
public Date date;
@Scope
作用:
@Scope注解是springIoc容器中的一个作用域,在 Spring IoC 容器中具有以下几种作用域:
基本作用域singleton(单例)、prototype(多例),Web 作用域(reqeust、session、globalsession),自定义作用域
@Scope(“singleton”)
位置:
类
属性:
a.singleton单例模式 – 全局有且仅有一个实例
b.prototype原型模式 – 每次获取Bean的时候会有一个新的实例
c.request – request表示该针对每一次HTTP请求都会产生一个新的bean,同时该bean仅在当前HTTP request内有效
d.session – session作用域表示该针对每一次HTTP请求都会产生一个新的bean,同时该bean仅在当前HTTP session内有效
e.globalsession – global session作用域类似于标准的HTTP Session作用域,不过它仅仅在基于portlet的web应用中才有意义
直接在bean对象方法上增加@Scope注解就可以如下:
@Scope注解默认的singleton实例,singleton实例的意思不管你使用多少次在springIOC容器中只会存在一个实例,演示如下只打印了一次创建实例:
细节:
几乎90%以上的业务使用singleton单实例就可以,所以spring默认的类型也是singleton,singleton虽然保证了全局是一个实例,对性能有所提高,但是如果实例中有非静态变量时,会导致线程安全问题,共享资源的竞争
当设置为prototype时:每次连接请求,都会生成一个bean实例,也会导致一个问题,当请求数越多,性能会降低,因为创建的实例,导致GC频繁,gc时长增加
Spring 只帮我们管理单例模式 Bean 的完整生命周期,对于 prototype 的 bean ,Spring 在创建好交给使用者之后则不会再管理后续的生命周期。
@PostConstruct & @PreDestroy
了解即可,详细:https://blog.csdn.net/tuesdayma/article/details/80532867
PostConstruct相当于init-method,使用在方法上,当Bean初始化时执行。
PreDestroy相当于destory-method,使用在方法上,当Bean销毁时执行。
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
@Component
public class MyUtils {
private static MyUtils taticInstance = new MyUtils();
@Autowired
private MyMethorClassService myService;
@PostConstruct
public void init(){
staticInstance.myService = myService;
}
@PreDestroy
public void destory(){
}
}