文章目錄
目錄:
本文章的大綱如下:
第一部分:
一、請求method
springboot的請求註解是@RequestMapping(value = "/user/home",method= RequestMethod.GET)
spring4.3以後可以使用: @GetMapping("/user/home2")
,@PostMapping("/user/create")
等語義化表示get,post等請求方法。
二、傳遞參數的3種方式
1.RequestParam
@RequestParam 默認必填,可以設置非必填,和默認值
:
/**
* @RequestParam 註解默認是參數必須提供值
* @param username
* @param password
* @return
*/
@PostMapping("/user/create")
@ResponseBody
public String create(@RequestParam(value = "username",defaultValue = "admin") String username, @RequestParam(value="password",required = false) String password){
return "user create, username=" + username + ",password="+password;
}
2.url方式 @PathVariable
/**
* 獲取url的方式/user/1 ,/user/2
* @param id
* @return
*/
@GetMapping("/user/{id}")
@ResponseBody
public String display(@PathVariable("id") String id){
return "user display is=" + id;
}
3.HttpServletRequest方式
@ResponseBody
@GetMapping("/user/ip")
public String edit(HttpServletRequest req){
return "user edit " + req.getRemoteHost();
}
三、@RestController
這個註解相當於@Controller+@RequestBody,用在視圖訪問層,表示當前controller的方法的返回值並可以直接用於body測試.返回json格式數據:
四、springboot的數據渲染到jsp頁面
需要的步驟:
1.配置文件:
application.properties加入2個配置項,執行頁面路徑和後綴
spring.mvc.view.prefix=/WEB-INF/jsp/
spring.mvc.view.suffix=.jsp
2.加入 tomcat-embed-jasper的依賴
pom.xml中:
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<!-- <version>9.0.27</version>-->
</dependency>
<!--servlet依賴jar-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
</dependency>
<!--Jstl標籤依賴的jar包start-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>
build下加入resoures
<resources>
<!-- <resource>-->
<!-- <directory>src/main/java</directory>-->
<!-- <includes>-->
<!-- <include>**/*.xml</include>-->
<!-- </includes>-->
<!-- </resource>-->
<!-- <resource>-->
<!-- <directory>src/main/resources</directory>-->
<!-- <includes>-->
<!-- <include>**/*.*</include>-->
<!-- </includes>-->
<!-- </resource>-->
<resource>
<directory>src/main/webapp</directory>
<targetPath>META-INF/resources</targetPath>
<includes>
<include>**/*.*</include>
</includes>
</resource>
</resources>
</build>
3.測試:
@Controller
public class LoginController {
@PostMapping("/login")
public String login(@RequestParam(value = "username") String username, @RequestParam(value = "password") String password) {
if (username.equals(password)) {
return "ok";
}
return "fail";
}
/**
* 給jsp傳參數,類似req.setAttribute
* @param model
* @return
*/
@GetMapping("/login")
public String loginIndex(Model model){
model.addAttribute("username", "root");
return "login";
}
}
login.jsp頁面:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>this is login page</h1>
<p>username is ${username}</p>
</body>
</html>
運行入口函數
@SpringBootApplication
public class Demo11Application {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(Demo11Application.class, args);
}
}
運行結果,顯示已經數據已經渲染到jsp頁面:
五、springboot渲染數據到freemarker頁面:
在springboot中使用freemarker的步驟
1. 在pom.xml裏面加入依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
2.配置文件修改freemarker的位置和後綴
看配置信息可以看源碼: FreeMarkerProperties
:
我們在application.properties中修改配置信息:
spring.freemarker.templateLoaderPath=classpath:/ftl/
spring.freemarker.suffix=.ftl
3.測試:
@Controller
public class AccountController {
@RequestMapping("/reg")
public String req(Model model){
model.addAttribute("username", "root");
return "reg";
}
}
頁面代碼:
運行入口函數:
@SpringBootApplication
public class Demo11Application {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(Demo11Application.class, args);
}
}
查看頁面,顯示已經渲染到HTML頁面:
六、更換web容器
pringboot 容器默認使用的是tomcat作爲外部容器, 可以更換爲jetty。
具體操作如下:
1.排除tomcat,加入jetty的依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<!-- 排除tomcat-->
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>
2.測試:
運行入口函數:
@SpringBootApplication
public class Demo11Application {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(Demo11Application.class, args);
}
}
運行結果,看打印結果,已顯示爲jetty:
源碼地址:
https://github.com/hufanglei/springboot-v-study/tree/springboot-web1
第二部分
一、請求靜態資源:
1. 放在webapp下 加resources.xml 可以訪問到
做個案例,測試下:
- 在webapp下準備一個圖片和一個user.html
- pom上加入資源
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/webapp</directory>
<!--注意此次必須要放在此目錄下才能被訪問到 -->
<targetPath>META-INF/resources</targetPath>
<includes>
<include>**/**</include>
</includes>
</resource>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
<includes>
<include>**/*</include>
</includes>
</resource>
</resources>
</build>
- 入口函數啓動:
@SpringBootApplication
public class Demo12Application {
public static void main(String[] args) {
SpringApplication.run(Demo12Application.class, args);
}
}
- 查看效果,顯示圖片和頁面都可以訪問到:
2. springboot默認的靜態資源的路徑是:
- “classpath:/META-INF/resources/”,
- “classpath:/resources/”,
- “classpath:/static/”,
- “classpath:/public/” };
我們可以在ResourceProperties源碼中找到這個原因:
在public下準備個文件看下能否訪問到:
運行入口函數:看下頁面,顯示已經訪問到public下的html頁面和css。
3.可以通過spring.resources.static-locations 配置項修改默認靜態資源路徑
試一試:
我們指定html文件下爲我們的默認靜態資源路徑,並準備個login.html,看下能否訪問:
運行,看下頁面效果:
結果顯示已經訪問到html下的頁面。修改默認的靜態資源路徑成功。
二、sevlet,filter,listener的2種配置方式:
1.springboot如何使用servlet
有2種方式,一種是用sevlet3加入口函數註解掃碼方式,一種是配置類注入servlet方式:
現在動手試試:
① 方法一:(servlet3可以使用這種方法)
- 1)編寫servlet,然後加上響應的註解@WebServlet
- 2)需要啓用@ServletComonentScan註解
@WebServlet("/user.do")
public class BookServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public BookServlet() {
System.out.println("===servet BookServlet========");
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.getWriter().println("book servlet");
}
}
@ServletComponentScan
@SpringBootApplication
public class Demo12Application {
public static void main(String[] args) {
SpringApplication.run(Demo12Application.class, args);
}
}
運行入口,訪問BookServlet 映射的user.do路徑:
說明servlet已經訪問成功。
② 方法2:(servlet2.5及以下版本可以使用這種方法)
- 1) 書寫servlet無需對位映射,不用加@WebServlet註解
- 2)書寫個配置類,使用@Bean注入,注入的話,需要調用ServletRegistrationBean的構造方法。
代碼如下:
servlet:
public class BookServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public BookServlet() {
System.out.println("===servet BookServlet========");
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.getWriter().println("book servlet");
}
}
配置類:
@SpringBootConfiguration
public class ServletConfigration {
@Bean
public ServletRegistrationBean createBookServlet(){
ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(new BookServlet(), "/book.do");
return servletRegistrationBean;
}
}
入口函數
@SpringBootApplication
public class Demo12Application {
public static void main(String[] args) {
SpringApplication.run(Demo12Application.class, args);
}
}
啓動並測試:結果顯示ok:
2.springboot如何使用過濾器
使用的方式和servet差不多,一種是@WebFilter("/*")註解方式,另一種是也是通過配置類:
不過生成filter的類是 fileter -》 FilterRegistrationBean。
方式1通過@WebFilter("/*")+入口@ServletComponentScan註解實現過濾器
@WebFilter("/*")
public class LogFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("==LogFilter =init===");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
System.out.println("==LogFilter =filter ==="+ request.getRemoteHost());
chain.doFilter(request,response);
}
@Override
public void destroy() {
System.out.println("=====destroy======");
}
}
入口函數
@ServletComponentScan
@SpringBootApplication
public class Demo12Application {
public static void main(String[] args) {
SpringApplication.run(Demo12Application.class, args);
}
}
啓動入口函數,訪問剛纔的servlet,看下控制檯打印情況:
顯示過濾器已經被注入了。
方式2:配置類+注入bean,
代碼:
public class EchoFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
System.out.println("spring boot web filter "+ req.getRequestURI());
chain.doFilter(request,response);
}
@Override
public void destroy() {
}
}
配置類:
@SpringBootConfiguration
public class ServletConfigration {
@Bean
public FilterRegistrationBean createFilterRegistrationBean(){
FilterRegistrationBean filter = new FilterRegistrationBean();
filter.setFilter(new EchoFilter());
filter.setUrlPatterns(Arrays.asList("/book.do"));
return filter;
}
}
入口函數
@SpringBootApplication
public class Demo12Application {
public static void main(String[] args) {
SpringApplication.run(Demo12Application.class, args);
}
}
測試:
運行結果:顯示過濾器已經起作用了了。
3.springboot如何使用監聽器
1)方式1:@WebListener+@ServletComponentScan
@WebListener
public class MyListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
System.out.println("StartUpListener app startup at " + LocalDateTime.now().toString());
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
}
}
@ServletComponentScan
@SpringBootApplication
public class Demo12Application {
public static void main(String[] args) {
SpringApplication.run(Demo12Application.class, args);
}
}
啓動:
2)方式2:配置類+@bean+ServletListenerRegistrationBean構造函數注入
public class StartUpListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
System.out.println("StartUpListener app startup at " + LocalDateTime.now().toString());
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
}
}
@SpringBootConfiguration
public class ServletConfigration {
@Bean
public ServletListenerRegistrationBean createServletListenerRegistrationBean(){
ServletListenerRegistrationBean listener = new ServletListenerRegistrationBean(new StartUpListener());
return listener;
}
}
@SpringBootApplication
public class Demo12Application {
public static void main(String[] args) {
SpringApplication.run(Demo12Application.class, args);
}
}
啓動:
源碼地址:
https://github.com/hufanglei/springboot-v-study/tree/demo12
第三部分
1.攔截器:
攔截器的使用步驟
①寫一個攔截器,實現HandlerInterceptor接口
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class LogHandlerInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("=========preHandle===============" + handler);
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("=========postHandle===============" + handler);
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("=========afterCompletion===============" + handler);
}
}
- preHandle: controller執行之前調用
- postHandle: controller執行之後,且頁面渲染之前調用
- afterCompletion: 頁面渲染之後調用,一般用於資源清理操作
②寫一個類,實現WebMvcConfigurer接口,重寫addInterceptors方法(已經過時),並調用registry.addInterceptor把上一步的攔截器加進去
@SpringBootConfiguration
public class WebConfiguration implements WebMvcConfigurer {
// @Override
// public void addResourceHandlers(ResourceHandlerRegistry registry) {
// registry.addResourceHandler("/web/**").addResourceLocations("classpath:/web/");
// }
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LogHandlerInterceptor());
}
}
測試
寫個controller
@RestController
public class UserController {
@GetMapping("/user/home")
public String home(){
return "user home";
}
@GetMapping("/user/help")
public String help() {
throw new IllegalArgumentException("args is empty");
}
}
@SpringBootApplication
public class Demo13Application {
public static void main(String[] args) {
SpringApplication.run(Demo13Application.class, args);
}
}
頁面測試:
看下控制檯:
顯示已經攔截controller。
2.異常處理:
1)默認異常處理邏輯ErrorMvcAutoConfiguration
當我們訪問一個不存在的url時候會出現如下頁面:
看下ErrorMvcAutoConfiguration源碼:
排除springboot默認顯示的異常頁方式1:
可以看到找到就是渲染的這段代碼。
我們可以關閉這個默認異常頁配置:
看了源碼再去修改applicaiton.properties
server.error.whitelabel.enabled=false
重新運行:
輸入一個無效的url,就沒有默認的異常處理頁了。
排除springboot默認顯示的異常頁方式2:
也可以直接在入口函數上,用exclude去排除自動註冊的這個默認異常註冊類:
@SpringBootApplication(exclude = ErrorMvcAutoConfiguration.class)
public class Demo13Application {
public static void main(String[] args) {
SpringApplication.run(Demo13Application.class, args);
}
}
2).自處理異常
定義一個controller。手動拋出異常:
①在當前controller類使用@ExceptionHandler處理異常
@RestController
public class BookController {
// @ExceptionHandler(value = FileNotFoundException.class)
@ExceptionHandler(value = FileNotFoundException.class)
public String error(Exception e){
return "file not found exception==== " + e.getMessage();
}
@GetMapping("/book/error1")
public String list() throws FileNotFoundException {
throw new FileNotFoundException("file not found");
}
@GetMapping("/book/error2")
public String error2() throws ClassNotFoundException {
throw new ClassNotFoundException("file not found");
}
@GetMapping("/user/null")
public String empty() {
throw new NullPointerException("args is empty");
}
}
我們看到訪問list,error2,empty的方法都會拋出異常,同時定義一個處理異常的方法error:
@ExceptionHandler(value = FileNotFoundException.class)
public String error(Exception e){
return "file not found exception==== " + e.getMessage();
}
如果匹配到 @ExceptionHandler中value對應的異常,就可以在error方法中處理異常,或者跳轉到錯誤頁面。
我們訪問/user/null:
因爲
@GetMapping("/user/null") public String empty() { throw new NullPointerException("args is empty"); } }
對應的是空指針異常,而@ExceptionHandler(value = FileNotFoundException.class)
是文件找不到的異常,所以controller沒給我們處理。
然後訪問@GetMapping("/book/error1")
看到已經幫我們處理了。
如果想要@ExceptionHandler當前類全部的方法,就可以擴大異常範圍,改成exception.class就可了。
@ExceptionHandler(value = Exception.class)
public String error(Exception e){
return " exception==== " + e.getMessage();
}
②全局處理異常的2種方式:
- a.方式1:使用ErrorPageRegistrar的接口
寫一個類,實現ErrorPageRegistrar接口,實現registerErrorPages,在該方法裏面,添加具體的錯誤處理邏輯
@Component
public class CommonErrorRegistry implements ErrorPageRegistrar {
@Override
public void registerErrorPages(ErrorPageRegistry registry) {
ErrorPage e404 = new ErrorPage(HttpStatus.NOT_FOUND, "/404.html");
ErrorPage e500 = new ErrorPage(INTERNAL_SERVER_ERROR, "/500.html");
ErrorPage argsPage= new ErrorPage(IllegalArgumentException.class, "/args.html");
registry.addErrorPages(e404, e500,argsPage);
}
}
- b.方式2:@ControllerAdvice
具體做法:
-1.寫一個類,需要加上@ControllerAdvice註解
-2.寫一個異常處理方法,需要加上@Exception(value=Exception.class)這個註解,在該方法上處理異常,
@ControllerAdvice
public class GloabalExceptinHandler {
@ExceptionHandler(value = Exception.class)
@ResponseBody
public String errorHandler(Exception e){
return "gloabal error " + e.getClass().getName()+ " =="+ e.getMessage();
}
@ExceptionHandler(value = NullPointerException.class)
@ResponseBody
public String errorHandler2(Exception e){
return "gloabal error2 " + e.getClass().getName()+ " =="+ e.getMessage();
}
}
這2種方法都可以跳轉到自定義的頁面,或者拋出異常。
看下這個ErrorPage類的源碼:
可以看到,errorpage可以通過請求響應狀態碼控制跳轉頁面,可以根據具體異常控制跳轉頁。
演示代碼git地址:
https://github.com/hufanglei/springboot-v-study/tree/springbootweb3
以上就說了springbootweb的大體內容,基礎springboot2的。關於請求方法參數,數據渲染到jsp頁面和freemarker頁面的配置方式,替換內置tomcat的方法,請求靜態頁面的設置,過濾器,監聽器,servlet的2種註冊方式,攔截器的自定義,異常處理的類上的處理,和全局處理的2種方式。
個人微信公號:
搜索: 怒放de每一天
不定時推送相關文章,期待和大家一起成長!!
完