参考文章
注解位置
注解可以放在方法头上,也可以放在方法限定符后面
@RequestMapping(value="/testuploadimg", method = RequestMethod.POST) public @ResponseBody String uploadImg() {}
@ReponseBody
- 返回json字符串或json对象。
- 在SpringMvc中当返回值是String时,如果不加此注解则Spring就会找这个String对应的页面,找不到则报404错误。
- 如果加上的话@ResponseBody就会把返回值放到response对象中
@RequestBody
- 提取json形式的入参中的属性绑定到同名属性上。
例如:
$.ajax({ url:"/login", type:"POST", data:'{"userName":"admin","pwd","admin123"}', content-type:"application/json charset=utf-8", success:function(data){ alert("request success ! "); } }); @requestMapping("/login") public void login(@requestBody String userName,@requestBody String pwd){ System.out.println(userName+" :"+pwd); }
- 以上情况是将json中的两个变量赋给了同名的字符串,假如有一个User类,拥有userName和pwd两个属性,则上述参数形式可以改为:@RequestBody User user。
- @RequestBody注解常用来处理content-type不是默认的application/x-www-form-urlcoded编码的内容,比如说:application/json或者是application/xml等。一般情况下来说常用其来处理application/json类型。
- 在一些特殊情况下@RequestBody也可以用来处理content-type类型为application/x-www-form-urlcoded的内容,比如jQuery easyUI的datagrid请求数据的时候、小型项目值创建一个pojo类的话也可以。
@Autowired
加在属性上
- 自动注入bean
在声明变量语句前加上该注释,即完成了免new直接实例化(免new的意思是前面已通过@Configuration(+@Bean)或者@Component注册好bean了)
@Autowired private Car BMW;
- 默认先byType,找Car类的bean,如果找到多个bean,则按照byName方法比对找名为BMW的bean,如果还有多个,则抛出异常。
- 使用@Qualifier才可以手动指定先byName方式注入,由于Spring搞成的bean默认都是类名小写,所以一般这里的值都是类名小写。
//通过此注解完成查找满足Fruit的bean,然后找到指定的pear
@Autowired
@Qualifier("pear")
public Fruit fruit;
- 如果要允许null值,可以设置它的required属性为false,如:@Autowired(required=false)。这样找不到bean时不会报错而是赋予null。
- 默认单例模式,在不同的类里用此注解注入的同类的bean都是同一个。
- required属性:默认required=true,若设为false则表示被注解的属性即使找不到对应的bean来装配也没事,不用报错,程序照常执行。
加在方法上
同样也是注入bean,加载方法上则方法会被自动调用,方法参数则被自动装配
public class TextEditor { //一个自定义的类 private SpellChecker spellChecker; @Autowired //自动装配,这个方法被自动调用 public void setSpellChecker(SpellChecker spellChecker){ //被调用后实例化一个SpellChecker this.spellChecker = spellChecker; //赋予类属性 } //直接调用这个方法,其中spellChecker由于上面setSpellChecker被自动调用所以已经实例化了 public void spellCheck() { spellChecker.checkSpelling(); } }
@Resource
- 和@Autowired相似,只是默认装配优先规则不同,并且@Resource是J2EE的注解,是Java自己的东西。因此建议使用@Resource,以减少代码和Spring之间的耦合。
- 默认byName自动注入(用byName会快一点),如果找不到再byType,再找不到则抛异常,无论按那种方式如果找到多个则抛异常。
- 可以手动指定bean,它有2个属性分别是name和type,使用name属性,@Resource(name=”bean名字”),则使用byName的自动注入,从上下文查找名称(id)匹配的bean注入;而使用type属性,@Resource(type=”bean的class”)则使用byType自动注入。
不能用于注入静态属性
public class Zoo { @Resource(name = "tiger") private Tiger tiger; @Resource(type = Monkey.class) private Monkey monkey; public String toString() { return tiger + "\n" + monkey; } }
- 默认单例模式,在不同的类里用此注解注入的同类的bean都是同一个。
在service层我们经常定义接口,然后写实现类,然后搞成bean的是实现类,但是我们用本注解引入这个bean时,只能将类型声明为接口,而不能是实现类:
@Resource private UserService userService; //不能是UserServiceImpl
- 否则报错:Can not set field to $Proxy;不知道@Autowired是不是这样的。
一定要用实现类的话可以在配置文件加入:
<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"/> <!--或者--> <aop:config proxy-target-class="true">
@SpringBootApplication
- 包含下面三个注解
@Configuration
- 定义配置类,可替换xml配置文件,被注解的类内包含被@Bean注解的方法,这些方法即注册了bean。
@Configuration
public class MockConfuration{
属性
方法
}
- 以上代码相当于把该类作为spring的xml配置文件中的
(默认单例),作用为配置spring容器(上下文) - 被注解的类不可以是final类型,不可以是匿名类,嵌套的@Configuration必须是静态类。
- 类中任何一个标注了@Bean的方法,其返回值将作为一个bean注册到spring的IOC容器,方法名则为其实例化对象
@Configuration
public class MockConfuguration{
@Bean(name="...") //指定bean名称默认为方法名
public MockService mockService(){//假定MockService是一个接口
return new MockServiceImpl();//MockServiceImpl是其实现类,它未加任何注解
}
}
相当于xml中的
,作用为注册bean对象。 @Bean相当于下面配置
- 在类内立即使用这个bean
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
/**
* 注册bean
*/
@Bean
private UserDetailsService loginService() {
return new LoginServiceImpl();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(loginService());//执行这个方法,注册bean后作为方法参数使用
}
}
- 表达bean与bean之间的依赖关系
- @Bean不能单独使用,应搭配@Configuration、@Component、@Controller、@Service、@Ripository使用。
- SpringBoot项目的config包就经常用这种方式来注册bean。
- 也可以用@Configuration+@Component来注册bean
/*bean类*/
@Component //添加注册bean的注解
public class TestBean {
}
/*配置类*/
@Configuration
@ComponentScan(basePackages = "com.dxz.demo.configuration") //自动扫描TestBean包路径搞成bean
public class TestConfiguration {
}
因为扫描的话会把整个包的类都搞成bean,所以只想把一个搞成bean的话,可以直接用第一种方法,或者只在那个类上加@Component、@Controller、@Service、@Ripository注解;如果确实都要搞成bean那肯定是第二种方法更适合。
spring4.0之二:@Configuration的使用:详细介绍了bean的注册原理与多种方式。
@ComponentScan
- @ComponentScan(“包路径”):等价于<context:component-scan base-package=”com.dxz.demo”/>,扫描指定包下的所有类,发现带@Controller,@Service,@Repository,@Component注解的都会搞成bean,如果这些注解都没有指定bean名的话默认用类名首字母小写。默认扫描和被注解类所在包及all子包。
- springboot工程启动时,由于入口类有这个注解,所以会默认加载和入口类所在目录及子目录下的所有类,所以一般情况下这些类都不用再加@ComponentScan。
- spring的话一般会写一个配置类加上该注解,负责扫描工程所有的bean,或者在配置文件指定扫描路径
- 写一个类
package com.study.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
@Configuration //必须与此连用
@ComponentScan(basePackages={"com.study"},
excludeFilters={@Filter(type=FilterType.ANNOTATION,
value=EnableWebMvc.class)})
public class RootConfig {
}
- 然后不知道是不是要在bean那边new一下这个类
- 参考文章
@EnableAutoConfiguration
- 像一只八爪鱼一样搜集所有的@Configuration配置,加载到springboot的IOC容器中
@Component
- 一种通用名称,泛指可以通过spring来管理的组件。加在类上以被扫描到并搞成bean,默认直接类名小写
- @Controller,@Service,@Repository则是一种特定的组件,通常用来表示某种场合下的组件。比如@Repository用来表示仓库(数据层,dao);@Service则用来表示服务层相关的类;@Controller则用来表示展示层(控制层)的类;不是前三种一般就用@Component了。
注解在类上之后通过配置文件制定路径来扫描(或者写个能扫描的java类)并搞成bean;如果最后还是被配置文件中的bean节点依赖的话,那么也可以不用注解
<!-- 自定义拦截器 --> <beans:bean id="securityInterceptor" class="com.ultrapower.me.util.security.interceptor.SecurityInterceptor"> <beans:property name="securityMetadataSource" ref="secureResourceFilterInvocationDefinitionSource" /> </beans:bean> <!-- 获取访问url对应的所有权限 --> <beans:bean id="secureResourceFilterInvocationDefinitionSource" class="com.ultrapower.me.util.security.interceptor.SecureResourceFilterInvocationDefinitionSource" /> //配置class属性,那么会自动到该路径去扫描并搞成bean
@Service(“name”):指定搞成的bean名
@PostConstruct和@PreDestroy
- 实现初始化和销毁之前进行的操作。分别只能注释一个方法,且该方法不能有参数,返回值必须是void,方法不能是静态的。
@Primary
- 自动装配当出现多个bean候选者时,被注解的将作为首选者,无注解将抛出异常
@Named
@Named和Spring的@Component功能相同。@Named可以有值,如果没有值生成的Bean名称默认和类名相同。
@Named public class Person; //或 @Named("cc") public class Person;
@RequestParam
接收请求中的参数
//将请求中参数为number映射到方法的number上,required=false表示该参数不是必需的,请求上可带可不带;若为必需,则请求中没有相应参数会导致404错误;defaultValue:默认值,表示如果哦请求中没有同名参数时的默认值 @RequestParam(value="number",required=false,defaultValue="0") String number;
- 其实不写也是接收得到的,只是有时候作为一个标志或者需要它的某些属性
- 如果参数是int类型并且required=false的话,建议以Integer变量接收,因为这时如果不传参数值会把null赋值给int,会报错。
@PathVariable
- 将@RequestMapping指定的请求所带的参数映射到方法的参数上
@RequestMapping("/zyh/{type}")
//传入参数type,其值来自/zyh/{type}请求所带的名为type的参数,其实括号中不写也行
public String zyh(@PathVariable(value="type") int type) {
}
- 和@RequestParam类似
@ResponseBody
- 自动把被注解的类中的方法的返回值中的java对象(Map或JSONObject等)转为json串,前台才能解析
- 可标注在方法上面或方法返回值类型前面
- 相当于ajax请求,不用指明返回哪个页面,会自动从来的地方回去
@RequestBody
- 将前台传来的json串转为java对象,后台才能处理。
- 前台传参格式有两种,一种是跟在url后面的键值对,一种是json串。
@Param
给参数命名
@Query("from User u where u.name=:username") User findUser(@Param("username") String name1); //给name1命名为username,使入参被u.name=:username识别 //@Param中的值必须和冒号后一样,至于形参和实参叫做什么就不重要了
@ConfigurationProperties
- 可以把配置文件中指定前缀的变量全部封装到类的实例中
- 要配合@Component使用,因为不需保证注释的类能被Spring扫描到,不然Spring扫描到此注解也不知道装配到哪个类里去
- 使用方式有两种
第一种:加在类上
@Component @ConfigurationProperties(prefix = "com.example.demo") public class People { private String name; private Integer age; private List<String> address; private Phone phone; //只有一个String类的number属性 }
application.properties中的变量
com.example.demo.name=${aaa:hi} com.example.demo.age=11 com.example.demo.address[0]=北京 com.example.demo.address[1]=上海 com.example.demo.address[2]=广州 com.example.demo.phone.number=1111111
大功告成,实例化
@Resource private People people;
- 第二种:通过@Bean的方式声明,这里我们加在入口类即可
@SpringBootApplication
public class DemoApplication {
@Bean
@ConfigurationProperties(prefix = "com.example.demo")
public People people() {
return new People();
}
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
大功告成,实例化
@Resource private People people;
- PS:如果发现@ConfigurationPropertie不生效,有可能是项目的目录结构问题,你可以通过@EnableConfigurationProperties(People.class)来明确指定需要用哪个实体类来装载配置信息。
@RequestMapping
- @RequestMapping(value=”/produces”,produces=”application/json”):表示注解方法将返回json格式的数据,此时若请求头中的Accept为application/json则可匹配。
@RequestMapping(value="/queryLearnList",method=RequestMethod.POST,
produces = "application/json;charset=utf-8")
//produces:指定返回值类型和字符集,不过使用了@ResponseBody的话就不用指定返回值了
- 支持通配符和ant风格的路径:
@RequestMapping(value = { "", "/page", "page*", "view/*,**/msg" })
匹配url如下:
- localhost:8080/home
- localhost:8080/home/
- localhost:8080/home/page
- localhost:8080/home/pageabc
- localhost:8080/home/view/
- localhost:8080/home/view/view
配合属性headers=”Accept=application/json”更能表明你的目的。
- value值可以是含有变量或正则表达式的一类值
@RequestMapping("/preUpdate/{id}") //请求方式:/preUpdate/1
@RequestMapping(
"/spring-web/{symbolicName:[a-z-]+}-{version:\d\.\d\.\d}.{extension:\.[a-z]}"
)
- method属性默认为无,也就是什么类型的HTTP请求都可以映射。
@PostConstruct
Java EE 5引入的注解,Spring允许开发者在受管Bean中使用它。当DI容器实例化当前受管Bean时,@PostConstruct注解的方法会被自动触发,从而完成一些初始化工作。
@Component public class MySecurityMetadataSource implements FilterInvocationSecurityMetadataSource { @Resource private ResourcesDao resourcesDao; private static Map<String, Collection<ConfigAttribute>> resourceMap = null; public Collection<ConfigAttribute> getAllConfigAttributes() { return null; } public boolean supports(Class<?> clazz) { return true; } /** * @PostConstruct是Java EE 5引入的注解, * Spring允许开发者在受管Bean中使用它。当DI容器实例化当前受管Bean时, * @PostConstruct注解的方法会被自动触发,从而完成一些初始化工作 */ @PostConstruct private void loadResourceDefine() { //加载所有资源与权限的关系 if (resourceMap == null) { resourceMap = new HashMap<String, Collection<ConfigAttribute>>(); List<Resources> list = resourcesDao.queryAll(new Resources()); for (Resources resources : list) { Collection<ConfigAttribute> configAttributes = new ArrayList<ConfigAttribute>(); // 通过资源名称来表示具体的权限 注意:必须"ROLE_"开头 ConfigAttribute configAttribute = new SecurityConfig("ROLE_" + resources.getResKey()); configAttributes.add(configAttribute); resourceMap.put(resources.getResUrl(), configAttributes); } } } //返回所请求资源所需要的权限 public Collection<ConfigAttribute> getAttributes(Object object) throws IllegalArgumentException { String requestUrl = ((FilterInvocation) object).getRequestUrl(); // System.out.println("requestUrl is " + requestUrl); if(resourceMap == null) { loadResourceDefine(); } //System.err.println("resourceMap.get(requestUrl); "+resourceMap.get(requestUrl)); if(requestUrl.indexOf("?")>-1){ requestUrl=requestUrl.substring(0,requestUrl.indexOf("?")); } Collection<ConfigAttribute> configAttributes = resourceMap.get(requestUrl); return configAttributes; } }
- 参考文章
@PropertySource、@Value
- @PropertySource({“classpath:jdbc.properties”}):注解在类头上,加载资源文件
- 然后在类内属性头上
/*
* 绑定资源属性
*/
@Value("${jdbc.driver}")
private String driverClass="hhh"; //无论此处赋值为何,都会被@Value覆盖
//设置默认值
@Value("${some.key:my default value}") //默认值也可设为空:${some.key:}
private String stringWithDefaultValue;
//数组的默认值用逗号分隔
@Value("${some.key:1,2,3}")
private int[] intArrayWithDefaults;
- 不过有一个例子,它没有指定配置文件,直接注入,好像也可以,代码:ideaProjects/shiro-chapter16/service/impl/PasswordHelper、resources/spring-config.xml。
@RestController
- 相当于@ResponseBody+@Controller合在一起,规定类中所有方法返回值被转换为json字符串传回前端
@ModelAttribute
- 作用在参数上,将客户端请求中的参数按名称注入到指定对象中,并将此对象作为传送数据存入ModelMap,便于在前端页面取用。
public String test1(@ModelAttribute("user") User user){}
- 将user以“user”为名绑定到模型对象的属性中,若请求参数为?username=zhang&password=123&workInfo.city=bj,则User类应包含username、password和workInfo属性的city属性,那么这三个参数将被注入到“user”attribute对应的属性中,并且以“user”命名被存入模型对象汇总,在前端页面可通过${user.username}来获取username属性。
- 运用在方法上,会在每一个@RequestMapping注解的方法前执行,若有返回值,则自动将其存入ModelMap。
/**
* 设置这个注解之后可以直接在前端页面使用hb这个对象(List)集合
*/
@ModelAttribute("hb") //此方法在@RequestMapping方法之前执行,并将返回值存入模型对象
public List<String> hobbiesList(){
List<String> hobbise = new LinkedList<String>();
hobbise.add("basketball");
hobbise.add("football");
hobbise.add("tennis");
return hobbise;
}
/**
* 前端使用hb
*/
<c:forEach items="${hb}" var="hobby" varStatus="vs">
<c:choose>
<c:when test="${hobby == 'basketball'}">
篮球<input type="checkbox" name="hobbies" value="basketball">
</c:when>
...
</c:choose>
</c:forEach>
若@ModelAttribute不指定属性名称则默认为返回类型的首字符小写,如返回类型为Account,则属性名为account。
若@ModelAttribute和@RequestMapping同时注释一个方法,则此时返回值并不表示一个视图的名称,而是model属性的值,视图名称则由RequestToViewNameTranslator根据请求“/helloWorld.do”转换为视图HelloWorld。
@Controller
public class HelloWorldController {
@RequestMapping(value = "/helloWorld.do")
@ModelAttribute("attributeName")
public String helloWorld() {
return "hi";
}
}