springboot原理实战(14)--springbootweb

ゞ 浴缸里的玫瑰 2023-07-17 15:36 74阅读 0赞

文章目录

  • 目录:
  • 第一部分:
    • 一、请求method
    • 二、传递参数的3种方式
      • 1.RequestParam
      • 2.url方式 @PathVariable
      • 3.HttpServletRequest方式
    • 三、@RestController
    • 四、springboot的数据渲染到jsp页面
      • 1.配置文件:
      • 2.加入 tomcat-embed-jasper的依赖
      • 3.测试:
    • 五、springboot渲染数据到freemarker页面:
        1. 在pom.xml里面加入依赖
      • 2.配置文件修改freemarker的位置和后缀
      • 3.测试:
    • 六、更换web容器
      • 1.排除tomcat,加入jetty的依赖
      • 2.测试:
  • 第二部分
    • 一、请求静态资源:
        1. 放在webapp下 加resources.xml 可以访问到
        1. springboot默认的静态资源的路径是:
      • 3.可以通过spring.resources.static-locations 配置项修改默认静态资源路径
    • 二、sevlet,filter,listener的2种配置方式:
      • 1.springboot如何使用servlet
        • ① 方法一:(servlet3可以使用这种方法)
        • ② 方法2:(servlet2.5及以下版本可以使用这种方法)
      • 2.springboot如何使用过滤器
        • 方式1通过@WebFilter(“/*“)+入口@ServletComponentScan注解实现过滤器
        • 方式2:配置类+注入bean,
      • 3.springboot如何使用监听器
        • 1)方式1:@WebListener+@ServletComponentScan
        • 2)方式2:配置类+@bean+ServletListenerRegistrationBean构造函数注入
  • 第三部分
    • 1.拦截器:
      • ①写一个拦截器,实现HandlerInterceptor接口
      • ②写一个类,实现WebMvcConfigurer接口,重写addInterceptors方法(已经过时),并调用registry.addInterceptor把上一步的拦截器加进去
      • 测试
    • 2.异常处理:
      • 1)默认异常处理逻辑ErrorMvcAutoConfiguration
        • 排除springboot默认显示的异常页方式1:
        • 排除springboot默认显示的异常页方式2:
      • 2).自处理异常
        • ①在当前controller类使用@ExceptionHandler处理异常
        • ②全局处理异常的2种方式:

目录:

本文章的大纲如下:
在这里插入图片描述

第一部分:

一、请求method

springboot的请求注解是@RequestMapping(value = "/user/home",method= RequestMethod.GET)
spring4.3以后可以使用: @GetMapping("/user/home2"),@PostMapping("/user/create")等语义化表示get,post等请求方法。
在这里插入图片描述

二、传递参数的3种方式

1.RequestParam

@RequestParam 默认必填,可以设置非必填,和默认值:

  1. /** * @RequestParam 注解默认是参数必须提供值 * @param username * @param password * @return */
  2. @PostMapping("/user/create")
  3. @ResponseBody
  4. public String create(@RequestParam(value = "username",defaultValue = "admin") String username, @RequestParam(value="password",required = false) String password){
  5. return "user create, username=" + username + ",password="+password;
  6. }

2.url方式 @PathVariable

  1. /** * 获取url的方式/user/1 ,/user/2 * @param id * @return */
  2. @GetMapping("/user/{id}")
  3. @ResponseBody
  4. public String display(@PathVariable("id") String id){
  5. return "user display is=" + id;
  6. }

3.HttpServletRequest方式

  1. @ResponseBody
  2. @GetMapping("/user/ip")
  3. public String edit(HttpServletRequest req){
  4. return "user edit " + req.getRemoteHost();
  5. }

三、@RestController

这个注解相当于@Controller+@RequestBody,用在视图访问层,表示当前controller的方法的返回值并可以直接用于body测试.返回json格式数据:
在这里插入图片描述

四、springboot的数据渲染到jsp页面

需要的步骤:

1.配置文件:

application.properties加入2个配置项,执行页面路径和后缀

  1. spring.mvc.view.prefix=/WEB-INF/jsp/
  2. spring.mvc.view.suffix=.jsp

2.加入 tomcat-embed-jasper的依赖

pom.xml中:

  1. <dependency>
  2. <groupId>org.apache.tomcat.embed</groupId>
  3. <artifactId>tomcat-embed-jasper</artifactId>
  4. <!-- <version>9.0.27</version>-->
  5. </dependency>
  6. <!--servlet依赖jar-->
  7. <dependency>
  8. <groupId>javax.servlet</groupId>
  9. <artifactId>javax.servlet-api</artifactId>
  10. </dependency>
  11. <!--Jstl标签依赖的jar包start-->
  12. <dependency>
  13. <groupId>javax.servlet</groupId>
  14. <artifactId>jstl</artifactId>
  15. </dependency>

build下加入resoures

  1. <resources>
  2. <!-- <resource>-->
  3. <!-- <directory>src/main/java</directory>-->
  4. <!-- <includes>-->
  5. <!-- <include>**/*.xml</include>--> <!-- </includes>--> <!-- </resource>--> <!-- <resource>--> <!-- <directory>src/main/resources</directory>--> <!-- <includes>--> <!-- <include>**/*.*</include>-->
  6. <!-- </includes>-->
  7. <!-- </resource>-->
  8. <resource>
  9. <directory>src/main/webapp</directory>
  10. <targetPath>META-INF/resources</targetPath>
  11. <includes>
  12. <include>**/*.*</include> </includes> </resource> </resources> </build>

3.测试:

  1. @Controller
  2. public class LoginController {
  3. @PostMapping("/login")
  4. public String login(@RequestParam(value = "username") String username, @RequestParam(value = "password") String password) {
  5. if (username.equals(password)) {
  6. return "ok";
  7. }
  8. return "fail";
  9. }
  10. /** * 给jsp传参数,类似req.setAttribute * @param model * @return */
  11. @GetMapping("/login")
  12. public String loginIndex(Model model){
  13. model.addAttribute("username", "root");
  14. return "login";
  15. }
  16. }

login.jsp页面:

  1. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
  2. <html>
  3. <head>
  4. <title>Title</title>
  5. </head>
  6. <body>
  7. <h1>this is login page</h1>
  8. <p>username is ${username}</p>
  9. </body>
  10. </html>

运行入口函数

  1. @SpringBootApplication
  2. public class Demo11Application {
  3. public static void main(String[] args) {
  4. ConfigurableApplicationContext context = SpringApplication.run(Demo11Application.class, args);
  5. }
  6. }

运行结果,显示已经数据已经渲染到jsp页面:
在这里插入图片描述

五、springboot渲染数据到freemarker页面:

在springboot中使用freemarker的步骤

1. 在pom.xml里面加入依赖

  1. <dependency>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-starter-freemarker</artifactId>
  4. </dependency>

2.配置文件修改freemarker的位置和后缀

看配置信息可以看源码: FreeMarkerProperties:
在这里插入图片描述
我们在application.properties中修改配置信息:

  1. spring.freemarker.templateLoaderPath=classpath:/ftl/
  2. spring.freemarker.suffix=.ftl

3.测试:

  1. @Controller
  2. public class AccountController {
  3. @RequestMapping("/reg")
  4. public String req(Model model){
  5. model.addAttribute("username", "root");
  6. return "reg";
  7. }
  8. }

页面代码:
在这里插入图片描述
运行入口函数:

  1. @SpringBootApplication
  2. public class Demo11Application {
  3. public static void main(String[] args) {
  4. ConfigurableApplicationContext context = SpringApplication.run(Demo11Application.class, args);
  5. }
  6. }

查看页面,显示已经渲染到HTML页面:
在这里插入图片描述

六、更换web容器

pringboot 容器默认使用的是tomcat作为外部容器, 可以更换为jetty。
具体操作如下:

1.排除tomcat,加入jetty的依赖

  1. <dependency>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-starter-web</artifactId>
  4. <!-- 排除tomcat-->
  5. <exclusions>
  6. <exclusion>
  7. <groupId>org.springframework.boot</groupId>
  8. <artifactId>spring-boot-starter-tomcat</artifactId>
  9. </exclusion>
  10. </exclusions>
  11. </dependency>
  12. <dependency>
  13. <groupId>org.springframework.boot</groupId>
  14. <artifactId>spring-boot-starter-jetty</artifactId>
  15. </dependency>

2.测试:

运行入口函数:

  1. @SpringBootApplication
  2. public class Demo11Application {
  3. public static void main(String[] args) {
  4. ConfigurableApplicationContext context = SpringApplication.run(Demo11Application.class, args);
  5. }
  6. }

运行结果,看打印结果,已显示为jetty:
在这里插入图片描述

源码地址:
https://github.com/hufanglei/springboot-v-study/tree/springboot-web1


第二部分

一、请求静态资源:

1. 放在webapp下 加resources.xml 可以访问到

做个案例,测试下:

  • 在webapp下准备一个图片和一个user.html
    在这里插入图片描述
  • pom上加入资源




    org.springframework.boot
    spring-boot-maven-plugin




    src/main/webapp

    META-INF/resources

    /



    src/main/resources
    true

    */




  • 入口函数启动:

    @SpringBootApplication
    public class Demo12Application {

    1. public static void main(String[] args) {
    2. SpringApplication.run(Demo12Application.class, args);
    3. }

    }

  • 查看效果,显示图片和页面都可以访问到:
    在这里插入图片描述

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 {

    1. private static final long serialVersionUID = 1L;
    2. public BookServlet() {
    3. System.out.println("===servet BookServlet========");
    4. }
    5. @Override
    6. protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    7. resp.getWriter().println("book servlet");
    8. }

    }

    @ServletComponentScan
    @SpringBootApplication
    public class Demo12Application {

    1. public static void main(String[] args) {
    2. SpringApplication.run(Demo12Application.class, args);
    3. }

    }

运行入口,访问BookServlet 映射的user.do路径:
在这里插入图片描述
说明servlet已经访问成功。

② 方法2:(servlet2.5及以下版本可以使用这种方法)

  • 1) 书写servlet无需对位映射,不用加@WebServlet注解
  • 2)书写个配置类,使用@Bean注入,注入的话,需要调用ServletRegistrationBean的构造方法。
    代码如下:
    servlet:

    public class BookServlet extends HttpServlet {

    1. private static final long serialVersionUID = 1L;
    2. public BookServlet() {
    3. System.out.println("===servet BookServlet========");
    4. }
    5. @Override
    6. protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    7. resp.getWriter().println("book servlet");
    8. }

    }

配置类:

  1. @SpringBootConfiguration
  2. public class ServletConfigration {
  3. @Bean
  4. public ServletRegistrationBean createBookServlet(){
  5. ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(new BookServlet(), "/book.do");
  6. return servletRegistrationBean;
  7. }
  8. }

入口函数

  1. @SpringBootApplication
  2. public class Demo12Application {
  3. public static void main(String[] args) {
  4. SpringApplication.run(Demo12Application.class, args);
  5. }
  6. }

启动并测试:结果显示ok:
在这里插入图片描述

2.springboot如何使用过滤器

使用的方式和servet差不多,一种是@WebFilter(“/*“)注解方式,另一种是也是通过配置类:
不过生成filter的类是 fileter -》 FilterRegistrationBean。

方式1通过@WebFilter(“/*“)+入口@ServletComponentScan注解实现过滤器

  1. @WebFilter("/*")
  2. public class LogFilter implements Filter {
  3. @Override
  4. public void init(FilterConfig filterConfig) throws ServletException {
  5. System.out.println("==LogFilter =init===");
  6. }
  7. @Override
  8. public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
  9. System.out.println("==LogFilter =filter ==="+ request.getRemoteHost());
  10. chain.doFilter(request,response);
  11. }
  12. @Override
  13. public void destroy() {
  14. System.out.println("=====destroy======");
  15. }
  16. }

入口函数

  1. @ServletComponentScan
  2. @SpringBootApplication
  3. public class Demo12Application {
  4. public static void main(String[] args) {
  5. SpringApplication.run(Demo12Application.class, args);
  6. }
  7. }

启动入口函数,访问刚才的servlet,看下控制台打印情况:
在这里插入图片描述
显示过滤器已经被注入了。

方式2:配置类+注入bean,

代码:

  1. public class EchoFilter implements Filter {
  2. @Override
  3. public void init(FilterConfig filterConfig) throws ServletException {
  4. }
  5. @Override
  6. public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
  7. HttpServletRequest req = (HttpServletRequest) request;
  8. System.out.println("spring boot web filter "+ req.getRequestURI());
  9. chain.doFilter(request,response);
  10. }
  11. @Override
  12. public void destroy() {
  13. }
  14. }

配置类:

  1. @SpringBootConfiguration
  2. public class ServletConfigration {
  3. @Bean
  4. public FilterRegistrationBean createFilterRegistrationBean(){
  5. FilterRegistrationBean filter = new FilterRegistrationBean();
  6. filter.setFilter(new EchoFilter());
  7. filter.setUrlPatterns(Arrays.asList("/book.do"));
  8. return filter;
  9. }
  10. }

入口函数

  1. @SpringBootApplication
  2. public class Demo12Application {
  3. public static void main(String[] args) {
  4. SpringApplication.run(Demo12Application.class, args);
  5. }
  6. }

测试:
在这里插入图片描述

运行结果:显示过滤器已经起作用了了。
在这里插入图片描述

3.springboot如何使用监听器

1)方式1:@WebListener+@ServletComponentScan

  1. @WebListener
  2. public class MyListener implements ServletContextListener {
  3. @Override
  4. public void contextInitialized(ServletContextEvent sce) {
  5. System.out.println("StartUpListener app startup at " + LocalDateTime.now().toString());
  6. }
  7. @Override
  8. public void contextDestroyed(ServletContextEvent sce) {
  9. }
  10. }
  11. @ServletComponentScan
  12. @SpringBootApplication
  13. public class Demo12Application {
  14. public static void main(String[] args) {
  15. SpringApplication.run(Demo12Application.class, args);
  16. }
  17. }

启动:
在这里插入图片描述

2)方式2:配置类+@bean+ServletListenerRegistrationBean构造函数注入

  1. public class StartUpListener implements ServletContextListener {
  2. @Override
  3. public void contextInitialized(ServletContextEvent sce) {
  4. System.out.println("StartUpListener app startup at " + LocalDateTime.now().toString());
  5. }
  6. @Override
  7. public void contextDestroyed(ServletContextEvent sce) {
  8. }
  9. }
  10. @SpringBootConfiguration
  11. public class ServletConfigration {
  12. @Bean
  13. public ServletListenerRegistrationBean createServletListenerRegistrationBean(){
  14. ServletListenerRegistrationBean listener = new ServletListenerRegistrationBean(new StartUpListener());
  15. return listener;
  16. }
  17. }
  18. @SpringBootApplication
  19. public class Demo12Application {
  20. public static void main(String[] args) {
  21. SpringApplication.run(Demo12Application.class, args);
  22. }
  23. }

启动:
在这里插入图片描述
源码地址:
https://github.com/hufanglei/springboot-v-study/tree/demo12


第三部分

1.拦截器:

拦截器的使用步骤

①写一个拦截器,实现HandlerInterceptor接口

  1. import org.springframework.web.servlet.HandlerInterceptor;
  2. import org.springframework.web.servlet.ModelAndView;
  3. import javax.servlet.http.HttpServletRequest;
  4. import javax.servlet.http.HttpServletResponse;
  5. public class LogHandlerInterceptor implements HandlerInterceptor {
  6. @Override
  7. public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
  8. System.out.println("=========preHandle===============" + handler);
  9. return true;
  10. }
  11. @Override
  12. public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
  13. System.out.println("=========postHandle===============" + handler);
  14. }
  15. @Override
  16. public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
  17. System.out.println("=========afterCompletion===============" + handler);
  18. }
  19. }
  • preHandle: controller执行之前调用
  • postHandle: controller执行之后,且页面渲染之前调用
  • afterCompletion: 页面渲染之后调用,一般用于资源清理操作

②写一个类,实现WebMvcConfigurer接口,重写addInterceptors方法(已经过时),并调用registry.addInterceptor把上一步的拦截器加进去

  1. @SpringBootConfiguration
  2. public class WebConfiguration implements WebMvcConfigurer {
  3. // @Override
  4. // public void addResourceHandlers(ResourceHandlerRegistry registry) {
  5. // registry.addResourceHandler("/web/**").addResourceLocations("classpath:/web/");
  6. // }
  7. @Override
  8. public void addInterceptors(InterceptorRegistry registry) {
  9. registry.addInterceptor(new LogHandlerInterceptor());
  10. }
  11. }

测试

写个controller

  1. @RestController
  2. public class UserController {
  3. @GetMapping("/user/home")
  4. public String home(){
  5. return "user home";
  6. }
  7. @GetMapping("/user/help")
  8. public String help() {
  9. throw new IllegalArgumentException("args is empty");
  10. }
  11. }
  12. @SpringBootApplication
  13. public class Demo13Application {
  14. public static void main(String[] args) {
  15. SpringApplication.run(Demo13Application.class, args);
  16. }
  17. }

页面测试:
在这里插入图片描述
看下控制台:
在这里插入图片描述
显示已经拦截controller。

2.异常处理:

1)默认异常处理逻辑ErrorMvcAutoConfiguration

当我们访问一个不存在的url时候会出现如下页面:
在这里插入图片描述
看下ErrorMvcAutoConfiguration源码:
在这里插入图片描述
在这里插入图片描述

排除springboot默认显示的异常页方式1:

可以看到找到就是渲染的这段代码。
我们可以关闭这个默认异常页配置:
在这里插入图片描述
看了源码再去修改applicaiton.properties

  1. server.error.whitelabel.enabled=false

重新运行:
在这里插入图片描述
输入一个无效的url,就没有默认的异常处理页了。

排除springboot默认显示的异常页方式2:

也可以直接在入口函数上,用exclude去排除自动注册的这个默认异常注册类:

  1. @SpringBootApplication(exclude = ErrorMvcAutoConfiguration.class)
  2. public class Demo13Application {
  3. public static void main(String[] args) {
  4. SpringApplication.run(Demo13Application.class, args);
  5. }
  6. }

2).自处理异常

定义一个controller。手动抛出异常:

①在当前controller类使用@ExceptionHandler处理异常

  1. @RestController
  2. public class BookController {
  3. // @ExceptionHandler(value = FileNotFoundException.class)
  4. @ExceptionHandler(value = FileNotFoundException.class)
  5. public String error(Exception e){
  6. return "file not found exception==== " + e.getMessage();
  7. }
  8. @GetMapping("/book/error1")
  9. public String list() throws FileNotFoundException {
  10. throw new FileNotFoundException("file not found");
  11. }
  12. @GetMapping("/book/error2")
  13. public String error2() throws ClassNotFoundException {
  14. throw new ClassNotFoundException("file not found");
  15. }
  16. @GetMapping("/user/null")
  17. public String empty() {
  18. throw new NullPointerException("args is empty");
  19. }
  20. }

我们看到访问list,error2,empty的方法都会抛出异常,同时定义一个处理异常的方法error:

  1. @ExceptionHandler(value = FileNotFoundException.class)
  2. public String error(Exception e){
  3. return "file not found exception==== " + e.getMessage();
  4. }

如果匹配到 @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就可了。

  1. @ExceptionHandler(value = Exception.class)
  2. public String error(Exception e){
  3. return " exception==== " + e.getMessage();
  4. }

②全局处理异常的2种方式:

  • a.方式1:使用ErrorPageRegistrar的接口

写一个类,实现ErrorPageRegistrar接口,实现registerErrorPages,在该方法里面,添加具体的错误处理逻辑

  1. @Component
  2. public class CommonErrorRegistry implements ErrorPageRegistrar {
  3. @Override
  4. public void registerErrorPages(ErrorPageRegistry registry) {
  5. ErrorPage e404 = new ErrorPage(HttpStatus.NOT_FOUND, "/404.html");
  6. ErrorPage e500 = new ErrorPage(INTERNAL_SERVER_ERROR, "/500.html");
  7. ErrorPage argsPage= new ErrorPage(IllegalArgumentException.class, "/args.html");
  8. registry.addErrorPages(e404, e500,argsPage);
  9. }
  10. }
  • b.方式2:@ControllerAdvice
    具体做法:

-1.写一个类,需要加上@ControllerAdvice注解
-2.写一个异常处理方法,需要加上@Exception(value=Exception.class)这个注解,在该方法上处理异常,

  1. @ControllerAdvice
  2. public class GloabalExceptinHandler {
  3. @ExceptionHandler(value = Exception.class)
  4. @ResponseBody
  5. public String errorHandler(Exception e){
  6. return "gloabal error " + e.getClass().getName()+ " =="+ e.getMessage();
  7. }
  8. @ExceptionHandler(value = NullPointerException.class)
  9. @ResponseBody
  10. public String errorHandler2(Exception e){
  11. return "gloabal error2 " + e.getClass().getName()+ " =="+ e.getMessage();
  12. }
  13. }

这2种方法都可以跳转到自定义的页面,或者抛出异常。
看下这个ErrorPage类的源码:
在这里插入图片描述
可以看到,errorpage可以通过请求响应状态码控制跳转页面,可以根据具体异常控制跳转页。

演示代码git地址:
https://github.com/hufanglei/springboot-v-study/tree/springbootweb3


以上就说了springbootweb的大体内容,基础springboot2的。关于请求方法参数,数据渲染到jsp页面和freemarker页面的配置方式,替换内置tomcat的方法,请求静态页面的设置,过滤器,监听器,servlet的2种注册方式,拦截器的自定义,异常处理的类上的处理,和全局处理的2种方式。


个人微信公号:
搜索: 怒放de每一天
不定时推送相关文章,期待和大家一起成长!!
在这里插入图片描述


发表评论

表情:
评论列表 (有 0 条评论,74人围观)

还没有评论,来说两句吧...

相关阅读

    相关 【JavaWeb】SpringBootWeb案例下篇

    文件上传,是指将本地图片、视频、音频等文件上传到服务器,供其他用户浏览或下载的过程。文件上传在项目中应用非常广泛,我们发微博、发微信朋友圈都用到了文件上传功能。前端页面三要素。