1:spring-web是什么原理以及组成,2:spring-web的搭建(以普通tomcat服务器做基础),3:敲黑板
1:spring-web是什么原理以及组成
spring-web是spring中提供给用户搭建web服务的框架,其中的spring-webmvc是其核心部分,webmvc采用MVC架构,M是model层,V是view层,C是controller层。那我们从这三个层次去讲解这部分。首先我们用一整套访问请求来讲解原理:
1->用户请求到服务器。
用户作为使用者,是用游览器(客户端)输入网址通过域名解析访问到我们的域名主机,然后域名主机会找到相应对的发布的服务(java服务,php服务)等,我们是java服务器,部署在tomcat上,那么tomcat就会根据程序上下文(application context)或者说它里面的Server.xml找到Host节点里面的Context节点找到项目的发布目录。
2->spring web的映射请求地址到相应的controller(C)。
tomcat调用java服务的Servlet,java第一道防线就是DispatcherServlet(中央调度器)。DispatcherServlet请求handlerMapping,返回相应的执行器handler,DispatcherServlet通过HandlerAdapter调用相应的handler执行器。执行器handler根据url找到相应的处理器调用controller
3->controller(c)进行数据处理,返回数据modelAndView(M)给DispatcherServlet。
controller接下来会进行数据处理,比如调用service去保存或者查询数据,service去通过dao进行持久化数据,然后返回数据给controller,controller把数据和需要返回的url给DispatcherServlet(也就是返回modelAndView对象)
4->ViewResolve进行视图解析返回view(V)
DispatcherServlet拿到modelAndView去找ViewResolver解析视图,返回view给DispatcherServlet。
5->DispatcherServlet响应数据,视图渲染
DispatcherServlet拿到view数据,返回给tomcat,tomcat相应游览器请求,并让其渲染视图。
这就是一整套请求和渲染流程,采用mvc架构
2:spring-web的搭建(以普通tomcat服务器做基础)
1->环境(自己去建一个普通web项目)
**【jdk8】,【spring-web5.2.3】,【spring-webmvc5.2.3】,【intellj idea2018】**
2->WEB-INF的web.xml配置(程序入口)
a:配置DispatcherServlet(中央调度器)
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" version="4.0"> <servlet> <servlet-name>dispatcher</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <!-- 这里有的地方叫dispatcher-servlet.xml,都一样--> <param-value>/WEB-INF/spring-mvc.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>dispatcher</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> </web-app>
b:spring-mvc.xml配置HandlerMapping和HandlerAdapter和ViewResolver和Controller以及bean的扫描路径,这里多配置了个访问拦截器。各位可以针对访问权限进行拦截
<?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:p="http://www.springframework.org/schema/p" 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-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd" default-lazy-init="true"> <!--mvc注解配置,方便我们使用@Autowired等注解--> <context:annotation-config /> <!--自动注册注解驱动 包扣handlerMapping和handlerAdapter的注册--> <mvc:annotation-driven /> <!--使Spring支持自动检测组件,如注解的Controller,这个注解包含了上面annotation-config--> <context:component-scan base-package="com.wanzi.controller" /> <context:property-placeholder location="WEB-INF/config.properties"/> <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver" p:prefix="/" p:suffix=".jsp" /> <!-- spring3.1之前用的是DefaultAnnotationHandlerMapping和AnnotationMethodHandlerAdapter,可以自动扫描bean上面有@Controller--> <!--<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" />--> <!--<!– 启动 Spring MVC 的注解功能,完成请求和注解 POJO 的映射 –>--> <!--<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">--> <!--<property name="messageConverters">--> <!--<list>--> <!--<bean class="org.springframework.http.converter.StringHttpMessageConverter"></bean>--> <!--</list>--> <!--</property>--> <!--</bean>--> <!-- spring3.1之后用的是RequestMappingHandlerMapping和RequestMappingHandlerAdapter,可以自动扫描bean上面有@Controller--> <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping" /> <!-- 启动 Spring MVC 的注解功能,完成请求和注解 POJO 的映射 --> <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"> <property name="messageConverters"> <list> <bean class="org.springframework.http.converter.StringHttpMessageConverter"></bean> </list> </property> </bean> <!-- 异常处理handler --> <bean id="exceptionHandler" class="com.wanzi.handler.ExceptionHandler" /> <!-- 文件上传设置 --> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <property name="maxUploadSize"> <value>104857600</value> </property> </bean> <!--静态资源--> <mvc:resources mapping="/script/plugins/**" location="/script/plugins/"/> <!-- 拦截器配置 --> <mvc:interceptors> <!-- 系统端校验 --> <mvc:interceptor> <mvc:mapping path="/**" /> <bean id="sysAuthInterceptor" class="com.wanzi.interceptor.SysAuthInterceptor"></bean> </mvc:interceptor> </mvc:interceptors> </beans>
c:配置程序上下文
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" version="4.0"> <context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/applicationContext.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <servlet> <servlet-name>dispatcher</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/spring-mvc.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>dispatcher</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> </web-app>
d:applicationContext.xml配置数据库连接池和持久层框架以及事务
<?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:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <context:component-scan base-package="com.wanzi" /> <context:property-placeholder location="/WEB-INF/config.properties"/> <bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver"/> <property name="url" value="${mysql_url}"/> <property name="username" value="${mysql_username}"/> <property name="password" value="${mysql_password}"/> <property name="validationQuery" value="select database()"/> </bean> <!-- 配置数据库,这里选用hibernate框架连接,这个包再orm的hibernate中--> <bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean"> <property name="dataSource" ref="dataSource"/> <property name="hibernateProperties"> <props> <prop key="hibernate.show_sql">true</prop> <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop> <!--千万别配置这个,这个属性不生效 <prop key="hbm2ddl.auto">create</prop> --> <!--这里自动更新和创建表--> <prop key="hibernate.hbm2ddl.auto">update</prop> </props> </property> <property name="packagesToScan" value="com.wanzi.entity"/> </bean> <!-- 这里注入hibernateTemplate,给传统的dao作为参数使用,可以使用@Repository中@Autowired注入--> <bean id="hibernateTemplate" class="org.springframework.orm.hibernate5.HibernateTemplate"> <property name="sessionFactory" ref="sessionFactory"></property> </bean> <bean id="transactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory"/> </bean> <tx:annotation-driven transaction-manager="transactionManager"/> </beans>
e:config.properties的数据
mysql_url=jdbc:mysql://127.0.0.1:3306/spring-web?characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&tinyInt1isBit=false&useOldAliasMetadataBehavior=true mysql_username=root mysql_password=
3->commons-loggings配置(这个log4j.properties必须放在classes下,也就是src那一层)
log4j.rootLogger=info,A #系统输出 log4j.appender.A=org.apache.log4j.ConsoleAppender log4j.appender.A.Target=System.out log4j.appender.A.layout=org.apache.log4j.PatternLayout log4j.appender.A.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} [%t:%p] %c %m%n
4->写个controller(C)
package com.wanzi.controller.sys; import com.wanzi.annotation.UnAuth; import com.wanzi.entity.SysAdmin; import com.wanzi.service.SysAdminService; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; @Controller @UnAuth @Slf4j @RequestMapping("/sys/test") public class TestController { @Autowired private SysAdminService sysAdminService; @RequestMapping(value = "/test") @ResponseBody public Object test(){ log.error("权限检验通过"); return "test"; } @RequestMapping(value = "/index") public String index(Model model){ log.error("权限检验通过"); SysAdmin sysAdmin = sysAdminService.getSysAdminById(1); model.addAttribute("test","我是测试传参"); return "/sys/test/index"; } }
5->写个Model(M),上文的sysAdminService
a:service
package com.wanzi.service; import com.wanzi.dao.SysAdminDao; import com.wanzi.entity.SysAdmin; import com.wanzi.template.SimpleHibernateTemplate; import org.hibernate.SessionFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; /** * 系统管理员service */ @Service @Transactional public class SysAdminService { @Autowired private SysAdminDao sysAdminDao; private SimpleHibernateTemplate<SysAdmin, Integer> sysAdminDaoH; @Autowired public void setSessionFactory (SessionFactory sessionFactory) { sysAdminDaoH = new SimpleHibernateTemplate<>(sessionFactory, SysAdmin.class); } /** * 根据id获取系统管理员信息 * * @param id * void */ public SysAdmin getSysAdminById (int id) { return sysAdminDao.getSysAdminById(id); // return this.sysAdminDaoH.get(id); } }
b:dao
这里dao我用了两种方法,一种是用系统HibernateTemplate实现增删改查,一种是用Session实现增删改查。
b->1:HibernateTemplate方式
上面的applicationContext.xml中有配置名字为hibernateTemplate的bean,传统方式就是操作这个类实现增删改查,下面是一个例子Dao
package com.wanzi.dao; import com.wanzi.entity.SysAdmin; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.orm.hibernate5.HibernateTemplate; import org.springframework.stereotype.Repository; @Repository public class SysAdminDao { @Autowired private HibernateTemplate hibernateTemplate; public SysAdmin getSysAdminById (int id) { return hibernateTemplate.get(SysAdmin.class,id); } }
b->2:灵活的Session
上文中service操作的SimpleHibernateTemplate是自定义的dao
package com.wanzi.template; import java.io.Serializable; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; /** R * Hibernate的范型基类. * * 可以在service类中直接创建使用.也可以继承出DAO子类,在多个Service类中共享DAO操作. * 参考Spring2.5自带的Petlinc例子,取消了HibernateTemplate. * 通过Hibernate的sessionFactory.getCurrentSession()获得session,直接使用Hibernate原生API. * * @param <T> DAO操作的对象类型 * @param <PK> 主键类型 */ public class SimpleHibernateTemplate<T, PK extends Serializable> { protected SessionFactory sessionFactory; protected Class<T> entityClass; public SimpleHibernateTemplate(SessionFactory sessionFactory, Class<T> entityClass) { this.sessionFactory = sessionFactory; this.entityClass = entityClass; } /** * 采用@Autowired按类型注入SessionFactory,当有多个SesionFactory的时候Override本函数. * 这个注解会生效 */ @Autowired public void setSessionFactory(final SessionFactory sessionFactory) { this.sessionFactory = sessionFactory; } public Session getSession() { return sessionFactory.getCurrentSession(); } /** * 按id获取对象. */ public T get(final PK id) { return (T) getSession().get(entityClass, id); } }
c:entity(这里不需要写建表语句,通过spring hibernate的hibernate.hbm2ddl.auto自动更新维护表)
package com.wanzi.entity; import lombok.Data; import java.util.Date; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Table; /** * table : sys_admin # 系统管理员数据表 * * @author zwm */ @Data @Table(name = "sys_admin") @Entity public class SysAdmin { /** * 管理员状态:0、停用 */ public static final int STATUS_DISABLE = 0; /** * 管理员状态:1、启用 */ public static final int STATUS_ENABLE = 1; @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private int id; @Column(name = "name") private String name; @Column(name = "password") private String password; @Column(name = "md5_password") private String md5Password; /** * 使用者 */ @Column(name = "real_name") private String realName; @Column(name = "status") private int status; @Column(name = "phone_num") private String phoneNum; @Column(name = "remark") private String remark; @Column(name = "last_login_time") private Date lastLoginTime; @Column(name = "last_login_ip") private String lastLoginIp; }
d:扩展知识
d->1:和数据库mysql相连,java采用线程池,现如今java有很多好用线程池,本例子采用dbcp2
,在applicationContext.xml中有配置dataSource,其他的数据源还有:
Apache Commons DBCP:Apache Commons DBCP(数据库连接池)是Apache软件基金会的一个项目,提供了一个稳定和可靠的连接池。它是许多Java应用程序的首选选择。
HikariCP:HikariCP是一个轻量级、高性能的数据库连接池,被广泛认为是目前性能最好的连接池之一。它专注于快速的连接获取和释放,适用于高并发的应用程序。
C3P0:C3P0是一个开源的数据库连接池,具有许多配置选项,可用于调整连接池的行为。它是一种稳定的连接池,被许多Java应用程序使用。
Tomcat JDBC Pool:Tomcat JDBC Pool是Apache Tomcat项目的一部分,提供了一个性能良好的连接池。它设计用于与Tomcat集成,但也可以作为独立的连接池使用。
H2 Database:H2 Database是一个嵌入式数据库,它包含了一个内置的连接池,适用于小型应用程序和测试用例。
Druid:Druid是一个开源的数据库连接池,具有监控和统计功能,可以帮助开发人员分析数据库连接的使用情况和性能。Bitronix Transaction Manager:Bitronix是一个支持分布式事务的连接池和事务管理器,适用于需要强大事务支持的应用程序。
二、当讨论连接词(连接池)时,可以通过生活中的一个例子来形象地理解它们的区别:
例子:自来水供应Apache Commons DBCP 可以类比为一个城市自来水公司,它负责向一座城市供水。这个水公司(连接池)管理着水的分配和流动,确保城市里的每户家庭都可以获得他们所需的水(数据库连接)。虽然它提供了稳定和可靠的供水服务,但它的运作可能不一定是最高效的,因为它可能需要一些时间来响应不同地区的需求。
HikariCP 就像是一家高效的自来水公司,它专注于提供最快速的自来水供应。它的供水管道(连接池)设计得非常流畅,可以迅速响应城市中不同区域的需求,确保每家每户都能够获得所需的水。这家自来水公司以其高性能和响应速度而著称。
C3P0 可以比作另一家自来水公司,它提供了许多不同的自来水供应计划,可以根据客户的需求进行定制。这家公司提供了灵活的供水方案,允许客户根据他们的特定需求来调整水的流量和质量。
Tomcat JDBC Pool 好像是一个城市自来水部门的子部门,专门为城市的一座公共建筑提供自来水服务。虽然它与整个城市的自来水系统相互关联,但它也可以独立运行,提供高效的供水服务。
H2 Database 就像是一个小村庄的自来水泵站,它供应水给村里的居民。虽然规模较小,但它是自足的,提供了足够的水供应来满足小村庄的需求。Druid 就像是一个有水质检测设备的自来水公司,它不仅提供水供应,还监控水的质量,并提供统计数据以帮助客户了解他们的水消耗情况。
d->2: 事务
@Transactional注解是Spring框架中用于声明式事务管理的关键注解,这个方法可以作用于类和方法,作用于类是整个类都开启该方法,作用于方法的话,该方法会被归纳到事务管理,事务管理有以下几个特性原子性,一致性,隔离性,持久性。原子性表示一个事务里所有操作要么全部成功,要么全部失败,因为最后都是事务管理统一提交的。一致性表示事务提交前后数据库状态一致。隔离性表示多个事务提交是并行,互不影响。持久性表示事务一旦提交修改数据会永久保存。那么对于事务用户有哪些要注意的呢,第一事务不能作用于非public的方法,第二事务注解@Transactional不能被作用于多个方法调用,也就是外部没有这个注解,调用有这个注解的方法,那么事务是无法开启,第三方法开启了事务,但是你自己捕捉了异常,那么事务就不会被异常回滚.
6->写个拦截器 (这个拦截器会优先拦截所有请求,只有return true才会允许给相应controller处理)
package com.wanzi.interceptor; import java.lang.reflect.Method; import com.wanzi.annotation.MenuAuth; import com.wanzi.annotation.UnAuth; import com.wanzi.bean.SysLoginAdmin; import com.wanzi.entity.SysAdmin; import com.wanzi.service.SysAdminService; import com.wanzi.util.WebUtils; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.method.HandlerMethod; import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * 系统端权限登录校验 */ @Slf4j public class SysAuthInterceptor extends HandlerInterceptorAdapter { @Autowired private SysAdminService adminService; /** * This implementation always returns {@code true}. */ @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { MenuAuth menuAuth = null; log.error("后端权限开始判断"); HandlerMethod handlerMethod = (HandlerMethod) handler; Class clasz = handlerMethod.getBean().getClass(); //不需要检验授权的可以跳过 if (clasz.isAnnotationPresent(UnAuth.class)) { return true; } //通过匹配找到url匹配的需要检验的方法注解MenuAuth Method[] methods = clasz.getMethods(); for (Method method : methods) { if (method.isAnnotationPresent(RequestMapping.class)) { if (method.isAnnotationPresent(UnAuth.class)) { RequestMapping mapping = method.getAnnotation(RequestMapping.class); for (String str : mapping.path()) { if (request.getRequestURI().indexOf(str) != -1) { return true; } } } else if (method.isAnnotationPresent(MenuAuth.class)) { // 菜单校验获取菜单 RequestMapping mapping = method.getAnnotation(RequestMapping.class); for (String str : mapping.path()) { if (request.getRequestURI().indexOf(str) != -1) { menuAuth = method.getAnnotation(MenuAuth.class); break; } } if (menuAuth == null) { for (String str : mapping.value()) { if (request.getRequestURI().indexOf(str) != -1) { menuAuth = method.getAnnotation(MenuAuth.class); break; } } } if (menuAuth != null) { break; } } } } log.error("进入权限判断"); SysLoginAdmin loginAdmin = WebUtils.getSysLoginAdmin(); if (loginAdmin != null) { SysAdmin sysAdmin = adminService.getSysAdminById(loginAdmin.getId()); if (sysAdmin != null) { if (sysAdmin.getStatus() == SysAdmin.STATUS_DISABLE) { throw new Exception("账号已停用,请联系管理员"); } if (menuAuth != null && !loginAdmin.checkMenuAuth(request.getRequestURI(), menuAuth)) { throw new Exception("无访问权限"); } return true; } throw new Exception("账号不存在,请重新登录"); } throw new Exception("账号未登录,请重新登录"); } }
7->写个异常处理器
package com.wanzi.handler; import java.util.HashMap; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import lombok.extern.slf4j.Slf4j; import org.springframework.web.servlet.HandlerExceptionResolver; import org.springframework.web.servlet.ModelAndView; /** * 异常处理 */ @Slf4j public class ExceptionHandler implements HandlerExceptionResolver { @Override public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { try { Map<String, Object> model = new HashMap<String, Object>(); model.put("exception", ex); model.put("uri", request.getRequestURI()); // ajax处理数据 if (isAjaxRequest(request)) { return null; } // 其他处理跳转统一异常页面 if(request.getRequestURI().startsWith("/m")){ return new ModelAndView("exception/error_mobile", model); } return new ModelAndView("exception/error", model); } catch (Exception e) { log.error(e.getMessage(),e); } return null; } /** * 是否ajax请求 */ public static boolean isAjaxRequest(HttpServletRequest request) { return request.getHeader("x-requested-with") != null && request.getHeader("x-requested-with").trim().toLowerCase().equals("xmlhttprequest"); } }
3:敲黑板
1:上文entity的SysAdmin为什么没有get和set方法,用了什么技术吗?
答:没错,上文采用了lombok插件,这个插件会在编译代码时候根据@Data等注解自动生成相应的代码。
2:为什么上文的@Slf4j注解,然后就可以直接使用了log?
答:因为@Slf4j也是lombok的注解,也是在编译期间会自动生成Log log = LogFactory.getLog("");所以下文可以直接用log变量,但是你要使用这个log,还需要配置日志文件,本文用的普通的log4j,最新的有log4j2和logback。我的配置文件是log4j.properties,commons-logging要求我们把日志文件放在classes下,也就是src的根目录下。
3:上文controller的Model对象,调用model.addAttribute("test",sysAdmin.getName());是啥意思?
答:这个是controller层向DispatcherServlet传参的一种方式。DispatcherServlet会拿着参数去视图解析器生成view。
4:上文的@ResponseBody是干嘛用的?
答:@ResponseBody 表示该方法的返回结果直接写入 HTTP response body中,一般在异步获取数据时使用【也就是AJAX】。
5:restful风格开发是什么?
答:这是套web开发的风格方案,我们传统的请求请求传参无外乎是?id=1这种通过进行请求,不管delete还是post还是get。但是restful不一样,REST 风格提倡 URL 地址使用统一的风格设计,从前到后各个单词使用斜杠分开,不使用问号键值对方 式携带请求参数,而是将要发送给服务器的数据作为 URL 地址的一部分,以保证整体风格的一致性。如【删除id=1,是delete请求,user/1】【保存id=1,是post请求,user/1】【更新id=1,是put请求,user/1】【查询id=1,是get请求,user/1】,而是都是通用的user?id=1这样子
6:hibernate的hbm2ddl.auto这个参数是会根据entity自动生成和更新数据库建表语句吗?
答:对的,但是前面你要设置value是update或者create。
7:上面controller的index方法的return "/sys/test/index";是干嘛的?
答:这个是返回view的相对地址给DispacherServlet,上面用model传参了,这里返回view。你可以理解成两个相对应就是modelAndView。
8:关于tomcat的知识可以给我们讲讲吗?
答:我给你们讲讲我遇到的一些tomcat的常见问题吧
a->intelljidea启动tomcat,但是控制台的output输出乱码怎么解决?
这个只要在启动的tomcat参数加个VM options的参数-Dfile.encoding=UTF-8
b->intelljidea启动tomcat服务器后,需要带项目名才能访问服务器,例如localhost/spring-web/test这样,那怎么直接把项目设置成根目录,而不是通过项目名访问?
这个的话,如果是在idea启动的项目,只要改下要启动的tomcat的deployment下面的application context为/就行。如果是在正式环境,需要去改动tomcat目录下的server.xml或者context.xml的Host下的context
4:下一章docker
5:本章资源下载链接
版权归原作者 明夕何夕帅 所有, 如有侵权,请联系我们删除。