目录 start
目录 end
|2018-05-26| 码云 | CSDN | OSChina
统一使用一个Servlet 进行请求的收发, 通过配置的URL对应的方法, 进行调用, 然后返回视图解析器进行渲染
如果引入了别的模板引擎就不需要配置解析器,不然就要配
也就是Maven的Web结构,甚至是Eclipse那样的DynamicWeb项目结构, 参考 博客
<properties>
<spring.version>4.3.9.RELEASE</spring.version>
</properties>
......
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- 如果使用JSP作为视图层,还需 -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
compile('org.springframework:spring-web:4.3.9.RELEASE')
compile('org.springframework:spring-webmvc:4.3.9.RELEASE')
<servlet>
<servlet-name>mysql</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet-mapping>
<servlet-name>mysql</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.sprinControllergframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!--启用spring的一些annotation -->
<context:annotation-config/>
<!-- 自动扫描该包,使SpringMVC认为包下用了@controller注解的类是控制器 -->
<context:component-scan base-package="com.test.controller">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
<!--HandlerMapping 无需配置,springmvc可以默认启动-->
<!--静态资源映射-->
<!--本项目把静态资源放在了WEB-INF的statics目录下,资源映射如下-->
<!--<mvc:resources mapping="/css/**" location="/WEB-INF/statics/css/"/>-->
<!--<mvc:resources mapping="/js/**" location="/WEB-INF/statics/js/"/>-->
<!--<mvc:resources mapping="/image/**" location="/WEB-INF/statics/image/"/>-->
<!--但是项目部署到linux下发现WEB-INF的静态资源会出现无法解析的情况,但是本地tomcat访问正常,因此建议还是直接把静态资源放在webapp的statics下,映射配置如下-->
<!--<mvc:resources mapping="/css/**" location="/statics/css/"/>-->
<!--<mvc:resources mapping="/js/**" location="/statics/js/"/>-->
<!--<mvc:resources mapping="/image/**" location="/statics/images/"/>-->
<!-- 配置注解驱动 可以将request参数与绑定到controller参数上 -->
<mvc:annotation-driven/>
<!-- 对模型视图名称的解析,即在模型视图名称添加前后缀(如果最后一个还是表示文件夹,则最后的斜杠不要漏了) 使用JSP-->
<!-- 默认的视图解析器 在上边的解析错误时使用 (默认使用html)- -->
<!--<bean id="defaultViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">-->
<!--<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>-->
<!--<property name="prefix" value="/WEB-INF/views/"/><!–设置JSP文件的目录位置–>-->
<!--<property name="suffix" value=".jsp"/>-->
<!--</bean>-->
<!-- springmvc文件上传需要配置的节点-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="20971500"/>
<property name="defaultEncoding" value="UTF-8"/>
<property name="resolveLazily" value="true"/>
</bean>
</beans>
public class ExceptionHandler implements HandlerExceptionResolver {
@Override
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
Map<String, Object> model = new HashMap<>();
model.put("ex", ex);
ex.printStackTrace();//打印异常信息
// 根据不同错误转向不同页面
if (ex instanceof CSRFException) {//受到csrf攻击
return new ModelAndView("/errorPage/error", model);
}
if (ex instanceof BusinessException) {//业务逻辑处理出错
return new ModelAndView("errorPage/businessError", model);
} else if (ex instanceof ParameterException) {//参数处理出错。
return new ModelAndView("errorPage/parameterError", model);
} else { //其他数据类型错误
return new ModelAndView("errorPage/error", model);
}
return new ModelAndView("error", model);
}
}
但如果是前后端分离的话, 就只能统一处理异常然后然后对应的错误码和提示信息了 参考博客 ResponseBody方案
// 自定义错误页面 需要放在静态资源下面
@Bean
public EmbeddedServletContainerCustomizer containerCustomizer() {
return (container -> {
ErrorPage error401Page = new ErrorPage(HttpStatus.FORBIDDEN, "/500.html");
ErrorPage error404Page = new ErrorPage(HttpStatus.NOT_FOUND, "/404.html");
ErrorPage error500Page = new ErrorPage(HttpStatus.INTERNAL_SERVER_ERROR, "/500.html");
container.addErrorPages(error401Page, error404Page, error500Page);
});
}
参考博客
但是奇怪的是某些方法用第二种正常,有些还是要用第一种
@GetMapping(value = "/target/all", produces = "application/json; charset=utf-8")
</mvc:annotation-driven>
只能有一个,要将上面的覆盖掉 <mvc:annotation-driven>
<mvc:message-converters>
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<!-- 如果是前后端使用JSON作为主要数据交换格式就把JSON列为第一个, 否则就会被认为是Text -->
<value>application/json; charset=UTF-8</value>
<value>text/plain; charset=UTF-8</value>
<value>text/html; charset=UTF-8</value>
</list>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
包 com.test.controller 下创建一个类
@RestController
@RequestMapping("/hi")
public class Hi {
@RequestMapping("/hi")
public String hi(){
return "Hi";
}
}
在Springboot框架中,static templates 文件夹下分别代表了tomcat管理的静态文件和MVC负责跳转的HTML文件或JSP文件 在static中对于路径的使用一定要带上应用路径,而在templates中就只要写相对路径即可
定义拦截器类
public class MythInterceptor extends HandlerInterceptorAdapter{
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
Long startTime = System.currentTimeMillis();
request.setAttribute("startTime",startTime);
return true;// true就继续跳转,false就停止
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
long startTime = (Long)request.getAttribute("startTime");
request.removeAttribute("startTime");
Long endTime = System.currentTimeMillis();
log.info(request.getRequestURL()+"发起请求耗时:[ "+ (endTime - startTime) +" ms]");
}
}
配置MVC的配置类
@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter{
//自定义拦截器bean
@Bean
public MythInterceptor mythInterceptor(){
return new MythInterceptor();
}
//注册拦截器
@Override
public void addInterceptors(InterceptorRegistry registry) {
//拦截器的URL正则
registry.addInterceptor(mythInterceptor()).addPathPatterns("/**");
super.addInterceptors(registry);
}
}
URL 中带了 jsessionid 参数,导致页面各种问题
一种原因:禁用cookie导致的
最终解决: chrome中在设置里清除localhost的所有cookie和缓存
ModelAndView中的addObject 的值能用js获取到么