spring-web搭建

目录

1:spring-web是什么原理以及组成

2:spring-web的搭建(以普通tomcat服务器做基础)

1->环境(自己去建一个普通web项目)

2->WEB-INF的web.xml配置(程序入口)

 3->commons-loggings配置(这个log4j.properties必须放在classes下,也就是src那一层)

4->写个controller(C)

5->写个Model(M),上文的sysAdminService

a:service

b:dao

c:entity(这里不需要写建表语句,通过spring hibernate的hibernate.hbm2ddl.auto自动更新维护表)

6->写个拦截器 (这个拦截器会优先拦截所有请求,只有return true才会允许给相应controller处理)

7->写个异常处理器

3:敲黑板 

4:下一章docker

5:本章资源下载链接


先说说这篇文章看完你能学习到什么吧

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" />--><!--&lt;!&ndash; 启动 Spring MVC 的注解功能,完成请求和注解 POJO 的映射 &ndash;&gt;--><!--<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/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx.xsdhttp://www.springframework.org/schema/contexthttp://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 {@Autowiredprivate SysAdminService sysAdminService;@RequestMapping(value = "/test")@ResponseBodypublic 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 {@Autowiredprivate SysAdminDao sysAdminDao;private SimpleHibernateTemplate<SysAdmin, Integer> sysAdminDaoH;@Autowiredpublic 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 {@Autowiredprivate 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本函数.* 这个注解会生效*/@Autowiredpublic 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 {@Autowiredprivate SysAdminService adminService;/*** This implementation always returns {@code true}.*/@Overridepublic 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匹配的需要检验的方法注解MenuAuthMethod[] 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 {@Overridepublic 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:本章资源下载链接

https://download.csdn.net/download/weixin_36667844/88797420

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/657703.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Qt6入门教程 14:QToolButton

目录 一.简介 二.常用接口 1.void setMenu(QMenu * menu) 2.void setPopupMode(ToolButtonPopupMode mode) 3.void setToolButtonStyle(Qt::ToolButtonStyle style) 4.void setArrowType(Qt::ArrowType type) 5.void setDefaultAction(QAction * action) 三.实战演练 1…

k8s从私有库harbor中拉取镜像

一、前言 Docker镜像是构建应用程序的基础。然而&#xff0c;许多组织和开发团队希望保留他们的Docker镜像在私有仓库中&#xff0c;并从中拉取镜像&#xff0c;而不是从公共Docker Hub中下载。这样做的原因有很多&#xff0c;包括&#xff1a; 1. 安全性&#xff1a;私有仓库可…

C++ //练习 3.13 下列的vector对象各包含多少个元素?这些元素的值分别是多少?

C Primer&#xff08;第5版&#xff09; 练习 3.13 练习 3.13 下列的vector对象各包含多少个元素&#xff1f;这些元素的值分别是多少&#xff1f; ( a ) vector<int> v1; ( b ) vector<int> v2(10); ( c ) vector<int> v3(10, 42); ( d ) vector<in…

通过MediaStore查询image,video,arm,pdf等等文件数据

需要直接查询系统库来获取手机上的全部文件信息&#xff0c;如&#xff1a;图片&#xff0c;视频&#xff0c;音频&#xff0c;pdf文件等等。 直接上代码&#xff0c;获取文件的方法&#xff1a; SuppressLint("Range") public ArrayList<DataBean> getFiles(…

collection、ofType、select的联合用法(Mybatis实现树状结构查询)

需求 得到树结构数据也可以用lambda表达式也行&#xff0c;也可以直接循环递归也行&#xff0c;本文采用的是直接在Mybatis层得到结果&#xff0c;各有各的优势。 代码 1、实体类 Data public class CourseChapterVO implements Serializable {private static final long s…

Java 字符串 07 练习-手机号屏蔽、身份证号信息查看,游戏骂人敏感词替换

注意点&#xff1a;只有返回值才是被截取的小串&#xff0c;所以需要有一个变量去承接它&#xff1b; 自己写的代码&#xff1a; import java.util.Scanner; public class practice {public static void main(String[] args) {Scanner input new Scanner(System.in);String …

Zookeeper分布式命名服务实战

目录 分布式命名服务 分布式API目录 分布式节点的命名 分布式的ID生成器 分布式的ID生成器方案&#xff1a; 基于Zookeeper实现分布式ID生成器 基于Zookeeper实现SnowFlakeID算法 分布式命名服务 命名服务是为系统中的资源提供标识能力。ZooKeeper的命名服务主要是利用Z…

ThreadLocal作用实例

ThreadLocal ThreadLocal表示线程的“局部变量”&#xff0c;它确保每个线程的ThreadLocal变量都是各自独立的&#xff0c;它提供了一种方法来创建只能被当前线程访问的变量。这意味着如果有两个不同的线程访问同一个ThreadLocal变量&#xff0c;那么这两个线程将不能看到彼此…

【issue-halcon例程学习】lines_gauss.hdev

例程功能 代码如下 dev_close_window () read_image (Angio, angio-part) get_image_size (Angio, Width, Height) dev_open_window (0, 0, 3 * Width / 2, 3 * Height / 2, black, WindowID) dev_display (Angio) dev_set_color (blue) MaxLineWidth : 8 Contrast : 12 calc…

Java中的线程安全

关于多线程并发环境下&#xff0c;数据的安全问题。 1.为什么这个是重点&#xff1f; 以后在开发中&#xff0c;我们的项目都是运行在服务器当中&#xff0c;而服务器已经将线程的定义&#xff0c;线程对象的创建&#xff0c;线程的启动等&#xff0c;都已经实现完了。这些代码…

QT自制软键盘 最完美、最简单、支持中文输入(二)

目录 一、前言 二、本自制虚拟键盘特点 三、中文输入原理 四、组合键输入 五、键盘事件模拟 六、界面 七、代码 7.1 frmKeyBoard 头文件代码 7.2 frmKeyBoard 源文件代码 八、使用示例 九、效果 十、结语 一、前言 由于系统自带虚拟键盘不一定好用&#xff0c;也不一…

【python】合理使用copy与deepcopy

合理使用**copy**与**deepcopy**对于dict和list等数据结构的对象&#xff0c;直接赋值使用的是引用的方式。而有些情况下需要复制整个对象&#xff0c;这时可以使用copy包里的copy和deepcopy&#xff0c;这两个函数的不同之处在于后者是递归复制的。效率也不一样&#xff1a;&a…

动态设置小程序IOS底部小黑条

创建setIOSAreaMixin.js文件 import {mapState,mapMutations } from vuexexport default {computed: {...mapState("ios_area", ["globalAreaClass", isSafeAreaCalculated])},mounted() {if (!this.isSafeAreaCalculated) {this.calculateSafeAreaClass(…

牛客网-----------[NOIP2006]数列

题目描述 给定一个正整数k(3≤k≤15),把所有k的方幂及所有有限个互不相等的k的方幂之和构成一个递增的序列&#xff0c;例如&#xff0c;当k3时&#xff0c;这个序列是&#xff1a; 1&#xff0c;3&#xff0c;4&#xff0c;9&#xff0c;10&#xff0c;12&#xff0c;13&…

2024年重庆市公务员考试报名明天开始,招聘4530人!

2024年重庆公务员招录公告已出&#xff0c;招聘人数&#xff1a;4530人 ✅重庆市考重要时间节点 报名时间&#xff1a;2月1日9:00-2月6日9:00 缴费时间&#xff1a;2月8日 笔试时间&#xff1a;3月16日-17日 笔试查成绩时间&#xff1a;4月15日 面试时间&#xff1a;4月27日-2…

C++文件操作(1)

C文件操作 1.文本的写入及读取文本文件写入文本文件读取 2.二进制文件的写入及读取二进制文件写入二进制文件读取 3.小结 C也有处理文件的能力&#xff0c;其功能实现依赖文件流。文件流是C中用来处理文件输入输出的一种流类。文件流可以用于从文件中读取数据或将数据写入到文件…

《游戏-03_2D-开发》

基于《游戏-02_2D-开发》&#xff0c; 继续制作游戏&#xff1a; 首先要做的时切割人物Idle空闲状态下的动画&#xff0c; 在切割之前我们需要创建一个文件夹&#xff0c;用来存放动画控制器AnimatorContoller&#xff0c; 再创建一个人物控制器文件夹用来存放人物控制器&…

【Ubuntu 22.04.3 LTS】apt-get下载安装有关问题可能原因及解决方法

ubuntu 22.04.3 LTS unaccountably error 装啥啥没依赖 可能是用了不合适的源&#xff0c;换个就好了 Now, let’s take a look at the lsb_release output, with a special focus on the Codename, which could be a crucial piece of information. The lsb_release comm…

认识BPMN2.0

&#x1f496;专栏简介 ✔️本专栏将从Camunda(卡蒙达) 7中的关键概念到实现中国式工作流相关功能。 ✔️文章中只包含演示核心代码及测试数据&#xff0c;完整代码可查看作者的开源项目snail-camunda ✔️请给snail-camunda 点颗星吧&#x1f618; &#x1f496;说在前面 …

STM32单片机基本原理与应用(四)

直流电机驱动控制原理 1、电机正反转控制 在STM32中&#xff0c;直流电机的正反转控制主要通过改变电机输入电源的极性来实现。当电机的电压极性发生变化时&#xff0c;电机的旋转方向也会相应改变。在硬件电路中&#xff0c;可以通过继电器或晶体管等电子开关来切换电机的电源…