Controller的不同写法和相应注解

一、写法一:

@RestController
@RequestMapping("/advertise")
public class AdvertiseController {
	@CrossOrigin
	@RequestMapping(value = "/add/{id}", method = RequestMethod.POST)
	public JSONObject addAdvertise(@RequestBody JSONObject params, @Context HttpServletRequest request, @PathVariable("id") String id) {
1.@PathVariable:

通过@PathVariable可以将URL中占位符参数绑定到控制器处理方法的入参中:URL中的{xxx}占位符可以通过@PathVariable(“xxx”)绑定到操作方法的入参中。

2.@RequestBody:

将请求体中的整体数据转化为对象,GET方式无请求体,所以使用@RequestBody接收数据时,前端不能使用GET方式提交数据,而是用POST方式进行提交。

3.@Context:

不太了解这个注解,但是我发现把这个注解去掉也不影响啥。

@RestController
public class HuiController {

    @RequestMapping(value="huitest")
    public String hui(@RequestBody JSONObject params, HttpServletRequest request) {
    	String qiang = request.getParameter("hehe");
    	String xiao = params.getString("qiang");
    	return qiang + "<-->" + xiao;
    }
}

《Controller的不同写法和相应注解》
也可以用这个curl命令测试:

curl http://localhost:8080/huitest -X POST -d '{"qiang":"qie"}' --header "Content-Type: application/json"
4.@CrossOrigin:

是用来处理跨域请求的注解

跨域,指的是浏览器不能执行其他网站的脚本。它是由浏览器的同源策略造成的,是浏览器对JavaScript施加的安全限制。
所谓同源是指,域名,协议,端口均相同,不明白没关系,举个栗子:
http://www.123.com/index.html 调用 http://www.123.com/server.PHP (非跨域)
http://www.123.com/index.html 调用 http://www.456.com/server.php (主域名不同:123/456,跨域)
http://abc.123.com/index.html 调用 http://def.123.com/server.php (子域名不同:abc/def,跨域)
http://www.123.com:8080/index.html 调用 http://www.123.com:8081/server.php (端口不同:8080/8081,跨域)
http://www.123.com/index.html 调用 https://www.123.com/server.php (协议不同:http/https,跨域)
请注意:localhost和127.0.0.1虽然都指向本机,但也属于跨域。
浏览器执行javascript脚本时,会检查这个脚本属于哪个页面,如果不是同源页面,就不会被执行。
当域名www.abc.com下的js代码去访问www.def.com域名下的资源,就会受到限制。
@CrossOrigin可以处理跨域请求,让你能访问不是一个域的文件。

5.@RequestMapping:

配置url映射,此注解即可以作用在控制器的某个方法上,也可以作用在此控制器类上。
当控制器在类级别上添加@RequestMapping注解时,这个注解会应用到控制器的所有处理器方法上。处理器方法上的@RequestMapping注解会对类级别上的@RequestMapping的声明进行补充。
例子一:@RequestMapping仅作用在处理器方法上

@RestController
public class HelloController {

    @RequestMapping(value="/hello",method= RequestMethod.GET)
    public String sayHello(){
        return "hello";
    }
}

以上代码sayHello所响应的url=localhost:8080/hello。
例子二:@RequestMapping仅作用在类级别上

@RestController
@RequestMapping("/hello")
public class HelloController {

    @RequestMapping(method= RequestMethod.GET)
    public String sayHello(){
        return "hello";
    }
}

以上代码sayHello所响应的url=localhost:8080/hello,效果与例子一一样,没有改变任何功能。
例子三:@RequestMapping作用在类级别和处理器方法上

@RestController
@RequestMapping("/hello")
public class HelloController {

    @RequestMapping(value="/sayHello",method= RequestMethod.GET)
    public String sayHello(){
        return "hello";
    }
    @RequestMapping(value="/sayHi",method= RequestMethod.GET)
    public String sayHi(){
        return "hi";
    }
}

这样,以上代码中的sayHello所响应的url=localhost:8080/hello/sayHello。
sayHi所响应的url=localhost:8080/hello/sayHi。
@RequestMapping 和 @GetMapping @PostMapping 区别:
@GetMapping是一个组合注解,是@RequestMapping(method = RequestMethod.GET)的缩写。
@PostMapping是一个组合注解,是@RequestMapping(method = RequestMethod.POST)的缩写。
如果@RequestMapping不指定请求方式则两种请求方式都可以。

@RestController
public class HuiController {

    @RequestMapping("huitest")
//	@PostMapping("huitest") 和 @RequestMapping(value="huitest",method = RequestMethod.POST)等效
//	@GetMapping(value="huitest") 和 @RequestMapping(value="huitest",method = RequestMethod.GET)等效
    public String hui(HttpServletRequest request) {
    	String hui = request.getParameter("hehe");
    	return hui;
    }
}

《Controller的不同写法和相应注解》
用浏览器直接访问其实是GET请求
《Controller的不同写法和相应注解》

6.@RestController:

在spring4.0之后,引入了@RestController这个注解。这个注解相当于把@ResponseBody + @Controller合在一起。
我们先来看一下@RestController的源码:

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Controller
@ResponseBody
public @interface RestController {
    String value() default "";
}

前端在通过表单提交和a标签请求后端的时候只需要注解@Controller即可,但是在通过Ajax请求后端的时候,还需要增加一个@ResponseBody注解,但是在spring4.0之后,无论是表单还是a标签还是Ajax请求后端,都只要@RestController一个注解即可。

@ResponseBody能将对象自动转换为json字符串,所以以往在Ajax返回时直接返回一个对象就行,而在表单和a标签请求是返回需要调用JSON.toJSONString(object)这个方法将对象转换为json字符串。

在spring4.0后,所有请求在@RestController之下,直接返回对象即可,再也不需要转换为json字符串了。

@RestController
public class HelloController {

    @RequestMapping(value="/hello",method= RequestMethod.GET)
    public String sayHello(){
        return "hello";
    }
}

与下面的代码作用一样

@Controller
@ResponseBody
public class HelloController {

    @RequestMapping(value="/hello",method= RequestMethod.GET)
    public String sayHello(){
        return "hello";
    }
}

使用了@RestController之后,所有返回的数据他都会把你解析为json字符串,所以如果是前后台不分开式开发(即返回的是跳转页面名字)时,不能使用@RestContoller,不然只会在原来页面中显式你要跳转页面的名字!
可参考:http://www.ityouknow.com/springboot/2016/02/03/spring-boot-web.html
注意:@Contoller注解在springboot1.5以前的版本中在maven配置spring-boot-starter-web(@Contoller引入的包是org.springframework.stereotype.Controller)中有,而1.5及以后则没有了。
 

二、写法二(其实就是Jersey写Restful接口):

@Path("/admin")
@Component
public class ManagementResource {
	@POST
	@Path("/login")
	@Consumes(MediaType.APPLICATION_JSON)
	@Produces(MediaType.APPLICATION_JSON)
	@CrossOrigin
	public Response login(JSONObject params, @Context HttpServletRequest request) {
1.@Component:

使用@Component是让该类能够在其他地方被依赖使用,即可以直接在其他地方使用@Autowired来创建其实例对象。
强力推荐:Spring注解详解

2.@Produces:

@Produces注释用来指定将要返回给client端的数据标识类型(MIME)。@Produces可以作为class注释,也可以作为方法注释,方法的@Produces注释将会覆盖class的注释。
a.返回给client字符串类型(text/plain)

@Produces(MediaType.TEXT_PLAIN)

b.返回给client为json类型(application/json)

@Produces(MediaType.APPLICATION_JSON)
3.@Consumes:

@Consumes与@Produces相反,用来指定可以接受client发送过来的MIME类型,同样可以用于class或者method,也可以指定多个MIME类型,一般用于@PUT,@POST
a.接受client参数为字符串类型

@Consumes(MediaType.TEXT_PLAIN)

b.接受clent参数为json类型

@Consumes(MediaType.APPLICATION_JSON)

三、其他常用注解:

参考:springboot中的常用注解

1.@Bean:

放在方法上,用@Bean标注方法等价于XML中配置bean,这个方法一般返回一个实体对象,告诉spring这里产生一个对象,然后这个对象会交给Spring管理。产生这个对象的方法Spring只会调用一次,随后这个Spring将会将这个Bean对象放在自己的容器中。

2.@Configuration:

标注当前类是配置类,并会将当前类内声明的一个或多个以@Bean注解标记的方法的实例纳入到srping容器中,并且实例名就是方法名。(其实就是靠@Component注解),源码:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Configuration {
    String value() default "";
}
3.@Resource:

是按照名称来注入的,当找不到与名称匹配的bean才会按照类型来注入。其实我们平时用的@Resource都是用了他的默认的方式,即都不指定名字和类型。spring通过反射机制使用byName方法自动注入。

@Resource(type = ShiroService.class, name = "shiroService") 
private ShiroService shiroService;

@Resource 的装配顺序:

  1. 如果同时指定了 name 属性和 type 属性,那么 Spring 将从容器中找唯一匹配的 bean 进行装配,找不到则抛出异常
  2. 如果指定了 name 属性值,则从容器中查找名称匹配的 bean 进行装配,找不到则抛出异常
  3. 如果指定了 type 属性值,则从容器中查找类型匹配的唯一的 bean 进行装配,找不到或者找到多个都会抛出异常
  4. 如果都不指定,则会自动按照 byName 方式进行装配(我们一般都用的是这个。。。)
4.@Autowried:

默认是按照类型进行装配注入,如果允许 null 值,可以设置它 required 为false。即:当不能确定 Spring 容器中一定拥有某个类的 Bean 时,可以在需要自动注入该类 Bean 的地方可以使用 @Autowired(required = false) ,这等于告诉 Spring:在找不到匹配 Bean 时也不报错。

@Autowired(required = false)
private ShiroService shiroService;
5.@Qualifier:

@Autowired是根据类型进行自动装配的。如果当spring上下文中存在不止一个A类型的bean时,就会抛出BeanCreationException异常;如果Spring上下文中不存在A类型的bean,而且我们又使用A类型,也会抛出BeanCreationException异常。针对存在多个A类型的Bean,我们可以联合使用@Qualifier和@Autowired来解决这些问题。

@Autowried
@Qualifier("adminDAO")
private AdminDAO adminDAO;
6.@SpringBootApplication:

这个注解就是集成了:@SpringBootConfiguration、@EnableAutoConfiguration、@ComponentScan这三个注解。其中@SpringBootConfiguration:表示这个类为配置类;@EnableAutoConfiguration:表示开启自动配置,我们平时所说springboot无配置就是这个参数起的作用,他读取了springboot默认的配置;@ComponentScan:表示自动扫描,这个扫描默认只能扫同一级的目录。

7.@Async与@EnableAsync:

其中@Async表示这个方法为异步方法;@EnableAsync这个注解需要加在启动类上,表示支持异步操作;如果不加,则@Async将不起作用。

@RestController
public class AsyncController {
    @Autowired
    private AsyncService asyncservice;

    @RequestMapping("/asyncTest.do")
    public String asyncTest() {
        System.out.println("############asyncTest############");
        System.out.println("############a############");
        asyncservice.test();
        System.out.println("############b############");
        return "success";
    }

    @RequestMapping("/asyncTest2.do")
    public String asyncTest2() {
        System.out.println("############asyncTest2############");
        System.out.println("############a############");
        asyncservice.test2();
        System.out.println("############b############");
        return "success";
    }

    @RequestMapping("/asyncTest3.do")
    public String asyncTest3() {
        System.out.println("############asyncTest3############");
        System.out.println("############a############");
        asyncservice.test3();
        System.out.println("############b############");
        return "success";
    }
}
@Service
public class AsyncService {

    public void test() {
        System.out.println("############c############");
        for (int i = 0; i < 5; i++) {
            System.out.println(i);
        }
        System.out.println("############d############");
    }

    @Async
    public void test2() {
        System.out.println("############c############");
        for (int i = 0; i < 5; i++) {
            System.out.println(i);
        }
        System.out.println("############d############");
    }

    /**
     * @Async就相当于另起一个线程
     */
    public void test3() {
        new Thread() {
            @Override
            public void run() {
                System.out.println("############c############");
                for (int i = 0; i < 5; i++) {
                    System.out.println(i);
                }
                System.out.println("############d############");
            }
        }.start();
    }

}

实验结果是: asyncTest.do输出为: acdb; asyncTest2.do输出为: abcd; asyncTest3.do输出为: abcd;
所以简单来说:@Async就相当于另起一个线程。

    原文作者:小强签名设计
    原文地址: https://blog.csdn.net/m0_37739193/article/details/82757798
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞