1 |
public class MyWebApplicationInitializer implements WebApplicationInitializer { |
2 |
@Override |
3 |
public void onStartup(ServletContext container) { |
4 |
ServletRegistration.Dynamic registration = container.addServlet( "dispatcher" , new DispatcherServlet()); |
5 |
registration.setLoadOnStartup( 1 ); |
6 |
registration.addMapping( "/example/*" ); |
7 |
} |
8 |
} |
01 |
< web-app > |
02 |
< servlet > |
03 |
< servlet-name >example</ servlet-name > |
04 |
< servlet-class >org.springframework.web.servlet.DispatcherServlet</ servlet-class > |
05 |
< load-on-startup >1</ load-on-startup > |
06 |
</ servlet > |
07 |
< servlet-mapping > |
08 |
< servlet-name >example</ servlet-name > |
09 |
< url-pattern >/example/*</ url-pattern > |
10 |
</ servlet-mapping > |
11 |
</ web-app > |
1 |
@Controller |
2 |
public class SimpleController { |
3 |
|
4 |
@RequestMapping ( "/simple" ) |
5 |
public @ResponseBody String simple() { |
6 |
return "Hello world!" ; |
7 |
} |
8 |
|
9 |
} |
01 |
public class JavaBean { |
02 |
|
03 |
@NotNull |
04 |
@Max ( 5 ) |
05 |
private Integer number; |
06 |
|
07 |
@NotNull |
08 |
@Future |
09 |
@DateTimeFormat (iso=ISO.DATE) |
10 |
private Date date; |
11 |
|
12 |
public Integer getNumber() { |
13 |
return number; |
14 |
} |
15 |
|
16 |
public void setNumber(Integer number) { |
17 |
this .number = number; |
18 |
} |
19 |
|
20 |
public Date getDate() { |
21 |
return date; |
22 |
} |
23 |
|
24 |
public void setDate(Date date) { |
25 |
this .date = date; |
26 |
} |
27 |
|
28 |
} |
01 |
@Controller |
02 |
public class ValidationController { |
03 |
|
04 |
// enforcement of constraints on the JavaBean arg require a JSR-303 provider on the classpath |
05 |
|
06 |
@RequestMapping ( "/validate" ) |
07 |
public @ResponseBody String validate( @Valid JavaBean bean, BindingResult result) { |
08 |
if (result.hasErrors()) { |
09 |
return "Object has validation errors" ; |
10 |
} else { |
11 |
return "No errors" ; |
12 |
} |
13 |
} |
14 |
|
15 |
} |
01 |
@Controller |
02 |
public class MappingController { |
03 |
|
04 |
@RequestMapping ( "/mapping/path" ) |
05 |
public @ResponseBody String byPath() { |
06 |
return "Mapped by path!" ; //最简单的,只定义了request的url |
07 |
} |
08 |
|
09 |
@RequestMapping (value= "/mapping/path/*" , method=RequestMethod.GET) |
10 |
public @ResponseBody String byPathPattern(HttpServletRequest request) { //拿到的HttpServletRequest基本上什么都可以做到了 |
11 |
return "Mapped by path pattern ('" + request.getRequestURI() + "')" ; |
12 |
} |
13 |
|
14 |
@RequestMapping (value= "/mapping/method" , method=RequestMethod.GET) |
15 |
public @ResponseBody String byMethod() { |
16 |
return "Mapped by path + method" ; |
17 |
} |
18 |
|
19 |
@RequestMapping (value= "/mapping/parameter" , method=RequestMethod.GET, params= "foo" ) |
20 |
public @ResponseBody String byParameter() { |
21 |
return "Mapped by path + method + presence of query parameter!" ; //定义了必须符合url+方法+参数三个规则的请求才可以被捕捉 |
22 |
} |
23 |
|
24 |
@RequestMapping (value= "/mapping/parameter" , method=RequestMethod.GET, params= "!foo" ) |
25 |
public @ResponseBody String byParameterNegation() { |
26 |
return "Mapped by path + method + not presence of query parameter!" ; //params="!foo",不能有foo这个参数的url+方法的请求 |
27 |
} |
28 |
|
29 |
@RequestMapping (value= "/mapping/header" , method=RequestMethod.GET, headers= "FooHeader=foo" ) |
30 |
public @ResponseBody String byHeader() { |
31 |
return "Mapped by path + method + presence of header!" ; //附加header的规则 |
32 |
} |
33 |
|
34 |
@RequestMapping (value= "/mapping/header" , method=RequestMethod.GET, headers= "!FooHeader" ) |
35 |
public @ResponseBody String byHeaderNegation() { |
36 |
return "Mapped by path + method + absence of header!" ; //没有FooHeader的headers |
37 |
} |
38 |
|
39 |
@RequestMapping (value= "/mapping/consumes" , method=RequestMethod.POST, consumes=MediaType.APPLICATION_JSON_VALUE) |
40 |
public @ResponseBody String byConsumes( @RequestBody JavaBean javaBean) { |
41 |
return "Mapped by path + method + consumable media type (javaBean '" + javaBean + "')" ; //这个在后面的convert再说 |
42 |
} |
43 |
|
44 |
@RequestMapping (value= "/mapping/produces" , method=RequestMethod.GET, produces=MediaType.APPLICATION_JSON_VALUE) |
45 |
public @ResponseBody JavaBean byProducesJson() { //返回JavaBean的json数据 |
46 |
return new JavaBean(); |
47 |
} |
48 |
|
49 |
@RequestMapping (value= "/mapping/produces" , method=RequestMethod.GET, produces=MediaType.APPLICATION_XML_VALUE) |
50 |
public @ResponseBody JavaBean byProducesXml() { //返回JavaBean的xml数据 |
51 |
return new JavaBean(); |
52 |
} |
53 |
} |
001 |
@Controller |
002 |
@RequestMapping ( "/data" ) |
003 |
public class RequestDataController { |
004 |
|
005 |
@RequestMapping (value= "param" , method=RequestMethod.GET) |
006 |
public @ResponseBody String withParam( @RequestParam String foo) { |
007 |
return "Obtained 'foo' query parameter value '" + foo + "'" ; //RequestParam ,获得一个foo的参数,还可以指定参数的名字,例如下面的的 |
008 |
} |
009 |
|
010 |
@RequestMapping (value= "group" , method=RequestMethod.GET) |
011 |
public @ResponseBody String withParamGroup(JavaBean bean) { |
012 |
return "Obtained parameter group " + bean; |
013 |
} |
014 |
|
015 |
@RequestMapping (value= "path/{var}" , method=RequestMethod.GET) |
016 |
public @ResponseBody String withPathVariable( @PathVariable String var) { //使用@PathVariable ,参数需要在url中出现例如 xxx/path/hello |
017 |
return "Obtained 'var' path variable value '" + var + "'" ; // "hello"这个参数就会被获取到 |
018 |
} |
019 |
|
020 |
@RequestMapping (value= "{path}/simple" , method=RequestMethod.GET) // url=/pets;foo=11/simple |
021 |
public @ResponseBody String withMatrixVariable( @PathVariable String path, @MatrixVariable String foo) { |
022 |
//path=pets; foo=11 |
023 |
return "Obtained matrix variable 'foo=" + foo + "' from path segment '" + path + "'" ; |
024 |
} |
025 |
|
026 |
@RequestMapping (value= "{path1}/{path2}" , method=RequestMethod.GET) // url = /42;foo1=11/21;foo2=22 |
027 |
public @ResponseBody String withMatrixVariablesMultiple ( |
028 |
@PathVariable String path1, @MatrixVariable (value= "foo" , pathVar= "path1" ) String foo1, |
029 |
@PathVariable String path2, @MatrixVariable (value= "foo" , pathVar= "path2" ) String foo2) { //类似上面的,分块分解参数 |
030 |
|
031 |
return "Obtained matrix variable foo=" + foo1 + " from path segment '" + path1 |
032 |
+ "' and variable 'foo=" + foo2 + " from path segment '" + path2 + "'" ; |
033 |
} |
034 |
|
035 |
@RequestMapping ( "/owners/{ownerId}" ) // 例如url:/owners/42/pets/21. |
036 |
public class RelativePathUriTemplateController { |
037 |
@RequestMapping ( "/pets/{petId}" ) |
038 |
public void findPet( @PathVariable String ownerId, @PathVariable String petId, Model model) { |
039 |
// implementation omitted |
040 |
} |
041 |
} |
042 |
|
043 |
// GET /owners/42;q=11/pets/21;q=22 |
044 |
@RequestMapping (value = "/owners/{ownerId}/pets/{petId}" , method = RequestMethod.GET) |
045 |
public void findPet( |
046 |
@MatrixVariable (value= "q" , pathVar= "ownerId" ) int q1, |
047 |
@MatrixVariable (value= "q" , pathVar= "petId" ) int q2) { |
048 |
// q1 == 11 |
049 |
// q2 == 22 |
050 |
} |
051 |
|
052 |
// GET /owners/42;q=11;r=12/pets/21;q=22;s=23 |
053 |
@RequestMapping (value = "/owners/{ownerId}/pets/{petId}" , method = RequestMethod.GET) //@MatrixVariable 允许组合所有参数成为一个 |
054 |
public void findPet( |
055 |
@MatrixVariable Map < String, String > matrixVars, |
056 |
@MatrixVariable (pathVar = "petId" ) Map<String, String> petMatrixVars) { |
057 |
// matrixVars: [" q " : [11,22], " r " : 12, " s " : 23] |
058 |
// petMatrixVars: [" q " : 11, " s " : 23] |
059 |
} |
060 |
/* |
061 |
Host localhost:8080 |
062 |
Accept text/html,application/xhtml+xml,application/xml;q=0.9 |
063 |
Accept-Language fr,en-gb;q=0.7,en;q=0.3 |
064 |
Accept-Encoding gzip,deflate |
065 |
Accept-Charset ISO-8859-1,utf-8;q=0.7,*;q=0.7 |
066 |
Keep-Alive 300 |
067 |
*/ |
068 |
@RequestMapping(value="header", method=RequestMethod.GET) |
069 |
public @ResponseBody String withHeader(@RequestHeader String Accept) {//@RequestHeader 可以指定你想或者header中的哪个属性的信息 |
070 |
return "Obtained 'Accept' header '" + Accept + "'";//例如@RequestHeader("Keep-Alive") 获得 300 |
071 |
} |
072 |
|
073 |
// cookie中有一个值openid_provider=415A4AC178C59DACE0B2C9CA727CDD84 ,也可以指定变量名withCookie(@CookieValue("openid_provider") param); |
074 |
@RequestMapping(value="cookie", method=RequestMethod.GET) |
075 |
public @ResponseBody String withCookie(@CookieValue String openid_provider) { |
076 |
return "Obtained 'openid_provider' cookie '" + openid_provider + "'"; |
077 |
} |
078 |
|
079 |
/** |
080 |
*响应流媒体,一般是xml和json数据,可以使用consumes="application/json"指定接受的是json还是xml |
081 |
*spring可以把POST的数据转换成为一个bean |
082 |
*例如有个class JavaBean implements Serializable { |
083 |
* private Interger id; |
084 |
* private Stirng name; |
085 |
* private String status; |
086 |
* public JavaBean (){ |
087 |
* |
088 |
* } |
089 |
* } |
090 |
* @RequestMapping(value="body", method=RequestMethod.POST) |
091 |
* public @ResponseBody String withBody(@RequestBody JavaBean bean) {//响应流媒体 |
092 |
* return "Posted request body '" + bean + "'"; |
093 |
* } |
094 |
* $.post("/body",{'id':1, 'name': 'people', 'status': 'yes'},function(result){ |
095 |
* alert(result); |
096 |
* }); |
097 |
* spring 会把post过来的数据组成一个bean,这种方式尽量少用 |
098 |
*/ |
099 |
@RequestMapping(value="body", method=RequestMethod.POST) |
100 |
public @ResponseBody String withBody(@RequestBody String body) {//响应流媒体 |
101 |
return "Posted request body '" + body + "'"; |
102 |
} |
103 |
|
104 |
@RequestMapping(value="entity", method=RequestMethod.POST) |
105 |
public @ResponseBody String withEntity(HttpEntity<String> entity) { |
106 |
return "Posted request body '" + entity.getBody() + "'; headers = " + entity.getHeaders(); |
107 |
}//这个就牛b了,把整个http请求的数据都给你了,有HttpEntity来传递请求数据当然有一个返回应答的数据流类 |
108 |
|
109 |
@RequestMapping("/something") |
110 |
public ResponseEntity<String> handle(HttpEntity<byte[]> requestEntity) throws |
111 |
UnsupportedEncodingException { |
112 |
String requestHeader = requestEntity.getHeaders().getFirst("MyRequestHeader")); |
113 |
byte[] requestBody = requestEntity.getBody(); |
114 |
// do something with request header and body |
115 |
HttpHeaders responseHeaders = new HttpHeaders(); |
116 |
responseHeaders.set("MyResponseHeader", "MyValue");//设置好header后和body-〉hello world组成ResponseEntity返回 |
117 |
return new ResponseEntity<String>("Hello World", responseHeaders, HttpStatus.CREATED); |
118 |
} |
119 |
/** |
120 |
*@RequestBody @ResponseBody分别是HttpEntity和ResponseEntity的去掉header的body部分 |
121 |
*/ |
122 |
|
123 |
} |
01 |
import java.io.Serializable; |
02 |
|
03 |
public class Person implements Serializable { |
04 |
|
05 |
private static final long serialVersionUID = -8333984959652704635L; |
06 |
|
07 |
private Integer id; |
08 |
private String firstName; |
09 |
private String lastName; |
10 |
private String currency; |
11 |
private Double money; |
12 |
|
13 |
......getter/setter |
14 |
|
15 |
} |
1 |
@Controller |
2 |
@RequestMapping ( "EDIT" ) |
3 |
public class PetSitesEditController { |
4 |
@ModelAttribute ( "people" ) |
5 |
public Person getPerson() { |
6 |
return this .person ; |
7 |
} //对于这个这个controller来说,其他的方法的返回的jsp页面里面都会有一个people属性被返回,因为@ModelAttribute注解的方法会在这个controller的其他方法调用前被调用 |
8 |
} |
01 |
<%@ taglib uri= "http://java.sun.com/jsp/jstl/core" prefix= "c" %> |
02 |
<%@ taglib uri= "http://www.springframework.org/tags/form" prefix= "form" %> |
03 |
<%@ page language= "java" contentType= "text/html; charset=UTF-8" |
04 |
pageEncoding= "UTF-8" %> |
05 |
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd" > |
06 |
<html> |
07 |
<head> |
08 |
<meta http-equiv= "Content-Type" content= "text/html; charset=UTF-8" > |
09 |
<title>Insert title here</title> |
10 |
</head> |
11 |
<body> |
12 |
|
13 |
<h1>Edit Person</h1> |
14 |
|
15 |
<c:url var= "saveUrl" value= "/main/edit/${personAttribute.id}" /> |
16 |
|
17 |
<form:form modelAttribute= "personAttribute" method= "POST" action= "${saveUrl}" > |
18 |
<table> |
19 |
<tr> |
20 |
<td><form:label path= "id" >Id:</form:label></td> |
21 |
<td><form:input path= "id" disabled= "true" /></td> |
22 |
</tr> |
23 |
|
24 |
<tr> |
25 |
<td><form:label path= "firstName" >First Name:</form:label></td> |
26 |
<td><form:input path= "firstName" /></td> |
27 |
</tr> |
28 |
|
29 |
<tr> |
30 |
<td><form:label path= "lastName" >Last Name</form:label></td> |
31 |
<td><form:input path= "lastName" /></td> |
32 |
</tr> |
33 |
|
34 |
<tr> |
35 |
<td><form:label path= "money" >Money</form:label></td> |
36 |
<td><form:input path= "money" /></td> |
37 |
</tr> |
38 |
|
39 |
<tr> |
40 |
<td><form:label path= "currency" >Currency:</form:label></td> |
41 |
<td><form:select path= "currency" items= "${currencies}" /></td> |
42 |
</tr> |
43 |
</table> |
44 |
|
45 |
<input type= "submit" value= "Save" /> |
46 |
</form:form> |
47 |
|
48 |
</body> |
49 |
</html> |
1 |
@RequestMapping (value = "/edit/{id}" , method = RequestMethod.POST) |
2 |
public String saveEdit( @ModelAttribute ( "personAttribute" ) Person person, |
3 |
@PathVariable Integer id) { |
4 |
//spring会把post过来的person信息组合成为一个JavaBean,这里还获得了id这个信息 |
5 |
} |
01 |
@Controller |
02 |
public class PersonController { |
03 |
|
04 |
@ModelAttribute ( "person" ) |
05 |
public Person getPerson() { |
06 |
return new Person(); |
07 |
} |
08 |
|
09 |
@RequestMapping (value = "/new" ) |
10 |
public String add( @ModelAttribute ( "person" ) Person person) { |
11 |
return "add person" ; |
12 |
} |
13 |
} |
14 |
/* |
15 |
* 访问url /new |
16 |
* 首先会执行getPerson的方法,然后再执行add方法,其中person这个bean已经被new出来了,所以在add方法中可以被获得,这个有点像下面要说的convert,但是功能要稍微弱一些。 |
17 |
*/ |
01 |
public class AccountConverter implements Converter<String, Account> { |
02 |
|
03 |
private AccountManager accountManager; |
04 |
|
05 |
@Autowired |
06 |
public AccountConverter(AccountManager accountManager) { //ioc一个accoutManager,用来根据id查出accout |
07 |
this .accountManager = accountManager; |
08 |
} |
09 |
|
10 |
@Override |
11 |
public Account convert(String id) { |
12 |
return this .accountManager.getAccount(id); |
13 |
} |
14 |
|
15 |
} |
01 |
@Controller |
02 |
@RequestMapping ( "/accounts" ) |
03 |
public class AccountController { |
04 |
05 |
@RequestMapping (value= "/{account}/edit" , method = RequestMethod.GET) |
06 |
public String edit( @PathVariable Account account) { |
07 |
//操作accout类 |
08 |
return "accounts/edit" ; |
09 |
} |
10 |
} |
01 |
@Controller |
02 |
@RequestMapping ( "/redirect" ) |
03 |
public class RedirectController { |
04 |
|
05 |
private final ConversionService conversionService; |
06 |
|
07 |
@Inject |
08 |
public RedirectController(ConversionService conversionService) { |
09 |
this .conversionService = conversionService; |
10 |
} |
11 |
|
12 |
@RequestMapping (value= "/uriTemplate" , method=RequestMethod.GET) |
13 |
public String uriTemplate(RedirectAttributes redirectAttrs) { |
14 |
redirectAttrs.addAttribute( "account" , "a123" ); // Used as URI template variable |
15 |
redirectAttrs.addAttribute( "date" , new LocalDate( 2011 , 12 , 31 )); // Appended as a query parameter |
16 |
return "redirect:/redirect/{account}" ; |
17 |
} |
18 |
|
19 |
@RequestMapping (value= "/uriComponentsBuilder" , method=RequestMethod.GET) |
20 |
public String uriComponentsBuilder() { |
21 |
String date = this .conversionService.convert( new LocalDate( 2011 , 12 , 31 ), String. class ); |
22 |
UriComponents redirectUri = UriComponentsBuilder.fromPath( "/redirect/{account}" ).queryParam( "date" , date) |
23 |
.build().expand( "a123" ).encode(); |
24 |
return "redirect:" + redirectUri.toUriString(); |
25 |
} |
26 |
|
27 |
@RequestMapping (value= "/{account}" , method=RequestMethod.GET) |
28 |
public String show( @PathVariable String account, @RequestParam (required= false ) LocalDate date) { |
29 |
return "redirect/redirectResults" ; |
30 |
} |
31 |
|
32 |
} |
01 |
@Controller |
02 |
@RequestMapping ( "/views/*" ) |
03 |
public class ViewsController { |
04 |
|
05 |
@RequestMapping (value= "html" , method=RequestMethod.GET) |
06 |
public String prepare(Model model) { |
07 |
model.addAttribute( "foo" , "bar" ); |
08 |
model.addAttribute( "fruit" , "apple" ); |
09 |
return "views/html" ; |
10 |
} |
11 |
} |
01 |
@Controller |
02 |
@RequestMapping ( "/fileupload" ) |
03 |
public class FileUploadController { |
04 |
|
05 |
@ModelAttribute |
06 |
public void ajaxAttribute(WebRequest request, Model model) { |
07 |
model.addAttribute( "ajaxRequest" , AjaxUtils.isAjaxRequest(request)); |
08 |
} |
09 |
|
10 |
@RequestMapping (method=RequestMethod.GET) |
11 |
public void fileUploadForm() { |
12 |
} |
13 |
|
14 |
@RequestMapping (method=RequestMethod.POST) |
15 |
public void processUpload( @RequestParam MultipartFile file, Model model) throws IOException { //MultipartFile可以指定变量名@MultipartFile("file001") file |
16 |
//file.isEmpty(),file.getBytes();,file.getInputStream(); |
17 |
model.addAttribute( "message" , "File '" + file.getOriginalFilename() + "' uploaded successfully" ); |
18 |
} |
19 |
} |
01 |
@RequestMapping (value = "/files/{file_name}" , method = RequestMethod.GET) |
02 |
public void getFile( |
03 |
@PathVariable ( "file_name" ) String fileName, |
04 |
HttpServletResponse response) { |
05 |
try { |
06 |
// get your file as InputStream |
07 |
InputStream is = ...; |
08 |
// copy it to response's OutputStream |
09 |
IOUtils.copy(is, response.getOutputStream()); |
10 |
response.flushBuffer(); |
11 |
} catch (IOException ex) { |
12 |
log.info( "Error writing file to output stream. Filename was '" + fileName + "'" ); |
13 |
throw new RuntimeException( "IOError writing file to output stream" ); |
14 |
} |
15 |
} //本人比较喜欢这个 |
16 |
17 |
@RequestMapping (value = "/files/{file_name}" , method = RequestMethod.GET) |
18 |
@ResponseBody |
19 |
public FileSystemResource getFile( @PathVariable ( "file_name" ) String fileName) { |
20 |
return new FileSystemResource(myService.getFileFor(fileName)); |
21 |
} |
01 |
@WebServlet (urlPatterns = "/demo" , asyncSupported = true ) |
02 |
public class AsyncDemoServlet extends HttpServlet { |
03 |
@Override |
04 |
public void doGet(HttpServletRequest req, HttpServletResponse resp) |
05 |
throws IOException, ServletException { |
06 |
resp.setContentType( "text/html;charset=UTF-8" ); |
07 |
PrintWriter out = resp.getWriter(); |
08 |
out.println( "开始时间:" + new Date() + "." ); |
09 |
out.flush(); |
10 |
|
11 |
//在子线程中执行业务调用,并由其负责输出响应,主线程退出 |
12 |
AsyncContext ctx = req.startAsync(); |
13 |
new Thread( new Executor(ctx)).start(); |
14 |
|
15 |
out.println( "结束时间:" + new Date() + "." ); |
16 |
out.flush(); |
17 |
} |
18 |
} |
19 |
|
20 |
public class Executor implements Runnable { |
21 |
private AsyncContext ctx = null ; |
22 |
public Executor(AsyncContext ctx){ |
23 |
this .ctx = ctx; |
24 |
} |
25 |
|
26 |
public void run(){ |
27 |
try { |
28 |
//等待十秒钟,以模拟业务方法的执行 |
29 |
Thread.sleep( 10000 ); |
30 |
PrintWriter out = ctx.getResponse().getWriter(); |
31 |
out.println( "业务处理完毕的时间:" + new Date() + "." ); |
32 |
out.flush(); |
33 |
ctx.complete(); |
34 |
} catch (Exception e) { |
35 |
e.printStackTrace(); |
36 |
} |
37 |
} |
38 |
} |
01 |
@RequestMapping ( "/response-body" ) |
02 |
public @ResponseBody Callable<String> callable( final @RequestParam (required= false , defaultValue= "true" ) boolean handled) { |
03 |
//进行一些与处理之后,把最耗时的业务逻辑部分放到Callable中,注意,如果你需要在new Callable中用到从页面传入的参数,需要在参数前加入final |
04 |
return new Callable<String>() { |
05 |
@Override |
06 |
public String call() throws Exception { |
07 |
if (handled){ |
08 |
Thread.sleep( 2000 ); |
09 |
} else { |
10 |
Thread.sleep( 2000 * 2 ); |
11 |
} |
12 |
return "Callable result" ; |
13 |
} |
14 |
}; |
15 |
} |
01 |
@RequestMapping ( "/custom-timeout-handling" ) |
02 |
public @ResponseBody WebAsyncTask<String> callableWithCustomTimeoutHandling() { |
03 |
04 |
Callable<String> callable = new Callable<String>() { |
05 |
@Override |
06 |
public String call() throws Exception { |
07 |
Thread.sleep( 2000 ); |
08 |
return "Callable result" ; |
09 |
} |
10 |
}; |
11 |
12 |
return new WebAsyncTask<String>( 1000 , callable); //允许指定timeout时间 |
13 |
} |
01 |
@Controller |
02 |
@RequestMapping ( "/async" ) |
03 |
public class DeferredResultController { |
04 |
|
05 |
private final Queue<DeferredResult<String>> responseBodyQueue = new ConcurrentLinkedQueue<DeferredResult<String>>(); |
06 |
|
07 |
private final Queue<DeferredResult<ModelAndView>> mavQueue = new ConcurrentLinkedQueue<DeferredResult<ModelAndView>>(); |
08 |
|
09 |
private final Queue<DeferredResult<String>> exceptionQueue = new ConcurrentLinkedQueue<DeferredResult<String>>(); |
10 |
|
11 |
|
12 |
@RequestMapping ( "/deferred-result/response-body" ) |
13 |
public @ResponseBody DeferredResult<String> deferredResult() { |
14 |
DeferredResult<String> result = new DeferredResult<String>(); |
15 |
this .responseBodyQueue.add(result); |
16 |
return result; |
17 |
} |
18 |
|
19 |
@RequestMapping ( "/deferred-result/model-and-view" ) |
20 |
public @ResponseBody DeferredResult<ModelAndView> deferredResultWithView() { |
21 |
DeferredResult<ModelAndView> result = new DeferredResult<ModelAndView>(); |
22 |
this .mavQueue.add(result); |
23 |
return result; |
24 |
} |
25 |
|
26 |
@RequestMapping ( "/deferred-result/exception" ) |
27 |
public @ResponseBody DeferredResult<String> deferredResultWithException() { |
28 |
DeferredResult<String> result = new DeferredResult<String>(); |
29 |
this .exceptionQueue.add(result); |
30 |
return result; |
31 |
} |
32 |
//上面三个分别接受了请求之后就return了 |
33 |
// 这里允许我们在其他的线程中处理数据,并且无需实时返回 |
34 |
@RequestMapping ( "/deferred-result/timeout-value" ) |
35 |
public @ResponseBody DeferredResult<String> deferredResultWithTimeoutValue() { |
36 |
|
37 |
// Provide a default result in case of timeout and override the timeout value |
38 |
// set in src/main/webapp/WEB-INF/spring/appServlet/servlet-context.xml |
39 |
|
40 |
return new DeferredResult<String>(1000L, "Deferred result after timeout" ); |
41 |
} |
42 |
//创建一个计划任务,每2秒处理一次 |
43 |
@Scheduled (fixedRate= 2000 ) |
44 |
public void processQueues() { |
45 |
for (DeferredResult<String> result : this .responseBodyQueue) { |
46 |
result.setResult( "Deferred result" ); |
47 |
this .responseBodyQueue.remove(result); |
48 |
} |
49 |
for (DeferredResult<String> result : this .exceptionQueue) { |
50 |
result.setErrorResult( new IllegalStateException( "DeferredResult error" )); |
51 |
this .exceptionQueue.remove(result); |
52 |
} |
53 |
for (DeferredResult<ModelAndView> result : this .mavQueue) { |
54 |
result.setResult( new ModelAndView( "views/html" , "javaBean" , new JavaBean( "bar" , "apple" ))); |
55 |
this .mavQueue.remove(result); |
56 |
} |
57 |
} |
58 |
|
59 |
@ExceptionHandler |
60 |
@ResponseBody |
61 |
public String handleException(IllegalStateException ex) { |
62 |
return "Handled exception: " + ex.getMessage(); |
63 |
} |
64 |
|
65 |
} |
1 |
< mvc:interceptors > |
2 |
< ref bean = "officeHoursInterceptor" /> |
3 |
</ mvc:interceptors > |
4 |
< bean id = "officeHoursInterceptor" |
5 |
class = "samples.TimeBasedAccessInterceptor" > |
6 |
< property name = "openingTime" value = "9" /> |
7 |
< property name = "closingTime" value = "18" /> |
8 |
</ bean > |
01 |
package samples; |
02 |
public class TimeBasedAccessInterceptor extends HandlerInterceptorAdapter { |
03 |
private int openingTime; |
04 |
private int closingTime; |
05 |
public void setOpeningTime( int openingTime) { |
06 |
this .openingTime = openingTime; |
07 |
} |
08 |
public void setClosingTime( int closingTime) { |
09 |
this .closingTime = closingTime; |
10 |
} |
11 |
public boolean preHandle( |
12 |
HttpServletRequest request, |
13 |
HttpServletResponse response, |
14 |
Object handler) throws Exception { |
15 |
Calendar cal = Calendar.getInstance(); |
16 |
int hour = cal.get(HOUR_OF_DAY); |
17 |
if (openingTime <= hour && hour < closingTime) { |
18 |
return true ; |
19 |
} else { |
20 |
response.sendRedirect( "http://host.com/outsideOfficeHours.html" ); |
21 |
return false ; |
22 |
} |
23 |
} |
24 |
} |