JavaWeb
此教程是为了理解 Jeecg-库存管理网站 的后端部分,只需普通的 HTTP 单次请求
如果希望制作 Chatbot(会话/即时交互),建立连接--多次交互--断开,即需要搭建 Socket 长连接(TCP/IP),建议使用 Socket.IO
推荐: SpringBoot清晰教程
工具
-
IntelliJ IDEA Ultimate 中通过 Maven 管理包:.pom文件
- 本地安装Maven后: IDEA中File--Settings--搜索maven--设置home/cfg/repo等信息
- 随后可以创建Maven项目,尝试一下IT码徒,公司会提供正版IDEA
-
Mysql 数据库运行后,可以用 Navicat 可视化管理其中的 table
-
Postman 测试 server API
概念
MVC
Model 处理数据逻辑----JavaBean
Controller 对请求选择合适的Model和View----Servlet (url)
View 用于数据展示、与用户交互----前端
规范-SSM框架
SSM = Spring + SpringMVC + MyBatis 概览
MyBatis 持久层 与数据库进行交互,增删改查
Spring 业务逻辑层 Model 应用的核心框架,管理对象及其生命周期
SpringMVC 表现层 Controller+View 处理用户界面和交互逻辑
| 层 | -- | 获得的POJO | MyBatis 项目中(见SSM教程) |
|---|---|---|---|
| Dao | 封装对数据库的操作:增删改查 | Entity:严格对应数据库表的字段 | 设置SQL语句的Mapper |
| Service | Do something | Domain/Model:综合/节选多张表的字段与信息 | Service接口 -> Impl实现类 -> Bean |
| Controller | 根据url请求参数,调用不同的 Service | View:发送给前端展示的字段 | @Controller |
注: POJO 指普通Java对象,包括私有字段、对应的 getter/setter
Cookie/SessionID/Token
假设用户登陆后,需要维持一段时间的登录状态,可有如下三种选择。
-
登录成功后,Server 向浏览器发送简单 Cookie,此后用户每次发送请求都
Request + Cookie {username:xx};随后,Server 根据 Cookie 中的用户名获取对应的登录信息- 由于 Cookie 仅存储于浏览器中,有被篡改的风险
- ...
-
登录成功后,Server 对此次登录生成 SessionID、发送给浏览器,此后用户每次发送请求都
Request + Cookie {SessionID};随后,Server 根据 Cookie 中的 SessionID 获取对应的用户和登录信息- 多台服务器的情况下,登录信息可能不能共通
-
登录成功后,JWT 加密
algorithm - userinfo - signature生成 Token 发送给浏览器,此后用户每次发送请求都带上{Authorization:token};随后,Server 进行解密、检查 signature 后决定放行
注:关于对文件/信息进行加密
keygen() -> (public_key, private_key)
encrypt(PlainT, public_key) -> Cipher //非对称加密
decrypt(Cipher, private_key) -> PlainT
sign(Msg, private_key) -> signature //对文件进行签名
varify(Msg, signature, public_key) -> OK?
encrypt(PlainT, key) -> Cipher //对称加密
decrypt(Cipher, key) -> PlainT
教程导航
- Tips
- 右键目录,选择生成class/servlet/..
- 右键 或 Alt+Insert 自动生成类的 Getter/Setter 等代码
- 右键--Project Structure--Facets--点击项目--点击标红目录进行自动创建
- 非java代码都放在resources文件夹中
黑马程序员JavaWeb基础教程
基础JavaEE,有助于了解概念和技术发展
-
JDBC API (mysql-connector-java) 是 java 与 MySQL 交互的接口,进一步可使用 Druid 连接池分配程序与数据库间的 connection
-
MyBatis 是一款持久层框架,简化了JDBC操作:将配置放在config中,SQL语句放在mapper中
mybatis-config.xml | mapper resource="UserMapper.xml"
UserMapper.xml | <select id="selectAll" ...>SQL</select>
User.java | public class User {...}
UserMapper.java | public interface UserMapper {List<User> selectAll();}
Demo.java | UserMapper mm = session.getMapper(UserMapper.class);
| List<User> uu = mm.selectAll();
可用注解代替xml,此外,MyBatis 提供SQL 语句构建器
public interface UserMapper{
@Select("select * from tbl where age = #{age}")
List<User> selectByAge(int age);
}
-
Tomcat部署web项目: 作为容器创建Servlet对象
- 打包Maven项目后部署在Tomcat中,注意:pom.xml 添加
<packaging>war</packaging>,否则默认打包.jar - 也可以集成至Idea:运行标志边上(下拉栏)--Edit Configuration--Run/Debug Configuration--ADD符号--Tomcat Server--Local--Configure--Server Tab--设置Home--Deployment Tab--ADD符号--xxx.war--OK--Apply--运行标志
- 也可以以Maven插件的方式集成至当前项目:pom.xml 添加相关依赖--Run Maven--tomcat:run
- 也可内置于springboot中
- 打包Maven项目后部署在Tomcat中,注意:pom.xml 添加
-
A Servlet is a small Java program that runs within a Web server, 由 JavaEE 提供规范接口
- Servlet在容器中运行,其生命周期由容器管理:第一次访问--加载/实例化--init()--处理请求--destroy()
- Servlet(接口)--- GenericServlet(抽象实现类)--- HttpServlet(封装HTTP协议后的实现类)
@WebServlet(urlPatterns = {"/login"})
public class Demo implements Servlet{
public void init(ServletConfig config) throws ServletException{...}
public void service(ServletRequest req, ServletResponse res){
String name = req.getParameter("name");
res.setHeader("content-type","text/html;charset=utf-8");
res.getWriter().write('<h1>Hello</h1>');
}
public void destroy(){...}
public ServletConfig getServletConfig(){...}
public String getServletInfo(){...}
...
}
开发者的自定义Servlet一般 extends HttpServlet: doGet()/doPost(),二者通用:
Map<String,String[]> map= httpReq.getParameterMap()
String[] val = httpReq.getParameterValues(String name)
String par = httpReq.getParameter(String name)
转发getRequestDispatcher v.s. 重定向sendRedirect 的实现;以及路径中何时需要加虚拟目录
Response 非纯文本情况下不能 res.getWriter().write,需要先将其转变为字节流:
FileInputStream fis = new FileInputStream('a.png');
ServletOutputStream os = httpRES.getOutputStream();
// 从File流拷贝至Servlet流
byte[] buff = new byte[1024];
int len = 0;
while ( (len = fis.read(buff))!= -1 ){
os.write(buff,0,len);
}
fis.close();
- JSP = HTML + Java,被访问时由Tomcat将其转换为servlet,用于简化开发:java代码和HTML在一个文件中,response时不用write太多东西
- 代码难以阅读,已逐渐被 Servlet + html + AJAX 取代
- EL 表达式的域
- JSTL取代JSP页面上的Java代码
黑马Spring教程 + SSM教程
-
为什么要用 Bean?IoC、DI、AOP 以降低对象间耦合度
-
记得引入xml-header部分的xmlns、xsi,以及pom中相关依赖
-
通过BeanFactory配置/创建/管理Beans,步骤
- 简单创建一个Maven项目后,配置 spring-context
- 创建 UserService 接口
- UserServiceImpl 是 UserService 的实现类(可配置为Bean)
- IDEA 右键目录 New 一个 XML Configuration File,配置
<bean id="userService" class="xx.xx.impl.UserServiceImpl">...</bean> - 如果某Bean中还需要引用另一个Bean,例如 ,
- 则
...处增加:<property name="bean2" ref="bean2"></property> - 或
autowire="byName":实现类中设定setBean2(Bean2 bean2)方法,寻找容器中name/id=bean2者,自动注入 - 或
autowire="byType":寻找容器中类型为Bean2类型者,若有重复则会报错,e.g.当Bean2接口对应两个Impl实现类,配置成两个Bean
- 则
- 如果是有参构造,例如
class XImpl的构造方法public XImpl(String argname){},则...处增加:<constructor-arg name="argname" value="123"></constructor-arg> - 总结:ref="BeanXxx", value=String/int/boolean, 如果需要注入的是ref/value的List,则
<property name="xxx"> <list> <value>aaa</value> <value>bbb</value> </list> </property>
// 创建工厂对象
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
// 读取xml
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
reader.loadBeanDefinitions("beans.xml");
// 根据id获取Bean实例对象 -- 首次调用getBean()时才将被调用的Beans实例化、初始化
UserService userService = (UserService) beanFactory.getBean("serv1");
- ApplicationContext (Spring容器) 中封装了BeanFactory,并且扩展了功能API(监听、国际化等),getBean方法
// 创建容器 -- 此时就将Beans实例化、初始化
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
UserService userService = (UserService) applicationContext.getBean("serv1"); // bean xml的优先顺序:(name1,name2)>id>class
-
设定test/dev环境
- 希望使用大标签
<beans profile="dev">....bean1234....</beans>内的Beans - 则main方法中
System.setProperty("spring.profiles.active","dev")
- 希望使用大标签
-
有时项目过大,可以吧Beans分开写进不同的xml中,然后
<import resource="classpath:aa.xml"></import>至相关<beans>大标签中 -
许多外部包提供非自定义的Beans,JDBC组件库Druid示例如下;Mybatis-SqlSessionFactory同理,其InputStream可设置为静态BeanFactory
// main函数中,Druid的正常用法
DruidDataSource dataSource = new DruidDataSource();
dataSource.setUrl("jdbc:mysql://xxx:port/xxx");
dataSource.set....
// <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
// dataSource.setXxx等改为在 <property> 标签中设置(如果是构造对象时就需要的参数,使用<constructor-arg>,例如返回Connection的DriveManager.getConnection方法)
// xml中进行以上设置后,main改为:
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
Object dataSource = applicationContext.getBean("dataSource");
// xml中 <context:component-scan base-package="com.proj"/>
@Component("beanName") //get时byName,不填则需byType
public class UserServiceImpl implements UserService {...}
- SpringMVC的使用类似Servlet:导入spring-webmvc + servlet坐标,beans config配置同上文Spring,初始化DispathcerServlet,随后即可使用(建议遵循RESTful风格),Postman测试5种类型参数的传递、Postman测试json格式参数的传递(@RequestBody)
@Controller
public class UserController{
@RequestMapping(value="/users/{}",method=RequestMethod.DELETE) // 访问/users/1 意味着输入形参id=1
@ResponseBody // 设置响应内容为当前返回值,无需解析(建议返回json格式)
public String delete(@PathVariabla Integer id){ // /users/1?name=aa&age=bb可提供name、age两个形参
return "{'val':'ok'}" //
}
@RequestMapping("/users") // /users?name=aa&age=22可提供name、age两个形参
@ResponseBody
public String test(@RequestParam("name") String userName,int age){ // 形参名一致可直接输入,但不一致则用RequestParam绑定关系
return "{'val':'ok'}" // 也可直接接收POJO对象 User{name='aa',age='22'}
} // String[] 直接接收数组 v.s. @RequestParam List<String> 给集合对象赋值
}
-
SpringBoot进一步简化了SpringMVC,并且整合了Tomcat
- IDEA 勾选 Spring Initializr---web---Spring web 初始化SpringBoot项目,只需留下pom文件和src文件夹
- New Controller,@RestController
- application.properties/.yaml
// .yaml中 lesson:abc
@RestController
@RestMapping("/ab")
public class AbController{
@Value("${lesson}") //从.yaml中获取lesson取值
private String lesson;
@GetMapping("/{id}")
public String test(@PathVariabla Integer id){
System.out.println(lesson);
return "ok";
}
}
- MyBatisPlus 进一步简化了MyBatis,使用步骤
- 生成一个SpringBoot项目:IDEA 勾选 Spring Initializr---web---Spring web,---SQL---MyBatis Framework,---SQL---MySQL Driver
- application.yml 配置数据源
- 定义数据层接口映射配置(教程所例的BaseMapper接口提供了基本CRUD操作接口)
@Mapper
public interface UserDao{
@Select("select * from user where id=#{id}")
public User getById(Long id);
}