学习笔记:
Springboot默认支持模板引擎,不支持jsp,当然,也建议大家都是用模板(Freemaker、Thymeleaf 、 Velocity等),jsp只能将项目打成war包才能使用,而且以后的趋势是前后端分离。
第一步:引入依赖
<!-- servlet 依赖包 --> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> </dependency> <!-- JSTL (JSP standard Tag Library) JSP 标准标签库 --> <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> </dependency> <!-- 对jsp的支持 --> <dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-jasper</artifactId> </dependency>
第二步:在application.properties文件中添加前缀和后缀配置
#页面默认前缀目录 spring.mvc.view.prefix=/WEB-INF/jsp/ #页面默认后缀目录 spring.mvc.view.suffix=.jsp
第三步:编写控制层
@Controller public class LoginController { @RequestMapping("login") public String login(@RequestParam("password") String password,@RequestParam("password2") String password2){ if (StringUtils.equalsIgnoreCase(password,password2)){ return "/success"; } return "/error"; } }
第四步:编写jsp页面(代码很简单,仅限于模拟)
<%@ page contentType="text/html;charset=UTF-8"%> <html> <head> <title>My first Spring boot web demo</title> </head> <body> <h2>success</h2> </body> </html>
<%@ page contentType="text/html;charset=UTF-8"%> <html> <head> <title>My first Spring boot web demo</title> </head> <body> <h2>Error</h2> </body> </html>
第五步:测试
http://127.0.0.1:8080/login?password=123456&password2=1234561
http://127.0.0.1:8080/login?password=123456&password2=123456
到这里,springboot中集成jsp功能就结束了。但是我在测试集成的时候遇到了一个问题,就是如果控制层这样写
@Controller public class LoginController { @RequestMapping("login") public String login(@RequestParam("password") String password,@RequestParam("password2") String password2){ if (StringUtils.equalsIgnoreCase(password,password2)){ return "success"; } return "error";// 注意:这里没有加 / } }
返回error页面时,没有加/,就会报错,错误如下
在springboot中,有一个类BasicErrorController,用于同一处理全局异常,当页面发生异常的时候回自动将请求转发到/error页面,这是springboot默认提供的一个映射。查看源码,
@RequestMapping("${server.error.path:${error.path:/error}}")
@RequestMapping(produces = "text/html") public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response) { HttpStatus status = getStatus(request); Map<String, Object> model = Collections.unmodifiableMap(getErrorAttributes( request, isIncludeStackTrace(request, MediaType.TEXT_HTML))); response.setStatus(status.value()); ModelAndView modelAndView = resolveErrorView(request, response, status, model); return (modelAndView != null ? modelAndView : new ModelAndView("error", model)); }在这里找到了原因,因为springboot默认了一个视图error。。。但是我依然不明白返回/error就能找到我自己的jsp,返回error就找它的
这个类里根据自动配置类ErrorMvcAutoConfiguration中
@Bean @ConditionalOnMissingBean(value = ErrorController.class, search = SearchStrategy.CURRENT) public BasicErrorController basicErrorController(ErrorAttributes errorAttributes) { return new BasicErrorController(errorAttributes, this.serverProperties.getError(), this.errorViewResolvers); }
上面这段代码意思就是如果没有定义ErrorController时,这段代码生效,换言之,如果我们自定义了ErrorController这段代码,这段代码就不会自动配置了。一般来说,我们都需要定制化返回的错误信息,这个时候就需要重写BasicErrorController,继承重写error和errorHtml方法即可。
@Controller public class MyErrorController extends BasicErrorController { // public MyErrorController(ErrorAttributes errorAttributes, ErrorProperties errorProperties) { // super(errorAttributes, errorProperties); // } public MyErrorController(ServerProperties serverProperties) { super(new DefaultErrorAttributes(), serverProperties.getError()); } /** * 改写默认返回的HTML * * @param request * @param response * @return */ @Override public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response) { // 请求状态 HttpStatus status = getStatus(request); Map<String, Object> model = Collections.unmodifiableMap(getErrorAttributes( request, isIncludeStackTrace(request, MediaType.TEXT_HTML))); response.setStatus(status.value()); ModelAndView modelAndView = resolveErrorView(request, response, status, model); //改写默认错误视图 return (modelAndView != null ? modelAndView : new ModelAndView("error", model)); } /** * 改写默认返回的json * * @param request * @return */ @Override public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) { HttpStatus status = getStatus(request); Map<String, Object> map = new HashMap<>(); map.put("message", "哦豁,出现了错误,请稍后重试"); map.put("status", false); return new ResponseEntity<>(map, status); } }
上面只是改变了返回的内容而已,但是怎么改变返回的不是默认的error处理呢
第一种办法:
在application.properties中添加
#server.error.path=/WEB-INF/jsp/error.jsp
第二种办法
指定错误页面来改写默认的错误页面,在或者在自定义的Controller上修改映射和produces指定映射地址
@RequestMapping("${server.error.path:${error.path:/myerror}}")
这两种办法一样的
但是对于error和/error依然困惑着,以后希望有人能够解答下。
----------------------------------------------------------------------------------------------------------------------
此外,对于全局异常处理,springboot也提供了@ControllerAdvice注解
@ControllerAdvice @ResponseBody public class GlobalExceptionHandler { private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class); /** * 全局异常处理 * * @param e RuntimeException * @param response HttpServletResponse * @return error JSONResult */ @ExceptionHandler(RuntimeException.class) public JSONResult globalException(RuntimeException e, HttpServletResponse response) { logger.error(e.getMessage(), e); return ResultUtil.error(ResultCode.FAIL.getCode(), "操作失败"); } /** * 非法登录异常处理 * @param e * @param response * @return */ @ExceptionHandler(IllegalAccessException.class) public JSONResult illegalAccessException(IllegalAccessException e, HttpServletResponse response) { logger.error(e.getMessage(), e); return ResultUtil.error(ResultCode.NO_VISIT_RIGHT.getCode(), e.getMessage()); } }
可以监测所有的RuntimeException,也可以自定义异常如IllegalAccessException
/** * 非法登录异常 */ public class IllegalAccessException extends RuntimeException { public IllegalAccessException() { } public IllegalAccessException(String message) { super(message); } }
@ControllerAdvice可以设置参数,监测某些路径下的控制器,也可以指定特定控制器类型等。
也可以自定义AOP拦截处理异常。