public class MyWebApplicationInitializer implements WebApplicationInitializer { @Override public void onStartup(ServletContext container) { ServletRegistration.Dynamic registration = container.addServlet("dispatcher", new DispatcherServlet()); registration.setLoadOnStartup(1); registration.addMapping("/example/*"); } }
<web-app> <servlet> <servlet-name>example</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>example</servlet-name> <url-pattern>/example/*</url-pattern> </servlet-mapping> </web-app>
@Controller public class SimpleController { @RequestMapping("/simple") public @ResponseBody String simple() { return "Hello world!"; } }
public class JavaBean { @NotNull @Max(5) private Integer number; @NotNull @Future @DateTimeFormat(iso=ISO.DATE) private Date date; public Integer getNumber() { return number; } public void setNumber(Integer number) { this.number = number; } public Date getDate() { return date; } public void setDate(Date date) { this.date = date; } }
@Controller public class ValidationController { // enforcement of constraints on the JavaBean arg require a JSR-303 provider on the classpath @RequestMapping("/validate") public @ResponseBody String validate(@Valid JavaBean bean, BindingResult result) { if (result.hasErrors()) { return "Object has validation errors"; } else { return "No errors"; } } }
@Controller public class MappingController { @RequestMapping("/mapping/path") public @ResponseBody String byPath() { return "Mapped by path!";//最簡單的,只定義了request的url } @RequestMapping(value="/mapping/path/*", method=RequestMethod.GET) public @ResponseBody String byPathPattern(HttpServletRequest request) {//拿到的HttpServletRequest基本上什麼均可以作到了 return "Mapped by path pattern ('" + request.getRequestURI() + "')"; } @RequestMapping(value="/mapping/method", method=RequestMethod.GET) public @ResponseBody String byMethod() { return "Mapped by path + method"; } @RequestMapping(value="/mapping/parameter", method=RequestMethod.GET, params="foo") public @ResponseBody String byParameter() { return "Mapped by path + method + presence of query parameter!";//定義了必須符合url+方法+參數三個規則的請求才能夠被捕捉 } @RequestMapping(value="/mapping/parameter", method=RequestMethod.GET, params="!foo") public @ResponseBody String byParameterNegation() { return "Mapped by path + method + not presence of query parameter!";//params="!foo",不能有foo這個參數的url+方法的請求 } @RequestMapping(value="/mapping/header", method=RequestMethod.GET, headers="FooHeader=foo") public @ResponseBody String byHeader() { return "Mapped by path + method + presence of header!";//附加header的規則 } @RequestMapping(value="/mapping/header", method=RequestMethod.GET, headers="!FooHeader") public @ResponseBody String byHeaderNegation() { return "Mapped by path + method + absence of header!";//沒有FooHeader的headers } @RequestMapping(value="/mapping/consumes", method=RequestMethod.POST, consumes=MediaType.APPLICATION_JSON_VALUE) public @ResponseBody String byConsumes(@RequestBody JavaBean javaBean) { return "Mapped by path + method + consumable media type (javaBean '" + javaBean + "')";//這個在後面的convert再說 } @RequestMapping(value="/mapping/produces", method=RequestMethod.GET, produces=MediaType.APPLICATION_JSON_VALUE) public @ResponseBody JavaBean byProducesJson() {//返回JavaBean的json數據 return new JavaBean(); } @RequestMapping(value="/mapping/produces", method=RequestMethod.GET, produces=MediaType.APPLICATION_XML_VALUE) public @ResponseBody JavaBean byProducesXml() {//返回JavaBean的xml數據 return new JavaBean(); } }
@Controller @RequestMapping("/data") public class RequestDataController { @RequestMapping(value="param", method=RequestMethod.GET) public @ResponseBody String withParam(@RequestParam String foo) { return "Obtained 'foo' query parameter value '" + foo + "'";//RequestParam ,得到一個foo的參數,還能夠指定參數的名字,例以下面的的 } @RequestMapping(value="group", method=RequestMethod.GET) public @ResponseBody String withParamGroup(JavaBean bean) { return "Obtained parameter group " + bean; } @RequestMapping(value="path/{var}", method=RequestMethod.GET) public @ResponseBody String withPathVariable(@PathVariable String var) {//使用@PathVariable ,參數須要在url中出現例如 xxx/path/hello return "Obtained 'var' path variable value '" + var + "'";// "hello"這個參數就會被獲取到 } @RequestMapping(value="{path}/simple", method=RequestMethod.GET)// url=/pets;foo=11/simple public @ResponseBody String withMatrixVariable(@PathVariable String path, @MatrixVariable String foo) { //path=pets; foo=11 return "Obtained matrix variable 'foo=" + foo + "' from path segment '" + path + "'"; } @RequestMapping(value="{path1}/{path2}", method=RequestMethod.GET)// url = /42;foo1=11/21;foo2=22 public @ResponseBody String withMatrixVariablesMultiple ( @PathVariable String path1, @MatrixVariable(value="foo", pathVar="path1") String foo1, @PathVariable String path2, @MatrixVariable(value="foo", pathVar="path2") String foo2) {//相似上面的,分塊分解參數 return "Obtained matrix variable foo=" + foo1 + " from path segment '" + path1 + "' and variable 'foo=" + foo2 + " from path segment '" + path2 + "'"; } @RequestMapping("/owners/{ownerId}")// 例如url:/owners/42/pets/21. public class RelativePathUriTemplateController { @RequestMapping("/pets/{petId}") public void findPet(@PathVariable String ownerId, @PathVariable String petId, Model model) { // implementation omitted } } // GET /owners/42;q=11/pets/21;q=22 @RequestMapping(value = "/owners/{ownerId}/pets/{petId}", method = RequestMethod.GET) public void findPet( @MatrixVariable(value="q", pathVar="ownerId") int q1, @MatrixVariable(value="q", pathVar="petId") int q2) { // q1 == 11 // q2 == 22 } // GET /owners/42;q=11;r=12/pets/21;q=22;s=23 @RequestMapping(value = "/owners/{ownerId}/pets/{petId}", method = RequestMethod.GET)//@MatrixVariable 容許組合全部參數成爲一個 public void findPet( @MatrixVariable Map < String, String > matrixVars, @MatrixVariable(pathVar = "petId" ) Map<String, String> petMatrixVars) { // matrixVars: [" q " : [11,22], " r " : 12, " s " : 23] // petMatrixVars: [" q " : 11, " s " : 23] } /* Host localhost:8080 Accept text/html,application/xhtml+xml,application/xml;q=0.9 Accept-Language fr,en-gb;q=0.7,en;q=0.3 Accept-Encoding gzip,deflate Accept-Charset ISO-8859-1,utf-8;q=0.7,*;q=0.7 Keep-Alive 300 */ @RequestMapping(value="header", method=RequestMethod.GET) public @ResponseBody String withHeader(@RequestHeader String Accept) {//@RequestHeader 能夠指定你想或者header中的哪一個屬性的信息 return "Obtained 'Accept' header '" + Accept + "'";//例如@RequestHeader("Keep-Alive") 得到 300 } // cookie中有一個值openid_provider=415A4AC178C59DACE0B2C9CA727CDD84 ,也能夠指定變量名withCookie(@CookieValue("openid_provider") param); @RequestMapping(value="cookie", method=RequestMethod.GET) public @ResponseBody String withCookie(@CookieValue String openid_provider) { return "Obtained 'openid_provider' cookie '" + openid_provider + "'"; } /** *響應流媒體,通常是xml和json數據,可使用consumes="application/json"指定接受的是json仍是xml *spring能夠把POST的數據轉換成爲一個bean *例若有個class JavaBean implements Serializable { * private Interger id; * private Stirng name; * private String status; * public JavaBean (){ * * } * } * @RequestMapping(value="body", method=RequestMethod.POST) * public @ResponseBody String withBody(@RequestBody JavaBean bean) {//響應流媒體 * return "Posted request body '" + bean + "'"; * } * $.post("/body",{'id':1, 'name': 'people', 'status': 'yes'},function(result){ * alert(result); * }); * spring 會把post過來的數據組成一個bean,這種方式儘可能少用 */ @RequestMapping(value="body", method=RequestMethod.POST) public @ResponseBody String withBody(@RequestBody String body) {//響應流媒體 return "Posted request body '" + body + "'"; } @RequestMapping(value="entity", method=RequestMethod.POST) public @ResponseBody String withEntity(HttpEntity<String> entity) { return "Posted request body '" + entity.getBody() + "'; headers = " + entity.getHeaders(); }//這個就牛b了,把整個http請求的數據都給你了,有HttpEntity來傳遞請求數據固然有一個返回應答的數據流類 @RequestMapping("/something") public ResponseEntity<String> handle(HttpEntity<byte[]> requestEntity) throws UnsupportedEncodingException { String requestHeader = requestEntity.getHeaders().getFirst("MyRequestHeader")); byte[] requestBody = requestEntity.getBody(); // do something with request header and body HttpHeaders responseHeaders = new HttpHeaders(); responseHeaders.set("MyResponseHeader", "MyValue");//設置好header後和body-〉hello world組成ResponseEntity返回 return new ResponseEntity<String>("Hello World", responseHeaders, HttpStatus.CREATED); } /** *@RequestBody @ResponseBody分別是HttpEntity和ResponseEntity的去掉header的body部分 */ }
import java.io.Serializable; public class Person implements Serializable { private static final long serialVersionUID = -8333984959652704635L; private Integer id; private String firstName; private String lastName; private String currency; private Double money; ......getter/setter }
@Controller @RequestMapping("EDIT") public class PetSitesEditController { @ModelAttribute("people") public Person getPerson() { return this.person ; }//對於這個這個controller來講,其餘的方法的返回的jsp頁面裏面都會有一個people屬性被返回,由於@ModelAttribute註解的方法會在這個controller的其餘方法調用前被調用 }
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <%@ taglib uri="http://www.springframework.org/tags/form" prefix="form" %> <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> </head> <body> <h1>Edit Person</h1> <c:url var="saveUrl" value="/main/edit/${personAttribute.id}" /> <form:form modelAttribute="personAttribute" method="POST" action="${saveUrl}"> <table> <tr> <td><form:label path="id">Id:</form:label></td> <td><form:input path="id" disabled="true"/></td> </tr> <tr> <td><form:label path="firstName">First Name:</form:label></td> <td><form:input path="firstName"/></td> </tr> <tr> <td><form:label path="lastName">Last Name</form:label></td> <td><form:input path="lastName"/></td> </tr> <tr> <td><form:label path="money">Money</form:label></td> <td><form:input path="money"/></td> </tr> <tr> <td><form:label path="currency">Currency:</form:label></td> <td><form:select path="currency" items="${currencies}"/></td> </tr> </table> <input type="submit" value="Save" /> </form:form> </body> </html>
@RequestMapping(value = "/edit/{id}", method = RequestMethod.POST) public String saveEdit(@ModelAttribute("personAttribute") Person person, @PathVariable Integer id) { //spring會把post過來的person信息組合成爲一個JavaBean,這裏還得到了id這個信息 }controller代碼
@Controller public class PersonController { @ModelAttribute("person") public Person getPerson() { return new Person(); } @RequestMapping(value = "/new") public String add(@ModelAttribute("person") Person person) { return "add person"; } } /* * 訪問url /new * 首先會執行getPerson的方法,而後再執行add方法,其中person這個bean已經被new出來了,因此在add方法中能夠被得到,這個有點像下面要說的convert,可是功能要稍微弱一些。 */
public class AccountConverter implements Converter<String, Account> { private AccountManager accountManager; @Autowired public AccountConverter(AccountManager accountManager) {//ioc一個accoutManager,用來根據id查出accout this.accountManager = accountManager; } @Override public Account convert(String id) { return this.accountManager.getAccount(id); } }
@Controller @RequestMapping("/accounts") public class AccountController { @RequestMapping(value="/{account}/edit", method = RequestMethod.GET) public String edit(@PathVariable Account account) { //操做accout類 return "accounts/edit"; } }
@Controller @RequestMapping("/redirect") public class RedirectController { private final ConversionService conversionService; @Inject public RedirectController(ConversionService conversionService) { this.conversionService = conversionService; } @RequestMapping(value="/uriTemplate", method=RequestMethod.GET) public String uriTemplate(RedirectAttributes redirectAttrs) { redirectAttrs.addAttribute("account", "a123"); // Used as URI template variable redirectAttrs.addAttribute("date", new LocalDate(2011, 12, 31)); // Appended as a query parameter return "redirect:/redirect/{account}"; } @RequestMapping(value="/uriComponentsBuilder", method=RequestMethod.GET) public String uriComponentsBuilder() { String date = this.conversionService.convert(new LocalDate(2011, 12, 31), String.class); UriComponents redirectUri = UriComponentsBuilder.fromPath("/redirect/{account}").queryParam("date", date) .build().expand("a123").encode(); return "redirect:" + redirectUri.toUriString(); } @RequestMapping(value="/{account}", method=RequestMethod.GET) public String show(@PathVariable String account, @RequestParam(required=false) LocalDate date) { return "redirect/redirectResults"; } }
@Controller @RequestMapping("/views/*") public class ViewsController { @RequestMapping(value="html", method=RequestMethod.GET) public String prepare(Model model) { model.addAttribute("foo", "bar"); model.addAttribute("fruit", "apple"); return "views/html"; } }
@Controller @RequestMapping("/fileupload") public class FileUploadController { @ModelAttribute public void ajaxAttribute(WebRequest request, Model model) { model.addAttribute("ajaxRequest", AjaxUtils.isAjaxRequest(request)); } @RequestMapping(method=RequestMethod.GET) public void fileUploadForm() { } @RequestMapping(method=RequestMethod.POST) public void processUpload(@RequestParam MultipartFile file, Model model) throws IOException {//MultipartFile能夠指定變量名@MultipartFile("file001") file //file.isEmpty(),file.getBytes();,file.getInputStream(); model.addAttribute("message", "File '" + file.getOriginalFilename() + "' uploaded successfully"); } }
@RequestMapping(value = "/files/{file_name}", method = RequestMethod.GET) public void getFile( @PathVariable("file_name") String fileName, HttpServletResponse response) { try { // get your file as InputStream InputStream is = ...; // copy it to response's OutputStream IOUtils.copy(is, response.getOutputStream()); response.flushBuffer(); } catch (IOException ex) { log.info("Error writing file to output stream. Filename was '" + fileName + "'"); throw new RuntimeException("IOError writing file to output stream"); } }//本人比較喜歡這個 @RequestMapping(value = "/files/{file_name}", method = RequestMethod.GET) @ResponseBody public FileSystemResource getFile(@PathVariable("file_name") String fileName) { return new FileSystemResource(myService.getFileFor(fileName)); }10.ajax 部分,有關 Servlet 3 async processing feature:
@WebServlet(urlPatterns = "/demo", asyncSupported = true) public class AsyncDemoServlet extends HttpServlet { @Override public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException { resp.setContentType("text/html;charset=UTF-8"); PrintWriter out = resp.getWriter(); out.println("開始時間:" + new Date() + "."); out.flush(); //在子線程中執行業務調用,並由其負責輸出響應,主線程退出 AsyncContext ctx = req.startAsync(); new Thread(new Executor(ctx)).start(); out.println("結束時間:" + new Date() + "."); out.flush(); } } public class Executor implements Runnable { private AsyncContext ctx = null; public Executor(AsyncContext ctx){ this.ctx = ctx; } public void run(){ try { //等待十秒鐘,以模擬業務方法的執行 Thread.sleep(10000); PrintWriter out = ctx.getResponse().getWriter(); out.println("業務處理完畢的時間:" + new Date() + "."); out.flush(); ctx.complete(); } catch (Exception e) { e.printStackTrace(); } } }
@RequestMapping("/response-body") public @ResponseBody Callable<String> callable(final @RequestParam(required=false, defaultValue="true") boolean handled) { //進行一些與處理以後,把最耗時的業務邏輯部分放到Callable中,注意,若是你須要在new Callable中用到從頁面傳入的參數,須要在參數前加入final return new Callable<String>() { @Override public String call() throws Exception { if(handled){ Thread.sleep(2000); }else{ Thread.sleep(2000*2); } return "Callable result"; } }; }
@RequestMapping("/custom-timeout-handling") public @ResponseBody WebAsyncTask<String> callableWithCustomTimeoutHandling() { Callable<String> callable = new Callable<String>() { @Override public String call() throws Exception { Thread.sleep(2000); return "Callable result"; } }; return new WebAsyncTask<String>(1000, callable);//容許指定timeout時間 }
@Controller @RequestMapping("/async") public class DeferredResultController { private final Queue<DeferredResult<String>> responseBodyQueue = new ConcurrentLinkedQueue<DeferredResult<String>>(); private final Queue<DeferredResult<ModelAndView>> mavQueue = new ConcurrentLinkedQueue<DeferredResult<ModelAndView>>(); private final Queue<DeferredResult<String>> exceptionQueue = new ConcurrentLinkedQueue<DeferredResult<String>>(); @RequestMapping("/deferred-result/response-body") public @ResponseBody DeferredResult<String> deferredResult() { DeferredResult<String> result = new DeferredResult<String>(); this.responseBodyQueue.add(result); return result; } @RequestMapping("/deferred-result/model-and-view") public @ResponseBody DeferredResult<ModelAndView> deferredResultWithView() { DeferredResult<ModelAndView> result = new DeferredResult<ModelAndView>(); this.mavQueue.add(result); return result; } @RequestMapping("/deferred-result/exception") public @ResponseBody DeferredResult<String> deferredResultWithException() { DeferredResult<String> result = new DeferredResult<String>(); this.exceptionQueue.add(result); return result; } //上面三個分別接受了請求以後就return了 // 這裏容許咱們在其餘的線程中處理數據,而且無需實時返回 @RequestMapping("/deferred-result/timeout-value") public @ResponseBody DeferredResult<String> deferredResultWithTimeoutValue() { // Provide a default result in case of timeout and override the timeout value // set in src/main/webapp/WEB-INF/spring/appServlet/servlet-context.xml return new DeferredResult<String>(1000L, "Deferred result after timeout"); } //建立一個計劃任務,每2秒處理一次 @Scheduled(fixedRate=2000) public void processQueues() { for (DeferredResult<String> result : this.responseBodyQueue) { result.setResult("Deferred result"); this.responseBodyQueue.remove(result); } for (DeferredResult<String> result : this.exceptionQueue) { result.setErrorResult(new IllegalStateException("DeferredResult error")); this.exceptionQueue.remove(result); } for (DeferredResult<ModelAndView> result : this.mavQueue) { result.setResult(new ModelAndView("views/html", "javaBean", new JavaBean("bar", "apple"))); this.mavQueue.remove(result); } } @ExceptionHandler @ResponseBody public String handleException(IllegalStateException ex) { return "Handled exception: " + ex.getMessage(); } }
<mvc:interceptors> <ref bean="officeHoursInterceptor"/> </mvc:interceptors> <bean id="officeHoursInterceptor" class="samples.TimeBasedAccessInterceptor"> <property name="openingTime" value="9"/> <property name="closingTime" value="18"/> </bean>
package samples; public class TimeBasedAccessInterceptor extends HandlerInterceptorAdapter { private int openingTime; private int closingTime; public void setOpeningTime(int openingTime) { this.openingTime = openingTime; } public void setClosingTime(int closingTime) { this.closingTime = closingTime; } public boolean preHandle( HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { Calendar cal = Calendar.getInstance(); int hour = cal.get(HOUR_OF_DAY); if (openingTime <= hour && hour < closingTime) { return true; } else { response.sendRedirect("http://host.com/outsideOfficeHours.html"); return false; } } }