springboot原理实战(14)--springbootweb
文章目录
- 目录:
- 第一部分:
- 一、请求method
- 二、传递参数的3种方式
- 1.RequestParam
- 2.url方式 @PathVariable
- 3.HttpServletRequest方式
- 三、@RestController
- 四、springboot的数据渲染到jsp页面
- 1.配置文件:
- 2.加入 tomcat-embed-jasper的依赖
- 3.测试:
- 五、springboot渲染数据到freemarker页面:
- 在pom.xml里面加入依赖
- 2.配置文件修改freemarker的位置和后缀
- 3.测试:
- 六、更换web容器
- 1.排除tomcat,加入jetty的依赖
- 2.测试:
- 第二部分
- 一、请求静态资源:
- 放在webapp下 加resources.xml 可以访问到
- 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 默认必填,可以设置非必填,和默认值
:
/** * @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上加入资源
org.springframework.boot
spring-boot-maven-plugin
src/main/webapp
META-INF/resources
/
src/main/resources
true
*/
入口函数启动:
@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每一天
不定时推送相关文章,期待和大家一起成长!!
完
还没有评论,来说两句吧...