9-SpringBoot-Web
优质
小牛编辑
149浏览
2023-12-01
9.1 快速启动一个SpringBootWeb
- @RequestMapping(value = "/user/home")表明URL,默认设置下不限制请求方式,可以使用method方法设置请求方式
- @ResponseBody表明返回数据
- application.properties中server.port=设置端口
package com.clsaa.edu.springboot;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* Created by Egg on 2017/2/25.
*/
@SpringBootApplication
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class,args);
}
}
package com.clsaa.edu.springboot;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
/**
* Created by Egg on 2017/2/25.
*/
@Controller
public class UserController {
@RequestMapping(value = "/user/home")
@ResponseBody
public String home(){
return "user home";
}
}
- 在4.3.1后还支持以下控制限制请求方式
@ResponseBody
@GetMapping(value = "/user/show")
public String show(){
return "user show";
}
@ResponseBody
@PostMapping
public String create(){
return "user create";
}
9.2 参数传递
9.2.1 @RequestParam获取表单中的参数
- 默认必须提供值,可设置required为false
- 可设置defaultValue默认值
@ResponseBody
@PostMapping(value = "user/create")
public String create(@RequestParam("username") String username
,@RequestParam("password") String password){
return "create " + username+":"+password;
}
9.2.2 @PathVariable获取url中的参数
@ResponseBody
@GetMapping("/user/{id}")
public String display(@PathVariable("id") String id){
return "user display" + id ;
}
9.2.3 通过注入的HttpServletRequest
@ResponseBody
@GetMapping("/user/host")
public String host(HttpServletRequest request){
return "user display " + request.getRemoteHost() ;
}
9.2.4 @RestController
- 表示当前controller的方法的返回值可以直接用于body输出
9.3 在SpringBoot中使用JSP
- 创建目录src/main/webapp
- 在WEBAPP下创建如下目录
- src/main/webapp/WEB-INF/jsp/fail.jsp
- src/main/webapp/WEB-INF/jsp/login.jsp
- src/main/webapp/WEB-INF/jsp/ok.jsp
- 在application.properties中做如下配置
- spring.mvc.view.prefix=/WEB-INF/jsp/
- spring.mvc.view.suffix=.jsp
- 在maven中加入如下依赖
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
</dependency>
package com.clsaa.edu.springboot;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
/**
* Created by Egg on 2017/2/26.
*/
@Controller
public class LoginController {
/**
* 跳转到JSP页面
* @param username
* @param password
* @return
*/
@PostMapping("/login")
public String login(@RequestParam("username") String username
,@RequestParam("password") String password){
if (username.equals(password)){
return "ok";
}
return "fail";
}
/**
* 给JSP传参数
* @param model
* @return
*/
@GetMapping("/login")
public String loginIndex(Model model){
model.addAttribute("username","root");
return "login";
}
}
9.4 更换web容器
- springboot默认使用tomcat作为web容器
- 可以配置为Jetty
- 排除tomcat
- 添加jetty
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>clsaa</groupId>
<artifactId>springboot</artifactId>
<version>1.0-SNAPSHOT</version>
<!--spring boot 父节点依赖,引入这个之后相关的引入就不需要添加version配置,spring boot会自动选择最合适的版本进行添加。-->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.1.RELEASE</version>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
<!--
<version></version>
由于我们在上面指定了 parent(spring boot)
-->
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>
</dependencies>
</project>
9.5 在springboot中获取静态资源
9.5.1 将静态资源放置在webapp下
- 如:src/main/webapp/user.html
- 此时我们可以直接在url中获取静态资源:http://localhost:8080/user.html
9.5.2 使用ResourceProperties
- org.springframework.boot.autoconfigure.web.ResourceProperties
- 可以看到默认资源访问路径是
- "classpath:/META-INF/resources/"
- "classpath:/resources/"
- "classpath:/static/"
- "classpath:/public/" 可以通过spring.resources.staticLocations=classpath:/html/进行配置D:\Data\MyCode\codeMaven\learn_springboot003\src\main\resources\html
@ConfigurationProperties(prefix = "spring.resources", ignoreUnknownFields = false)
public class ResourceProperties implements ResourceLoaderAware {
private static final String[] SERVLET_RESOURCE_LOCATIONS = { "/" };
private static final String[] CLASSPATH_RESOURCE_LOCATIONS = {
"classpath:/META-INF/resources/", "classpath:/resources/",
"classpath:/static/", "classpath:/public/" };
private static final String[] RESOURCE_LOCATIONS;
static {
RESOURCE_LOCATIONS = new String[CLASSPATH_RESOURCE_LOCATIONS.length
+ SERVLET_RESOURCE_LOCATIONS.length];
System.arraycopy(SERVLET_RESOURCE_LOCATIONS, 0, RESOURCE_LOCATIONS, 0,
SERVLET_RESOURCE_LOCATIONS.length);
System.arraycopy(CLASSPATH_RESOURCE_LOCATIONS, 0, RESOURCE_LOCATIONS,
SERVLET_RESOURCE_LOCATIONS.length, CLASSPATH_RESOURCE_LOCATIONS.length);
}
/**
* Locations of static resources. Defaults to classpath:[/META-INF/resources/,
* /resources/, /static/, /public/] plus context:/ (the root of the servlet context).
*/
private String[] staticLocations = RESOURCE_LOCATIONS;
/**
* Cache period for the resources served by the resource handler, in seconds.
*/
private Integer cachePeriod;
/**
* Enable default resource handling.
*/
private boolean addMappings = true;
private final Chain chain = new Chain();
private ResourceLoader resourceLoader;
9.6 拦截器
- preHandle:请求之前调用,如果返回false则终止执行请求.
- postHandle:请求之后,页面渲染之前执行.
- afterCompletion:请求完成之后执行,一般用于资源清理.
/*
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.web.servlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.method.HandlerMethod;
/**
* Workflow interface that allows for customized handler execution chains.
* Applications can register any number of existing or custom interceptors
* for certain groups of handlers, to add common preprocessing behavior
* without needing to modify each handler implementation.
*
* <p>A HandlerInterceptor gets called before the appropriate HandlerAdapter
* triggers the execution of the handler itself. This mechanism can be used
* for a large field of preprocessing aspects, e.g. for authorization checks,
* or common handler behavior like locale or theme changes. Its main purpose
* is to allow for factoring out repetitive handler code.
*
* <p>In an asynchronous processing scenario, the handler may be executed in a
* separate thread while the main thread exits without rendering or invoking the
* {@code postHandle} and {@code afterCompletion} callbacks. When concurrent
* handler execution completes, the request is dispatched back in order to
* proceed with rendering the model and all methods of this contract are invoked
* again. For further options and details see
* {@code org.springframework.web.servlet.AsyncHandlerInterceptor}
*
* <p>Typically an interceptor chain is defined per HandlerMapping bean,
* sharing its granularity. To be able to apply a certain interceptor chain
* to a group of handlers, one needs to map the desired handlers via one
* HandlerMapping bean. The interceptors themselves are defined as beans
* in the application context, referenced by the mapping bean definition
* via its "interceptors" property (in XML: a <list> of <ref>).
*
* <p>HandlerInterceptor is basically similar to a Servlet Filter, but in
* contrast to the latter it just allows custom pre-processing with the option
* of prohibiting the execution of the handler itself, and custom post-processing.
* Filters are more powerful, for example they allow for exchanging the request
* and response objects that are handed down the chain. Note that a filter
* gets configured in web.xml, a HandlerInterceptor in the application context.
*
* <p>As a basic guideline, fine-grained handler-related preprocessing tasks are
* candidates for HandlerInterceptor implementations, especially factored-out
* common handler code and authorization checks. On the other hand, a Filter
* is well-suited for request content and view content handling, like multipart
* forms and GZIP compression. This typically shows when one needs to map the
* filter to certain content types (e.g. images), or to all requests.
*
* @author Juergen Hoeller
* @since 20.06.2003
* @see HandlerExecutionChain#getInterceptors
* @see org.springframework.web.servlet.handler.HandlerInterceptorAdapter
* @see org.springframework.web.servlet.handler.AbstractHandlerMapping#setInterceptors
* @see org.springframework.web.servlet.handler.UserRoleAuthorizationInterceptor
* @see org.springframework.web.servlet.i18n.LocaleChangeInterceptor
* @see org.springframework.web.servlet.theme.ThemeChangeInterceptor
* @see javax.servlet.Filter
*/
public interface HandlerInterceptor {
/**
* Intercept the execution of a handler. Called after HandlerMapping determined
* an appropriate handler object, but before HandlerAdapter invokes the handler.
* <p>DispatcherServlet processes a handler in an execution chain, consisting
* of any number of interceptors, with the handler itself at the end.
* With this method, each interceptor can decide to abort the execution chain,
* typically sending a HTTP error or writing a custom response.
* <p><strong>Note:</strong> special considerations apply for asynchronous
* request processing. For more details see
* {@link org.springframework.web.servlet.AsyncHandlerInterceptor}.
* @param request current HTTP request
* @param response current HTTP response
* @param handler chosen handler to execute, for type and/or instance evaluation
* @return {@code true} if the execution chain should proceed with the
* next interceptor or the handler itself. Else, DispatcherServlet assumes
* that this interceptor has already dealt with the response itself.
* @throws Exception in case of errors
*/
boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception;
/**
* Intercept the execution of a handler. Called after HandlerAdapter actually
* invoked the handler, but before the DispatcherServlet renders the view.
* Can expose additional model objects to the view via the given ModelAndView.
* <p>DispatcherServlet processes a handler in an execution chain, consisting
* of any number of interceptors, with the handler itself at the end.
* With this method, each interceptor can post-process an execution,
* getting applied in inverse order of the execution chain.
* <p><strong>Note:</strong> special considerations apply for asynchronous
* request processing. For more details see
* {@link org.springframework.web.servlet.AsyncHandlerInterceptor}.
* @param request current HTTP request
* @param response current HTTP response
* @param handler handler (or {@link HandlerMethod}) that started asynchronous
* execution, for type and/or instance examination
* @param modelAndView the {@code ModelAndView} that the handler returned
* (can also be {@code null})
* @throws Exception in case of errors
*/
void postHandle(
HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
throws Exception;
/**
* Callback after completion of request processing, that is, after rendering
* the view. Will be called on any outcome of handler execution, thus allows
* for proper resource cleanup.
* <p>Note: Will only be called if this interceptor's {@code preHandle}
* method has successfully completed and returned {@code true}!
* <p>As with the {@code postHandle} method, the method will be invoked on each
* interceptor in the chain in reverse order, so the first interceptor will be
* the last to be invoked.
* <p><strong>Note:</strong> special considerations apply for asynchronous
* request processing. For more details see
* {@link org.springframework.web.servlet.AsyncHandlerInterceptor}.
* @param request current HTTP request
* @param response current HTTP response
* @param handler handler (or {@link HandlerMethod}) that started asynchronous
* execution, for type and/or instance examination
* @param ex exception thrown on handler execution, if any
* @throws Exception in case of errors
*/
void afterCompletion(
HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception;
}
9.5.1 基本使用示例
- 创建handler
package com.clsaa.edu.springboot;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* Created by Egg on 2017/2/26.
*/
@RestController
public class UserController {
@GetMapping("/user/home")
public String home(){
System.out.println("user home");
return "user home";
}
}
- 实现HanlerInterceptor接口
package com.clsaa.edu.springboot;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Created by Egg on 2017/2/26.
*/
public class LogHandlerInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("preHandler:"+handler.getClass());
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("postHandle:"+handler.getClass());
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("afterCompletion:"+handler.getClass());
}
}
- 写一个类,集成WebMvcConfigurerAdapter抽象类,然后重写addInterceptors把上一步的拦截器加进去
package com.clsaa.edu.springboot;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
/**
* Created by Egg on 2017/2/26.
*/
@SpringBootConfiguration
public class WebConfiguration extends WebMvcConfigurerAdapter{
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LogHandlerInterceptor());
}
}
- 输出
preHandler:class org.springframework.web.method.HandlerMethod
user home
postHandle:class org.springframework.web.method.HandlerMethod
afterCompletion:class org.springframework.web.method.HandlerMethod
9.6 异常处理
- 默认会使用org.springframework.boot.autoconfigure.web.ErrorMvcAutoConfiguration进行异常的处理
- 下列代码访问url会显示
Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback.
Sun Feb 26 15:45:49 CST 2017
There was an unexpected error (type=Internal Server Error, status=500).
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.IllegalArgumentException: args is empty
package com.clsaa.edu.springboot;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* Created by Egg on 2017/2/25.
*/
@SpringBootApplication
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class,args);
}
}
package com.clsaa.edu.springboot;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* Created by Egg on 2017/2/26.
*/
@RestController
public class UserController {
@GetMapping("/user/help")
public String help(){
throw new IllegalArgumentException("args is empty");
}
}
- 我们可以通过@SpringBootApplication(exclude = ErrorMvcAutoConfiguration.class)取消默认的异常处理类
9.6.1 加入自己的异常处理逻辑
- 实现以下接口
public interface ErrorPageRegistrar {
/**
* Register pages as required with the given registry.
* @param registry the error page registry
*/
void registerErrorPages(ErrorPageRegistry registry);
}
- 通过调用registry.addErrorPages(),调用之前我们要先构造ErrorPage,其构造可根据http状态码对应页面也可以根据具体的异常对应页面.
public ErrorPage(HttpStatus status, String path) {
this.status = status;
this.exception = null;
this.path = path;
}
public ErrorPage(Class<? extends Throwable> exception, String path) {
this.status = null;
this.exception = exception;
this.path = path;
}
- 代码实现
package com.clsaa.edu.springboot;
import org.springframework.boot.autoconfigure.web.ErrorMvcAutoConfiguration;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* Created by Egg on 2017/2/26.
*/
@RestController
public class UserController {
@GetMapping("/user/help")
public String help(){
throw new IllegalArgumentException("args is empty");
}
}
package com.clsaa.edu.springboot;
import org.springframework.boot.web.servlet.ErrorPage;
import org.springframework.boot.web.servlet.ErrorPageRegistrar;
import org.springframework.boot.web.servlet.ErrorPageRegistry;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
/**
* Created by Egg on 2017/2/26.
*/
@Component
public class CommonErrorPageRegistry implements ErrorPageRegistrar {
@Override
public void registerErrorPages(ErrorPageRegistry registry) {
ErrorPage errorPage404 = new ErrorPage(HttpStatus.NOT_FOUND,"/404.html");
ErrorPage errorPage500 = new ErrorPage(HttpStatus.INTERNAL_SERVER_ERROR,"/500.html");
registry.addErrorPages(errorPage404,errorPage500);
}
}
9.6.2 SpringMVC当前Controller异常处理
package com.clsaa.edu.springboot;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.io.FileNotFoundException;
/**
* Created by Egg on 2017/2/26.
*/
@RestController
public class BookController {
@ExceptionHandler(value = {FileNotFoundException.class,ClassNotFoundException.class})
public String errorHandlerList(){
return "file not found exception";
}
@GetMapping("/book/list")
public String list()throws FileNotFoundException{
throw new FileNotFoundException("file not found");
}
@GetMapping("/book/error")
public String error()throws ClassNotFoundException{
throw new ClassNotFoundException("class not found");
}
}
9.6.3 全局异常处理
package com.clsaa.edu.springboot;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
/**
* Created by Egg on 2017/2/26.
*/
@ControllerAdvice
public class GlobeExceptionHandler {
@ExceptionHandler(value = Exception.class)
@ResponseBody
public Demo errorHandler(Exception e){
Demo demo = new Demo();
demo.setName("name");
return demo;
}
}