springboot原理實戰(14)--springbootweb

文章目錄

目錄:

本文章的大綱如下:
在這裏插入圖片描述

第一部分:

一、請求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每一天
不定時推送相關文章,期待和大家一起成長!!
在這裏插入圖片描述


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章